Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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