Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/* 80x86/cproc.c */
32
 
33
/**********************************************************************
34
$Author: release $
35
$Date: 1998/03/16 11:25:21 $
36
$Revision: 1.4 $
37
$Log: cproc.c,v $
38
 * Revision 1.4  1998/03/16  11:25:21  release
39
 * Modifications prior to version 4.1.2.
40
 *
41
 * Revision 1.3  1998/03/15  16:00:14  pwe
42
 * regtrack dwarf dagnostics added
43
 *
44
 * Revision 1.2  1998/03/11  11:03:03  pwe
45
 * DWARF optimisation info
46
 *
47
 * Revision 1.1.1.1  1998/01/17  15:55:51  release
48
 * First version to be checked into rolling release.
49
 *
50
 * Revision 1.31  1997/10/23  09:36:56  pwe
51
 * extra_diags
52
 *
53
 * Revision 1.30  1997/10/10  18:25:03  pwe
54
 * prep ANDF-DE revision
55
 *
56
 * Revision 1.29  1997/08/23  13:45:28  pwe
57
 * initial ANDF-DE
58
 *
59
 * Revision 1.28  1997/05/02  11:04:47  pwe
60
 * minor dwarf2 corrections
61
 *
62
 * Revision 1.27  1997/04/17  11:55:43  pwe
63
 * dwarf2 improvements
64
 *
65
 * Revision 1.26  1997/04/02  10:33:10  pwe
66
 * diagnose pl_tests
67
 *
68
 * Revision 1.25  1997/03/24  11:15:08  pwe
69
 * dwarf2 option/default
70
 *
71
 * Revision 1.24  1997/03/20  16:23:35  pwe
72
 * dwarf2
73
 *
74
 * Revision 1.23  1996/12/13  14:39:19  pwe
75
 * prep NEWDIAGS
76
 *
77
 * Revision 1.22  1996/11/08  16:19:02  pwe
78
 * check_stack to check before modifying stack
79
 *
80
 * Revision 1.21  1996/10/31  12:02:33  pwe
81
 * correct env_offset used in constant evaluation
82
 *
83
 * Revision 1.20  1996/10/29  13:50:51  pwe
84
 * correct space for patched instructions
85
 *
86
 * Revision 1.19  1996/10/08  07:58:56  pwe
87
 * revised correction to env_offset v id out_of_line
88
 *
89
 * Revision 1.18  1996/10/07  13:31:06  pwe
90
 * push make_value, and env_offset v id out_of_line
91
 *
92
 * Revision 1.17  1996/07/31  12:56:53  pwe
93
 * restore alloca stack after longjump
94
 *
95
 * Revision 1.16  1996/07/09  09:43:35  pwe
96
 * caller env_offset if callees present, and tidy
97
 *
98
 * Revision 1.15  1996/02/08  13:45:12  pwe
99
 * Linux elf v aout option
100
 *
101
 * Revision 1.14  1996/01/10  09:19:03  pwe
102
 * profile const & envoffset correction
103
 *
104
 * Revision 1.13  1996/01/05  16:25:22  pwe
105
 * env_size and env_offset within constant expressions
106
 *
107
 * Revision 1.12  1995/12/22  09:34:27  pwe
108
 * solaris diags for stack objects
109
 *
110
 * Revision 1.11  1995/12/21  13:47:02  pwe
111
 * trap for missing pops (sco problem)
112
 *
113
 * Revision 1.10  1995/10/13  15:19:47  pwe
114
 * solaris PIC and linux tcc
115
 *
116
 * Revision 1.9  1995/10/09  15:14:09  pwe
117
 * dynamic initialisation etc
118
 *
119
 * Revision 1.8  1995/09/05  16:24:45  pwe
120
 * specials and exception changes
121
 *
122
 * Revision 1.7  1995/08/30  16:06:24  pwe
123
 * prepare exception trapping
124
 *
125
 * Revision 1.6  1995/08/23  09:42:39  pwe
126
 * track fpu control word for trap etc
127
 *
128
 * Revision 1.5  1995/08/14  13:53:30  pwe
129
 * several corrections, tail calls and error jumps
130
 *
131
 * Revision 1.4  1995/08/04  08:29:09  pwe
132
 * 4.0 general procs implemented
133
 *
134
 * Revision 1.3  1995/04/13  11:38:57  pwe
135
 * odd_bits clean for proc ending with bottom
136
 *
137
 * Revision 1.2  1995/01/30  12:56:04  pwe
138
 * Ownership -> PWE, tidy banners
139
 *
140
 * Revision 1.1  1994/10/27  14:15:22  jmf
141
 * Initial revision
142
 *
143
 * Revision 1.1  1994/07/12  14:29:47  jmf
144
 * Initial revision
145
 *
146
**********************************************************************/
147
 
148
 
149
/**********************************************************************
150
   cproc produces the code for the procedure defined by which has
151
   name pname.
152
 
153
**********************************************************************/
154
 
155
#include "config.h"
156
#include "common_types.h"
157
#include "weights.h"
158
#include "basicread.h"
159
#include "tags.h"
160
#include "codermacs.h"
161
#include "instr386.h"
162
#include "expmacs.h"
163
#include "exp.h"
164
#include "operand.h"
165
#include "shapemacs.h"
166
#include "instr.h"
167
#include "instrmacs.h"
168
#include "out.h"
169
#include "check.h"
170
#include "flags.h"
171
#include "codec.h"
172
#include "xalloc.h"
173
#include "global_opt.h"
174
#include "reg_record.h"
175
#include "externs.h"
176
#include "install_fns.h"
177
#include "installglob.h"
178
#include "machine.h"
179
#include "localflags.h"
180
#include "diag_fns.h"
181
#include "messages_8.h"
182
#include "assembler.h"
183
#include "coder.h"
184
#include "scan2.h"
185
#include "cproc.h"
186
 
187
#ifdef NEWDWARF
188
#include "dw2_config.h"
189
#include "dw2_info.h"
190
#include "dw2_basic.h"
191
#include "dw2_extra.h"
192
#endif
193
 
194
static exp returns_list;
195
 
196
int locals_offset;	/* global, needed for solaris stabs */
197
exp hasenvoff_list = nilexp;	/* global, used by coder */
198
 
199
/* MACROS */
200
 
201
#define GLOBALTABLEMASK 0x8
202
 
203
/* PROCEDURES */
204
 
205
static void add_odd_bits
206
    PROTO_N ( (r) )
207
    PROTO_T ( outofline * r )
208
{
209
  if (r != (outofline*)0) {
210
    if (r -> next == (outofline*)0)
211
      last_odd_bit = 1;
212
    add_odd_bits(r -> next);
213
  }
214
  else
215
    return;
216
 
217
  current_odd_bit = r;
218
  if (is80486)
219
    dot_align(4);
220
  simple_set_label(r->labno);
221
  clear_reg_record(crt_reg_record);
222
#ifdef NEWDWARF
223
  if (dwarf2) {
224
#if 1
225
    dw2_start_extra_bit (r->body);
226
#else
227
    dw2_start_extra_bit (r->dw2_slave);
228
#endif
229
    START_BB ();
230
  }
231
#endif
232
 
233
  regsinuse = r->regsinuse;
234
  fstack_pos = r->fstack_pos;
235
  cond1_set = r->cond1_set;
236
  cond2_set = r->cond2_set;
237
  cond1 = r->cond1;
238
  cond2a = r->cond2a;
239
  cond2b = r->cond2b;
240
  repeat_level = r->repeat_level;
241
  scale = r->scale;
242
  coder(r->dest, r->stack, r->body);
243
  if (name(sh(r->body)) != bothd)  {
244
    clean_stack();
245
    jump(r->jr, 0);
246
  }
247
  else
248
    stack_dec = 0;
249
#ifdef NEWDWARF
250
  if (dwarf2)
251
#if 1
252
    dw2_end_extra_bit (r->body);
253
#else
254
    dw2_end_extra_bit (r->dw2_hi);
255
#endif
256
#endif
257
  return;
258
}
259
 
260
static void out_pops
261
    PROTO_N ( (tot_sp, push_space, extra, dpos) )
262
    PROTO_T ( int tot_sp X int push_space X int extra X int dpos )
263
{
264
#ifdef NEWDWARF
265
  int st;
266
  long dwl0 = 0, dwl1 = 0, dwl2 = 0, dwl3 = 0, dwl4 = 0;
267
#endif
268
  tot_sp -= extra;
269
  if (no_frame && !stack_aligned_8byte) {
270
    if (tot_sp != push_space) {
271
      outs (" addl $");
272
      outn ((long)(tot_sp - push_space));
273
      outs (",%esp");
274
      outnl();
275
#ifdef NEWDWARF
276
      if (diagnose && dwarf2)
277
	dwl0 = set_dw_text_label ();
278
#endif
279
    };
280
  }
281
  else {
282
    if (tot_sp != push_space || has_alloca || stack_aligned_8byte) {
283
      outs (" leal -");
284
      outn ((long)push_space);
285
      outs ("(%ebp),%esp");
286
      outnl();
287
    };
288
  };
289
 
290
  /* pop the registers at the end */
291
  if (no_frame && (min_rfree & 0x40)) {
292
    outs (" pop %ebp");
293
    outnl();
294
#ifdef NEWDWARF
295
    if (diagnose && dwarf2)
296
      dwl1 = set_dw_text_label ();
297
#endif
298
  };
299
  if (min_rfree & 0x20) {
300
    outs (" pop %esi");
301
    outnl();
302
#ifdef NEWDWARF
303
    if (diagnose && dwarf2)
304
      dwl2 = set_dw_text_label ();
305
#endif
306
  };
307
  if (min_rfree & 0x10) {
308
    outs (" pop %edi");
309
    outnl();
310
#ifdef NEWDWARF
311
    if (diagnose && dwarf2)
312
      dwl3 = set_dw_text_label ();
313
#endif
314
  };
315
  if (min_rfree & 0x8) {
316
    outs (" pop %ebx");
317
    outnl();
318
#ifdef NEWDWARF
319
    if (diagnose && dwarf2)
320
      dwl4 = set_dw_text_label ();
321
#endif
322
  };
323
 
324
  if (!no_frame)  {
325
    outs (" pop %ebp");
326
    outnl();
327
#ifdef NEWDWARF
328
    if (diagnose && dwarf2)
329
      dwl1 = set_dw_text_label ();
330
#endif
331
  };
332
  outnl();
333
#ifdef NEWDWARF
334
  if (diagnose && dwarf2) {
335
    st = fseek (fpout, dpos, 0);
336
    if (st == -1) {
337
      failer (SEEK_FAILURE);
338
      exit(EXIT_FAILURE);
339
    };
340
    dw2_fde_restore_args (dwl0, dwl1, dwl2, dwl3, dwl4, push_space);
341
  }
342
#endif
343
  return;
344
}
345
 
346
static void out_untidy_pops
347
    PROTO_N ( (tot_sp, push_space) )
348
    PROTO_T ( int tot_sp X int push_space )
349
{
350
  if (no_frame) {
351
    int s_offset = tot_sp - push_space;
352
    if (min_rfree & 0x40) {
353
      outs (" movl ");
354
      outn ((long)s_offset);
355
      outs ("(%esp),%ebp");
356
      outnl();
357
      s_offset += 4;
358
    };
359
    if (min_rfree & 0x20) {
360
      outs (" movl ");
361
      outn ((long)s_offset);
362
      outs ("(%esp),%esi");
363
      outnl();
364
      s_offset += 4;
365
    };
366
    if (min_rfree & 0x10) {
367
      outs (" movl ");
368
      outn ((long)s_offset);
369
      outs ("(%esp),%edi");
370
      outnl();
371
      s_offset += 4;
372
    };
373
    if (min_rfree & 0x8) {
374
      outs (" movl ");
375
      outn ((long)s_offset);
376
      outs ("(%esp),%ebx");
377
      outnl();
378
      /* s_offset += 4; */
379
    };
380
  }
381
  else {
382
    int fm_offset = - push_space;
383
    if (min_rfree & 0x20) {
384
      outs (" movl ");
385
      outn ((long)fm_offset);
386
      outs ("(%ebp),%esi");
387
      outnl();
388
      fm_offset += 4;
389
    };
390
    if (min_rfree & 0x10) {
391
      outs (" movl ");
392
      outn ((long)fm_offset);
393
      outs ("(%ebp),%edi");
394
      outnl();
395
      fm_offset += 4;
396
    };
397
    if (min_rfree & 0x8) {
398
      outs (" movl ");
399
      outn ((long)fm_offset);
400
      outs ("(%ebp),%ebx");
401
      outnl();
402
      /* fm_offset += 4; */
403
    };
404
    outs (" movl 0(%ebp),%ebp");
405
    outnl();
406
  };
407
  return;
408
}
409
 
410
 
411
int cproc
412
    PROTO_N ( (p, pname, cname, global, diag_props) )
413
    PROTO_T ( exp p X char *pname X int cname X int global X diag_global * diag_props )
414
{
415
  exp jr, t, body;
416
  ash stack;
417
  int  ms;
418
  int tot_sp;
419
  int param_pos;
420
  int byte_stack_align = stack_align / 8;
421
  int   st;
422
  long  old_pos1,
423
        old_pos1a,
424
        old_pos2,
425
        old_pos3,
426
        old_pos4,
427
        old_pos5,
428
        old_pos8,
429
        old_pos9,
430
        this_pos;
431
  int  push_space = 0;
432
#ifdef NEWDWARF
433
  long dwl0, dwl8, dw_entry_pos;
434
  long dwl1 = 0, dwl2 = 0, dwl3 = 0, dwl4 = 0;
435
  char * dw_labroom = "                 ";
436
		     /* .Ldw12345678:\n */
437
#endif
438
 
439
  int request_align_8byte;
440
 
441
  returns_list = nilexp;
442
  crt_proc_exp = p;
443
  crt_proc_id = next_lab();
444
  crt_ret_lab = next_lab ();	/* set up the return label for the
445
				   procedure */
446
  crt_ret_lab_used = 0;
447
  odd_bits = (outofline*)0;
448
  scale = (float)1.0;
449
  not_in_params = 1;
450
  not_in_postlude = 1;
451
  keep_short = 0;
452
  repeat_level = 0;
453
  callee_size = (proc_has_vcallees(p) ? -1 : 0);
454
  ferrsize = 0;
455
  fpucon = normal_fpucon;
456
 
457
  has_dy_callees = 0;		/* set by scan2 when stack_dec indeterminable */
458
  has_tail_call = 0;		/* set by scan2, used in coder */
459
  has_same_callees = 0;		/* set by scan2, used in coder */
460
  proc_has_asm = 0;		/* set by scan2 if any asm operands */
461
  IGNORE scan2(1, p, p, 0);
462
  useful_double = 0;
463
  comp_weights(p);
464
 
465
/* 8byte align */
466
  request_align_8byte = permit_8byte_align && useful_double;
467
 
468
  if (pname[0] != local_prefix[0])
469
    proc_type(pname);
470
 
471
  has_alloca = proc_has_alloca(p);
472
 
473
  must_use_bp = (has_alloca || proc_has_lv(p));
474
 
475
  regsinuse = 0;
476
 
477
  no_frame = 1;
478
  if (always_use_frame || do_profile || must_use_bp || has_dy_callees ||
479
        proc_uses_crt_env(p) || proc_has_setjmp(p) || proc_has_asm
480
     )
481
     no_frame = 0;
482
 
483
  if (request_align_8byte && no_frame) {
484
    no_frame = 0;
485
    stack_aligned_8byte = 1;
486
  }
487
  else
488
    stack_aligned_8byte = 0;
489
 
490
  if (!no_frame)
491
    regsinuse = 0x40; /* prevent ebp from being used as an ordinary
492
                          register */
493
 
494
  fstack_pos = first_fl_reg;
495
 
496
  max_stack = 0;		/* maximum stack value attained */
497
  max_extra_stack = 0;		/* maximum stack value attained */
498
  min_rfree = 0;		/* total registers used */
499
  stack_dec = 0;		/* current stack decrement */
500
  cond1_set = 0;
501
  cond2_set = 0;		/* state of condition flags is not known
502
				*/
503
  clear_reg_record (crt_reg_record);
504
  stack.ashsize = 0;
505
  stack.ashalign = 0;
506
 
507
 
508
 
509
  vc_pointer = nilexp;
510
				/* set up params before any diagnostics */
511
  t = son(p);
512
  param_pos = 0;
513
  while (name(t) == ident_tag && isparam(t) && name(son(t)) != formal_callee_tag)
514
   {
515
     t = bro(son(t));
516
   };
517
  if (name(t) == ident_tag && name(son(t)) == formal_callee_tag)
518
   {
519
     if (callee_size < 0)
520
	vc_pointer = t;
521
     while (name(t) == ident_tag && name(son(t)) == formal_callee_tag)
522
      {
523
	ptno(t) = par_pl;
524
	no(t) = param_pos;
525
	if (isenvoff(t))
526
	  set_env_off(param_pos+64, t);
527
	param_pos = rounder(param_pos + shape_size(sh(son(t))), param_align);
528
	t = bro(son(t));
529
      };
530
     if (callee_size == 0)
531
	callee_size = param_pos;
532
   };
533
   {
534
     exp pp = son(p);
535
     while (name(pp) == ident_tag && isparam(pp) && name(son(pp)) != formal_callee_tag)
536
      {
537
	ptno(pp) = par_pl;
538
	no(pp) = param_pos;
539
	if (isenvoff(pp))
540
	  set_env_off(param_pos+64, pp);
541
	param_pos = rounder(param_pos + shape_size(sh(son(pp))), param_align);
542
	pp = bro(son(pp));
543
      };
544
   };
545
 
546
  body = t;
547
 
548
 
549
 
550
 
551
  if (global) {
552
    outs (".globl ");
553
    outs (pname);
554
    outnl ();
555
  };
556
 
557
  if (is80486)
558
    dot_align(16);
559
  else
560
    dot_align(4);
561
 
562
  if (diagnose)
563
#ifdef NEWDWARF
564
    DIAG_PROC_BEGIN (diag_props, global, cname, pname, p);
565
#else
566
    diag_proc_begin (diag_props, global, cname, pname);
567
#endif
568
 
569
  if (cname == -1)
570
    outs (pname);
571
  else
572
    {
573
      outs(local_prefix);
574
      outn((long)cname);
575
    };
576
  outs (":");
577
  outnl ();
578
#ifdef NEWDWARF
579
  if (diagnose && dwarf2) {
580
    START_BB ();
581
    dwl0 = set_dw_text_label ();
582
  }
583
#endif
584
 
585
/* space for setting local displacement label */
586
  if (flush_before_tell)
587
    IGNORE fflush(fpout);
588
  old_pos1 = ftell (fpout);
589
  outs ("                          ");
590
     /* ".set .LdispNNNN, SSSSS\n" */
591
  outnl ();
592
  if (flush_before_tell)
593
    IGNORE fflush(fpout);
594
  old_pos1a = ftell (fpout);
595
  outs ("                             ");
596
     /* ".set .LfcwdispNNNN, SSSSS\n" */
597
  outnl ();
598
 
599
  if (!no_frame) {
600
    outs (" pushl %ebp");
601
    outnl ();
602
    outs (" movl %esp,%ebp");
603
    outnl ();
604
#ifdef NEWDWARF
605
    if (diagnose && dwarf2)
606
      dwl1 = set_dw_text_label ();
607
#endif
608
  };
609
 
610
/* space for pushing fixed point registers */
611
  if (flush_before_tell)
612
    IGNORE fflush(fpout);
613
  old_pos2 = ftell (fpout);
614
  outs ("               ");
615
     /* " pushl %ebx\n" */
616
#ifdef NEWDWARF
617
  if (diagnose && dwarf2)
618
    outs (dw_labroom);
619
#endif
620
  outnl ();
621
  if (flush_before_tell)
622
    IGNORE fflush(fpout);
623
  old_pos3 = ftell (fpout);
624
  outs ("               ");
625
     /* " pushl %edi\n" */
626
#ifdef NEWDWARF
627
  if (diagnose && dwarf2)
628
    outs (dw_labroom);
629
#endif
630
  outnl ();
631
  if (flush_before_tell)
632
    IGNORE fflush(fpout);
633
  old_pos4 = ftell (fpout);
634
  outs ("               ");
635
     /* " pushl %esi\n" */
636
#ifdef NEWDWARF
637
  if (diagnose && dwarf2)
638
    outs (dw_labroom);
639
#endif
640
  outnl ();
641
  if (no_frame) {
642
    if (flush_before_tell)
643
      IGNORE fflush(fpout);
644
    old_pos5 = ftell (fpout);
645
    outs ("               ");
646
       /* " pushl %ebp\n" */
647
#ifdef NEWDWARF
648
    if (diagnose && dwarf2)
649
      outs (dw_labroom);
650
#endif
651
    outnl ();
652
  }
653
 
654
/* space for subtract from stack pointer */
655
  if (flush_before_tell)
656
    IGNORE fflush(fpout);
657
  old_pos8 = ftell (fpout);
658
  outs ("                     ");
659
     /* " subl $SSSSS,%esp\n" */
660
     /* " movl $SSSSS,%eax\n" */
661
  outnl ();
662
  if (proc_has_checkstack(p)) {
663
    checkalloc_stack (reg0, 1);
664
  };
665
#ifdef NEWDWARF
666
  if (diagnose && dwarf2) {
667
    dwl8 = set_dw_text_label ();
668
    dw_entry_pos = dw2_start_fde (dwl0, dwl1);
669
  }
670
#endif
671
 
672
  if (stack_aligned_8byte) {
673
    outs(" andl $-8,%esp");
674
    outnl();
675
  };
676
 
677
  if (flush_before_tell)
678
    IGNORE fflush(fpout);
679
  old_pos9 = ftell (fpout);
680
  outs ("                                    ");
681
     /* "movw $DDDD,0-.LfcwdispNNNN(%ebp)\n" */
682
  outnl ();
683
 
684
 
685
#if islinux || isfreebsd
686
  if (
687
#if islinux
688
	!linux_elf &&
689
#endif
690
	pname[0] != local_prefix[0] &&
691
	!strcmp (pname+prefix_length, "main")) {
692
    out_main_prelude();
693
  }
694
#endif
695
 
696
  if (do_profile) {
697
    int  labl = next_lab ();	/* output profile procedure header */
698
    outs (".data");
699
    outnl ();
700
    dot_align(4);
701
    outs(local_prefix);
702
    outs ("P");
703
    outn ((long)labl);
704
    outs (":");
705
    outnl ();
706
    outs (" .long 0");
707
    outnl ();
708
    outs (".text");
709
    outnl ();
710
    outs (" leal ");
711
    outs(local_prefix);
712
    outs ("P");
713
    outn ((long)labl);
714
    outs (",%edx");
715
    outnl ();
716
    outs (" call _mcount");
717
    outnl ();
718
  };
719
 
720
 
721
  if (PIC_code && proc_uses_external(p))
722
   {
723
     regsinuse |= GLOBALTABLEMASK;
724
     min_rfree |= GLOBALTABLEMASK;
725
     pic_prelude();
726
   };
727
 
728
  need_preserve_stack = 0;
729
  if (proc_uses_crt_env(p) && proc_has_lv(p) && has_alloca)
730
   {
731
     need_preserve_stack = 1;
732
     stack.ashsize += 32;
733
     max_stack = stack.ashsize;
734
     save_stack ();
735
   };
736
 
737
  scale = (float)1.0;
738
  last_odd_bit = 0;
739
  doing_odd_bits = 0;
740
  coder (zero, stack, body); /* code body of procedure */
741
 
742
  stack_dec = 0;
743
  doing_odd_bits = 1;
744
  while (odd_bits != (outofline*)0) {
745
    outofline * ol = odd_bits;
746
    odd_bits = (outofline*)0;
747
    last_odd_bit = 0;
748
    add_odd_bits(ol);
749
  }
750
 
751
 
752
  if (crt_ret_lab_used) {
753
    jr = getexp (f_bottom, nilexp, 0, nilexp, nilexp, 0,
754
                0, 0);
755
    sonno(jr) = stack_dec;
756
    ptno(jr) = crt_ret_lab;
757
    fstack_pos_of(jr) = (prop)first_fl_reg;
758
    set_label (jr);
759
  };
760
 
761
	/* If the procedure loads the current env and uses make_lv
762
	   it may be the destination of a long_jump. In that case
763
	   ebx, esi and edi must be saved at and restored at exit.
764
	   ebp will be saved and restored anyway because such a
765
	   procedure will have a frame pointer.
766
	*/
767
  if (proc_uses_crt_env(p) && proc_has_lv(p))
768
    min_rfree |= 0x38;
769
 
770
  /* compute space needed for local variables in memory */
771
  ms = ((max_stack + 31) / 32) * 4;
772
  /* compute space needed for pushing registers */
773
  if (no_frame && min_rfree & 0x40)
774
    push_space += 4;
775
  if (min_rfree & 0x20)
776
    push_space += 4;
777
  if (min_rfree & 0x10)
778
    push_space += 4;
779
  if (min_rfree & 0x8)
780
    push_space += 4;
781
 
782
  ferrsize /= 8;
783
  tot_sp = rounder(ms + push_space + ferrsize, byte_stack_align);
784
 
785
  if (crt_ret_lab_used) {
786
#ifdef NEWDWARF
787
    long over_lab;
788
    if (diagnose && dwarf2) {
789
      over_lab = next_dwarf_label ();
790
      dw2_return_pos (over_lab);
791
    }
792
#endif
793
    restore_callregs (0);
794
    retins();
795
    outnl ();
796
#ifdef NEWDWARF
797
    if (diagnose && dwarf2)
798
      dw2_after_fde_exit (over_lab);
799
#endif
800
  };
801
  outnl ();
802
 
803
  this_pos = ftell (fpout);
804
  while (returns_list != nilexp) {
805
    st = fseek (fpout, (long)no(returns_list), 0);
806
    if (st == -1) {
807
      failer (SEEK_FAILURE);
808
      exit(EXIT_FAILURE);
809
    };
810
    if (name(returns_list) == 1)
811
      out_untidy_pops (tot_sp, push_space);
812
    else
813
      out_pops(tot_sp, push_space, ptno(returns_list)/8, sonno(returns_list));
814
    returns_list = bro(returns_list);
815
  };
816
  fseek(fpout, this_pos, 0);
817
 
818
  locals_offset = tot_sp;
819
  if (diagnose) {
820
    no (p) = tot_sp;	/* may be used by delayed diagnostics */
821
#ifdef NEWDWARF
822
    DIAG_PROC_END (diag_props, p);
823
#else
824
    diag_proc_end (diag_props);
825
#endif
826
#ifdef NEWDWARF
827
  if (dwarf2)
828
    dw2_complete_fde ();
829
#endif
830
  }
831
 
832
  /* now set in the information at the head of the procedure */
833
  {
834
 
835
    if (flush_before_tell)
836
      IGNORE fflush(fpout);
837
    this_pos = ftell (fpout);
838
    st = fseek (fpout, old_pos1, 0);
839
    if (st == -1) {
840
      failer (SEEK_FAILURE);
841
      exit(EXIT_FAILURE);
842
    };
843
 
844
    /* set the label which says how much the stack was decreased, in case
845
       frame pointer addressing is used  */
846
    outs (".set ");
847
    outs(local_prefix);
848
    outs ("disp");
849
    outn ((long)crt_proc_id);
850
    outs (", ");
851
    outn ((long)tot_sp);
852
 
853
    if (ferrsize != 0) {
854
	/* set label for displacement to fpu control local store */
855
      st = fseek (fpout, old_pos1a, 0);
856
      if (st == -1) {
857
        failer (SEEK_FAILURE);
858
        exit(EXIT_FAILURE);
859
      };
860
      outs (".set ");
861
      outs(local_prefix);
862
      outs ("fcwdisp");
863
      outn ((long)crt_proc_id);
864
      outs (", ");
865
      outn ((long)((no_frame) ? (tot_sp - push_space - ferrsize) : (push_space + ferrsize)));
866
    }
867
 
868
    st = fseek (fpout, this_pos, 0);
869
    if (st == -1) {
870
      failer (SEEK_FAILURE);
871
      exit(EXIT_FAILURE);
872
    };
873
  };
874
 
875
  if (tot_sp != push_space || proc_has_checkstack(p)) {
876
    if (flush_before_tell)
877
      IGNORE fflush(fpout);
878
    this_pos = ftell (fpout);
879
    st = fseek (fpout, old_pos8, 0);
880
    if (st == -1) {
881
      failer (SEEK_FAILURE);
882
      exit(EXIT_FAILURE);
883
    };
884
 
885
    /* decrease the stack if necessary */
886
    if (proc_has_checkstack(p)) {
887
      outs (" movl $");
888
      outn ((long)(tot_sp - push_space));
889
      outs (",%eax");
890
    }
891
    else {
892
      outs (" subl $");
893
      outn ((long)(tot_sp - push_space));
894
      outs (",%esp");
895
    };
896
    outnl();
897
 
898
    if (ferrsize != 0) {	/* record FPU control word */
899
      st = fseek (fpout, old_pos9, 0);
900
      if (st == -1) {
901
        failer (SEEK_FAILURE);
902
        exit(EXIT_FAILURE);
903
      };
904
      move (uwordsh, mw(zeroe, normal_fpucon), mw(ferrmem, 0));
905
    }
906
 
907
    st = fseek (fpout, this_pos, 0);
908
    if (st == -1) {
909
      failer (SEEK_FAILURE);
910
      exit(EXIT_FAILURE);
911
    };
912
  };
913
 
914
  /* push registers as necessary */
915
  if (min_rfree & 0x8) {
916
    st = fseek (fpout, old_pos2, 0);
917
    if (st == -1) {
918
      failer (SEEK_FAILURE);
919
      exit(EXIT_FAILURE);
920
    };
921
    outs (" pushl %ebx");
922
    outnl();
923
#ifdef NEWDWARF
924
    if (diagnose && dwarf2)
925
      dwl2 = set_dw_text_label ();
926
#endif
927
  };
928
 
929
  if (min_rfree & 0x10) {
930
    st = fseek (fpout, old_pos3, 0);
931
    if (st == -1) {
932
      failer (SEEK_FAILURE);
933
      exit(EXIT_FAILURE);
934
    };
935
    outs (" pushl %edi");
936
    outnl();
937
#ifdef NEWDWARF
938
    if (diagnose && dwarf2)
939
      dwl3 = set_dw_text_label ();
940
#endif
941
  };
942
 
943
 
944
  if (min_rfree & 0x20) {
945
    st = fseek (fpout, old_pos4, 0);
946
    if (st == -1) {
947
      failer (SEEK_FAILURE);
948
      exit(EXIT_FAILURE);
949
    };
950
    outs (" pushl %esi");
951
    outnl();
952
#ifdef NEWDWARF
953
    if (diagnose && dwarf2)
954
      dwl4 = set_dw_text_label ();
955
#endif
956
  };
957
 
958
  if (no_frame && (min_rfree & 0x40)) {
959
    st = fseek (fpout, old_pos5, 0);
960
    if (st == -1) {
961
      failer (SEEK_FAILURE);
962
      exit(EXIT_FAILURE);
963
    };
964
    outs (" pushl %ebp");
965
    outnl();
966
#ifdef NEWDWARF
967
    if (diagnose && dwarf2)
968
      dwl1 = set_dw_text_label ();
969
#endif
970
  };
971
 
972
#ifdef NEWDWARF
973
  if (diagnose && dwarf2) {
974
    st = fseek (fpout, dw_entry_pos, 0);
975
    if (st == -1) {
976
      failer (SEEK_FAILURE);
977
      exit(EXIT_FAILURE);
978
    };
979
    dw2_fde_entry (dwl0, dwl1, dwl2, dwl3, dwl4, dwl8, tot_sp);
980
  };
981
#endif
982
 
983
  st = fseek (fpout, this_pos, 0);
984
  if (st == -1) {
985
    failer (SEEK_FAILURE);
986
    exit(EXIT_FAILURE);
987
  };
988
 
989
  if (pname[0] != local_prefix[0])
990
    proc_size (pname);
991
 
992
  if (proc_needs_envsize(p)) {
993
    outs (".set ");
994
    outs(local_prefix);
995
    outs ("ESZ");
996
    outs (pname);
997
    outs (", ");
998
    outn ((long)(tot_sp + 4 + max_extra_stack/8));
999
    outnl ();
1000
  }
1001
 
1002
#if islinux || isfreebsd
1003
  if (
1004
#if islinux
1005
	!linux_elf &&
1006
#endif
1007
	pname[0] != local_prefix[0] &&
1008
	!strcmp (pname+prefix_length, "main")) {
1009
    out_main_postlude();
1010
  }
1011
#endif
1012
 
1013
  /* now prepare params with env_offset for possible constant evaluation */
1014
  t = son(p);
1015
  while (name(t) == ident_tag && isparam(t)) {
1016
    if (isenvoff(t)) {
1017
      no(t) += 64;
1018
      name(t) = 0;
1019
      ptno(t) = local_pl;
1020
    }
1021
    t = bro(son(t));
1022
  }
1023
  while (hasenvoff_list != nilexp) {
1024
    exp id = son(hasenvoff_list);
1025
    exp next = bro(hasenvoff_list);
1026
    no(id) -= (locals_offset * 8);
1027
    name(id) = 0;
1028
    retcell(hasenvoff_list);
1029
    hasenvoff_list = next;
1030
  }
1031
 
1032
  if (no_frame)			/* hold info for later diagnostics */
1033
    clear_proc_has_fp(p);
1034
  else
1035
    set_proc_has_fp(p);
1036
 
1037
  return (proc_needs_envsize(p) ? tot_sp + 4 + max_extra_stack/8 : 0);
1038
}
1039
 
1040
 
1041
/* Restore call_save registers (%ebp, %esi, %edi, %ebx)
1042
   when we know which ones are reused.
1043
   This preserves %eax, %ecx, %edx */
1044
void restore_callregs
1045
    PROTO_N ( (untidy) )
1046
    PROTO_T ( int untidy )
1047
{
1048
  char *sp50 = "                                                  ";
1049
  long retpos = ftell(fpout);
1050
  outs("?");	/* will be overwritten, to cause assembler fail if sco bug */
1051
  outs(sp50); outs(sp50); outs(sp50);
1052
  outnl();
1053
  returns_list = getexp(f_top, returns_list, 0, nilexp,
1054
				nilexp, 0, 0, (unsigned char)untidy);
1055
  no(returns_list) = (int)retpos;
1056
  ptno(returns_list) = stack_dec;
1057
#ifdef NEWDWARF
1058
  if (diagnose && dwarf2)
1059
    sonno(returns_list) = (int)dw2_prep_fde_restore_args (untidy);
1060
#endif
1061
  return;
1062
}