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/coder.c */
62
 
63
/**********************************************************************
64
$Author: pwe $
65
$Date: 1998/03/15 16:00:13 $
66
$Revision: 1.4 $
67
$Log: coder.c,v $
68
 * Revision 1.4  1998/03/15  16:00:13  pwe
69
 * regtrack dwarf dagnostics added
70
 *
71
 * Revision 1.3  1998/03/11  11:03:01  pwe
72
 * DWARF optimisation info
73
 *
74
 * Revision 1.2  1998/02/18  11:21:59  pwe
75
 * test corrections
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.49  1997/12/08  16:44:33  pwe
81
 * make_compound
82
 *
83
 * Revision 1.48  1997/12/04  20:00:53  pwe
84
 * ANDF-DE V1.9
85
 *
86
 * Revision 1.47  1997/10/28  10:26:31  pwe
87
 * correct extra diags / locations
88
 *
89
 * Revision 1.46  1997/10/23  09:36:49  pwe
90
 * extra_diags
91
 *
92
 * Revision 1.45  1997/10/10  18:24:55  pwe
93
 * prep ANDF-DE revision
94
 *
95
 * Revision 1.44  1997/08/23  13:45:23  pwe
96
 * initial ANDF-DE
97
 *
98
 * Revision 1.43  1997/04/21  08:31:05  pwe
99
 * amend reg record at end of scope
100
 *
101
 * Revision 1.42  1997/04/17  11:55:34  pwe
102
 * dwarf2 improvements
103
 *
104
 * Revision 1.41  1997/03/20  16:23:29  pwe
105
 * dwarf2
106
 *
107
 * Revision 1.40  1997/02/18  11:42:46  pwe
108
 * NEWDIAGS for debugging optimised code
109
 *
110
 * Revision 1.39  1996/12/13  14:39:13  pwe
111
 * prep NEWDIAGS
112
 *
113
 * Revision 1.38  1996/12/10  15:11:27  pwe
114
 * prep NEWDIAGS
115
 *
116
 * Revision 1.37  1996/11/08  16:18:56  pwe
117
 * check_stack to check before modifying stack
118
 *
119
 * Revision 1.36  1996/10/08  07:58:50  pwe
120
 * revised correction to env_offset v id out_of_line
121
 *
122
 * Revision 1.35  1996/10/07  13:31:00  pwe
123
 * push make_value, and env_offset v id out_of_line
124
 *
125
 * Revision 1.34  1996/07/31  12:56:31  pwe
126
 * restore alloca stack after longjump
127
 *
128
 * Revision 1.33  1996/07/10  15:44:24  pwe
129
 * visible ptr top (for AVS 3.0)
130
 *
131
 * Revision 1.32  1996/05/20  14:30:06  pwe
132
 * improved 64-bit handling
133
 *
134
 * Revision 1.31  1996/05/13  12:51:49  pwe
135
 * undo premature commit
136
 *
137
 * Revision 1.29  1996/03/12  12:44:07  pwe
138
 * 64-bit ints compatible with gcc long long
139
 *
140
 * Revision 1.28  1996/02/20  14:44:55  pwe
141
 * linux/elf return struct
142
 *
143
 * Revision 1.27  1996/01/31  13:02:29  pwe
144
 * general proc with postlude used in proc parameter position
145
 *
146
 * Revision 1.26  1996/01/17  11:24:17  pwe
147
 * resurrect performance
148
 *
149
 * Revision 1.25  1996/01/11  14:02:15  pwe
150
 * struct return v postludes (again)
151
 *
152
 * Revision 1.24  1996/01/10  13:59:42  pwe
153
 * apply with varcallees within postlude
154
 *
155
 * Revision 1.23  1996/01/05  16:25:15  pwe
156
 * env_size and env_offset within constant expressions
157
 *
158
 * Revision 1.22  1995/12/14  16:49:09  pwe
159
 * postlude with struct result
160
 *
161
 * Revision 1.21  1995/11/01  18:41:04  pwe
162
 * PIC tail_call and exception handling
163
 *
164
 * Revision 1.20  1995/10/25  17:41:08  pwe
165
 * PIC_code current_env and callees
166
 *
167
 * Revision 1.19  1995/10/09  15:14:05  pwe
168
 * dynamic initialisation etc
169
 *
170
 * Revision 1.18  1995/09/29  16:17:49  pwe
171
 * gcc_compatible default on Linux
172
 *
173
 * Revision 1.17  1995/09/26  16:46:41  pwe
174
 * compare with zero to ignore previous overflow
175
 *
176
 * Revision 1.16  1995/09/08  12:51:01  pwe
177
 * exceptions improved
178
 *
179
 * Revision 1.15  1995/09/05  16:24:37  pwe
180
 * specials and exception changes
181
 *
182
 * Revision 1.14  1995/09/01  17:29:56  pwe
183
 * traps and Build scripts
184
 *
185
 * Revision 1.13  1995/08/30  16:06:17  pwe
186
 * prepare exception trapping
187
 *
188
 * Revision 1.12  1995/08/23  09:42:27  pwe
189
 * track fpu control word for trap etc
190
 *
191
 * Revision 1.11  1995/08/14  13:53:20  pwe
192
 * several corrections, tail calls and error jumps
193
 *
194
 * Revision 1.10  1995/08/04  08:28:58  pwe
195
 * 4.0 general procs implemented
196
 *
197
 * Revision 1.9  1995/04/13  11:32:16  pwe
198
 * catch discards with side effects
199
 *
200
 * Revision 1.8  1995/03/23  13:25:33  pwe
201
 * limit scale in deeply nested repeats
202
 *
203
 * Revision 1.7  1995/02/27  10:58:52  pwe
204
 * local_free val_tag offsets treated similar to alloca
205
 *
206
 * Revision 1.6  1995/02/23  10:24:13  pwe
207
 * correction to compare env_offset
208
 *
209
 * Revision 1.5  1995/02/22  11:49:14  pwe
210
 * compare env_offset
211
 *
212
 * Revision 1.4  1995/02/01  18:51:13  pwe
213
 * correct empty make_nof
214
 *
215
 * Revision 1.3  1995/01/30  12:56:00  pwe
216
 * Ownership -> PWE, tidy banners
217
 *
218
 * Revision 1.2  1994/11/08  09:00:14  jmf
219
 * Corrected ncopies - NOT TO COPY
220
 *
221
 * Revision 1.1  1994/10/27  14:15:22  jmf
222
 * Initial revision
223
 *
224
 * Revision 1.7  1994/08/19  13:14:15  jmf
225
 * goto_tag: do final_dest before elimination of redundant jump,
226
 * so that jump to next; jump L is treated better.
227
 *
228
 * Revision 1.6  1994/08/09  11:54:31  jmf
229
 * alloc_reg: change to refuse reals which are variables.
230
 *
231
 * Revision 1.5  1994/08/04  10:22:36  jmf
232
 * Unon
233
 * Undone last fix to test and testbit. Changed label_ops
234
 *
235
 * Revision 1.4  1994/08/04  09:13:25  jmf
236
 * test and testbit: only swap labels if there is a single use.
237
 *
238
 * Revision 1.3  1994/07/12  15:37:26  jmf
239
 * Corrected silly synatx error l29
240
 *
241
 * Revision 1.2  1994/07/12  15:16:42  jmf
242
 * Change to align_label(2 in solve
243
 * Removed is_tester (now in misc_c.c
244
 *
245
 * Revision 1.1  1994/07/12  14:28:00  jmf
246
 * Initial revision
247
 *
248
**********************************************************************/
249
 
250
 
251
/**********************************************************************
252
 
253
                             coder.c
254
 
255
   coder produces code for expressions. It calls codec to produce code
256
   for expressions which deliver results, and produces code itself for
257
   the others.
258
 
259
**********************************************************************/
260
 
261
 
262
#include "config.h"
263
#include <limits.h>
264
#include "common_types.h"
265
#include "weights.h"
266
#include "basicread.h"
267
#include "tags.h"
268
#include "codermacs.h"
269
#include "instr386.h"
270
#include "expmacs.h"
271
#include "exp.h"
272
#include "operand.h"
273
#include "shapemacs.h"
274
#include "instr.h"
275
#include "instrmacs.h"
276
#include "out.h"
277
#include "check.h"
278
#include "flags.h"
279
#include "codec.h"
280
#include "xalloc.h"
281
#include "global_opt.h"
282
#include "reg_record.h"
283
#include "externs.h"
284
#include "install_fns.h"
285
#include "installglob.h"
286
#include "machine.h"
287
#include "localflags.h"
288
#include "diag_fns.h"
289
#include "messages_8.h"
290
#include "assembler.h"
291
#include "natmacs.h"
292
#include "label_ops.h"
293
#include "misc_c.h"
294
#include "readglob.h"
295
#include "cproc.h"
296
#include "coder.h"
297
 
298
#ifdef NEWDIAGS
299
#include "dg_aux.h"
300
#include "dg_globs.h"
301
#endif
302
 
303
#ifdef NEWDWARF
304
#include "dw2_config.h"
305
#include "dw2_info.h"
306
#include "dw2_basic.h"
307
#include "dw2_extra.h"
308
#endif
309
 
310
 
311
extern exp hasenvoff_list;
312
 
313
 
314
/* MACROS */
315
 
316
#define crit_noframe 300
317
 
318
#define align_crit 10000.0
319
 
320
 
321
 
322
#define noreg 6
323
#define nobigreg 4
324
#define nosmallreg 2
325
#define bigmask1 0x40
326
#define bigmask1ns 0x8
327
#define bigmask2 0x30
328
#define smallmask1 0x2
329
#define smallmask2 0x6
330
 
331
#define nofl 6
332
#define nobigfl 3
333
#define bigflmask 0x1000
334
#define smallflmask 0x200
335
 
336
/* VARIABLES */
337
/* All variables initialised */
338
 
339
 
340
float scale = (float)1.0;	/* init by cproc */
341
 
342
 
343
int  crt_ret_lab;	/* init by cproc */
344
int  crt_ret_lab_used;	/* init by cproc */
345
int  min_rfree;		/* init by cproc */
346
int  max_stack;		/* init by cproc */
347
int  regsinuse;		/* init by cproc */
348
outofline * odd_bits;	/* init by cproc */
349
int last_odd_bit; 	/* init by cproc */
350
int doing_odd_bits; 	/* init by cproc */
351
outofline * current_odd_bit; 	/* init by cproc */
352
exp crt_proc_exp;	/* init by cproc */
353
 
354
int not_in_params = 1;	/* init by cproc */
355
int not_in_postlude = 1;	/* init by cproc */
356
int repeat_level = 0;	/* init by cproc */
357
int callee_size = 0;	/* init by cproc */
358
exp vc_pointer;		/* init by cproc */
359
int has_dy_callees = 0;	/* init by cproc */
360
int has_tail_call = 0;	/* init by cproc */
361
int has_same_callees = 0;	/* init by cproc */
362
int need_preserve_stack = 0;	/* init by cproc */
363
int proc_has_asm = 0;	/* init by cproc */
364
 
365
 
366
 
367
/* PROCEDURES */
368
 
369
void clean_stack
7 7u83 370
(void)
2 7u83 371
{
372
  if (no_frame && not_in_params && not_in_postlude && stack_dec != 0)
373
    stack_return(-stack_dec);
374
}
375
 
376
 
377
/* is this a pushable proc argument ? */
378
static int push_arg
7 7u83 379
(exp e)
2 7u83 380
{
381
  shape sha = sh(e);
7 7u83 382
  unsigned char  n = name(sha);
2 7u83 383
 
384
  if (name(e) == real_tag)
385
    return 1;
386
 
7 7u83 387
  if (is_floating(n) || n == cpdhd || n == nofhd)
2 7u83 388
    return 0;
389
 
7 7u83 390
  return(1);
2 7u83 391
}
392
 
393
static void code_push
7 7u83 394
(ash stack, exp t)
2 7u83 395
{
396
  int n = (int)name(t);
397
  if (is_o(n))
7 7u83 398
    coder(pushdest, stack, t);
2 7u83 399
  else {
400
    coder(reg0, stack, t);
401
    move(sh(t), reg0, pushdest);
402
  };
403
  return;
404
}
405
 
406
/* produce the code for proc params in
407
   order from last to first */
408
static void code_pars
7 7u83 409
(ash stack, exp t)
2 7u83 410
{
411
  int tsize = shape_size(sh(t));
412
  if (last (t)) {		/* last parameter is pushed first */
7 7u83 413
    code_push(stack,(name(t) ==caller_tag)? son(t): t);
414
    stack_dec -= rounder(tsize, param_align);
2 7u83 415
  }
416
  else {
417
    code_pars (stack, bro (t));/* encode the rest of the parameters */
418
    code_push (stack, (name(t)==caller_tag) ? son(t) : t);	/* code this parameter */
7 7u83 419
    stack_dec -= rounder(tsize, param_align);
2 7u83 420
    /* allow for the size */
421
  };
422
}
423
 
424
/* stack parameters ready for apply_proc */
425
static int procargs
7 7u83 426
(ash stack, exp arg, int has_checkstack)
2 7u83 427
{
428
  int use_push = 1;
429
  int longs = 0, extra;
430
  exp t = arg;
431
  while (t != nilexp) {
7 7u83 432
    if (name(t) ==caller_tag) {
433
      if (use_push && !push_arg(son(t)))
2 7u83 434
        use_push = 0;
435
      no(t) = longs;	/* needed for postlude */
436
    }
437
    else {
7 7u83 438
      if (use_push && !push_arg(t))
2 7u83 439
        use_push = 0;
440
    }
441
    longs = rounder(longs + shape_size(sh(t)), param_align);
442
    if (last(t))
443
      break;
444
    t = bro(t);
445
  };
7 7u83 446
  extra = (longs - stack_dec)% stack_align;
2 7u83 447
  longs += extra;
448
 
449
  if (use_push) {
450
	  /* push instructions can be used. Note that stack_dec is moved
451
	     so that instructions which address positively with respect to
452
	     sp can be changed. */
453
    if (extra != 0) {
454
      sub(slongsh, mw(zeroe, extra/8), sp, sp);
455
      stack_dec -= extra;  /* align stack to param_align */
456
#ifdef NEWDWARF
457
      if (diagnose && dwarf2 && no_frame)
458
	dw2_track_sp();
459
#endif
460
    };
461
    if (arg != nilexp) {
462
      if (has_checkstack && longs > 160) {
463
	/* check stack before pushing args if more than 5 words */
7 7u83 464
	checkalloc_stack(mw(zeroe, longs/8), 0);
2 7u83 465
      }
7 7u83 466
      code_pars(stack, arg);
2 7u83 467
    }
468
  }
469
  else {
470
	  /* if push cannot be used, move the stack down first, and then
471
	     assemble the parameters in place. Again, adjust stack_dec. */
472
    int off = extra;
473
    if (has_checkstack)
7 7u83 474
      checkalloc_stack(mw(zeroe, longs/8), 1);
2 7u83 475
    else
7 7u83 476
      decstack(longs);
2 7u83 477
    cond1_set = 0;
478
    cond2_set = 0;
479
    stack_dec -= longs;
480
#ifdef NEWDWARF
481
    if (diagnose && dwarf2 && no_frame)
482
      dw2_track_sp();
483
#endif
484
 
485
    t = arg;
486
    while (1)
487
     {
7 7u83 488
	coder(mw(ind_sp.where_exp, off), stack,(name(t) ==caller_tag ? son(t): t));
2 7u83 489
	off = rounder(off + shape_size(sh(t)), param_align);
490
	if (last(t))
491
	  break;
492
	t = bro(t);
493
     };
494
  };
495
  return longs;
496
}
497
 
498
/* stack dynamic or same callees */
499
/* %edx and %ecx don't need to be preserved */
500
static int push_cees
7 7u83 501
(exp src, exp siz, int vc, ash stack)
2 7u83 502
{
503
  int old_regsinuse = regsinuse;
504
  int longs = -1;
505
  if (siz == nilexp && callee_size >= 0)
506
    longs = callee_size;
507
  if (siz != nilexp && name(siz) == val_tag)
7 7u83 508
    longs = rounder(no(siz), param_align);
2 7u83 509
  if (longs == 0) {
510
    if (vc) {
7 7u83 511
      ins2(leal, 32, 32, mw(ind_sp.where_exp, longs), reg0);
512
      ins0(pusheax);
2 7u83 513
      stack_dec -= 32;
7 7u83 514
      return(32);
2 7u83 515
    }
7 7u83 516
    return(0);
2 7u83 517
  }
518
  if (longs < 0) {
519
    must_use_bp = 1;	/* scan2 must ensure !no_frame */
520
    if (siz == nilexp) {
521
	/* calculate size from calling proc callees */
7 7u83 522
      outs(" movl 8(%ebp),%eax\n");
523
      outs(" subl %ebp,%eax\n");
524
      outs(" subl $12,%eax\n");
2 7u83 525
    }
526
    else {
7 7u83 527
      coder(reg0, stack, siz);
2 7u83 528
      if (al2(sh(siz)) < param_align) {
529
	if (al2(sh(siz)) == 1) {
7 7u83 530
	  outs(" addl $31,%eax\n");
531
	  outs(" shrl $3,%eax\n");
2 7u83 532
	}
533
	else
7 7u83 534
	  outs(" addl $3,%eax\n");
535
	outs(" andl $-4,%eax\n");
2 7u83 536
      }
537
    }
7 7u83 538
    ins0(pusheax);
2 7u83 539
    stack_dec -= 32;
540
  }
541
  if (src == nilexp) {
542
    if (callee_size >= 0)
7 7u83 543
      outs(" leal 8(%ebp),%eax\n");
2 7u83 544
    else
7 7u83 545
      outs(" leal 12(%ebp),%eax\n");
2 7u83 546
    }
547
  else
7 7u83 548
    coder(reg0, stack, src);
549
  move(slongsh, reg5, reg1);
550
  move(slongsh, reg0, reg5);
2 7u83 551
  if (longs < 0) {
7 7u83 552
    ins0(popecx);
2 7u83 553
    stack_dec += 32;
554
    if (vc)
7 7u83 555
      outs(" movl %esp,%eax\n");
556
    outs(" subl %ecx,%esp\n");
557
    outs(" shrl $2,%ecx\n");
2 7u83 558
    if (vc)
7 7u83 559
      outs(" pushl %eax\n");
2 7u83 560
  }
561
  else {
562
    sub(slongsh, mw(zeroe, longs/8), sp, sp);
563
    stack_dec -= longs;
564
    if (vc) {
7 7u83 565
      ins2(leal, 32, 32, mw(ind_sp.where_exp, longs), reg0);
566
      ins0(pusheax);
2 7u83 567
      stack_dec -= 32;
568
    }
7 7u83 569
    move(slongsh, mw(zeroe, longs/32), reg2);
2 7u83 570
    if (vc)
571
      longs += 32;
572
  }
7 7u83 573
  move(slongsh, reg4, reg0);
2 7u83 574
  if (vc)
7 7u83 575
    outs(" leal 4(%esp),%edi\n");
2 7u83 576
  else
7 7u83 577
    outs(" movl %esp,%edi\n");
578
  outs(" rep\n movsl\n");
579
  move(slongsh, reg0, reg4);
580
  move(slongsh, reg1, reg5);
2 7u83 581
  regsinuse = old_regsinuse;
7 7u83 582
  invalidate_dest(reg1);
583
  invalidate_dest(reg2);
584
  invalidate_dest(reg4);
585
  invalidate_dest(reg5);
2 7u83 586
  return longs;
587
}
588
 
589
 
590
 
591
/*********************************************************************
592
   alloc_reg tries to choose registers for a value of shape sha.
593
   If there is no room, can_do of the result is 0, otherwise 1.
594
   If it can, ru_regs of result is the registers (as bit pattern)
595
   and ru_reg_free contains the bit pattern for the registers in use.
596
   rs is the bit pattern for the registers in use. All the registers must
597
   be above br (register number as integer, ie 0 for reg0 etc)
598
 
599
 *********************************************************************/
600
int  bits_in[16] = {		/* number of bits in the index */
601
  0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4
602
};
603
 
604
/* allocate registers ebx esi edi,
605
   providing br registers are left */
606
static regu alloc_reg_big
7 7u83 607
(int rs, shape sha, int br, int byteuse)
2 7u83 608
{
609
  int  sz,
610
        nr,
611
        mask,
612
        i,
613
        reg_left;		/* number of registers available */
614
  regu ru;
615
  int  noshort = 0;
616
  sz = shape_size(sha);
617
  if (sz <= 8 || byteuse)
618
    noshort = 3;
619
  nr = (sz + 31) / 32;
620
  reg_left = noreg - noshort - bits_in[rs & 0xf]
621
		 - bits_in[((unsigned int)rs >> 4) & 0x7];
622
 
623
 
624
  if ((reg_left) < (br)) {	/* can't allocate */
625
    ru.can_do = 0;
7 7u83 626
    return(ru);
2 7u83 627
  };
628
 
629
  switch (nr) {			/* number of registers needed
630
				   (consecutive) */
631
    case 1:
7 7u83 632
      mask = (noshort == 0)? bigmask1 : bigmask1ns;
2 7u83 633
      i = nobigreg - noshort;
634
      break;
635
    case 2:
636
      mask = bigmask2;
637
      i = nobigreg - 1;
638
      break;
639
    default: {
640
      SET(mask);
641
      SET(i);
7 7u83 642
      failer(WRONG_REGSIZE);
2 7u83 643
    };
644
  };
645
 
7 7u83 646
  while ((rs & mask)!= 0 && i > 0) {
2 7u83 647
    mask = (int)((unsigned int)mask >> 1);
648
    --i;
649
  };
650
 
651
  if (i > 0) {			/* allocate registers */
652
    min_rfree |= mask;
653
    ru.can_do = 1;
654
    ru.ru_regs = mask;
655
    ru.ru_reg_free = rs | mask;
656
  }
657
  else
658
    ru.can_do = 0;
659
 
7 7u83 660
  return(ru);
2 7u83 661
}
662
 
663
/* allocate registers ecx edx ebx esi edi
664
   if at least br registers are available */
665
static regu alloc_reg_small
7 7u83 666
(int rs, shape sha, int br, int byteuse)
2 7u83 667
{
668
  int  sz,
669
        nr,
670
        mask,
671
        i,
672
        reg_left;		/* number of registers left */
673
  regu ru;
674
  int  noshort = 0;
675
  sz = shape_size(sha);
676
  if (sz <= 8 || byteuse)
677
    noshort = 3;
678
  nr = (sz + 31) / 32;
679
  reg_left = noreg - noshort - bits_in[rs & 0xf]
680
		 - bits_in[((unsigned int)rs >> 4) & 0x7];
681
 
682
 
683
  if ((reg_left) < (br)) {	/* can't allocate */
684
    ru.can_do = 0;
7 7u83 685
    return(ru);
2 7u83 686
  };
687
 
688
  switch (nr) {			/* number of registers needed
689
				   (consecutive) */
690
    case 1:
691
      mask = smallmask1;
692
      i = nosmallreg;
693
      break;
694
    case 2:
695
      mask = smallmask2;
696
      i = nosmallreg - 1;
697
      break;
698
    default: {
699
      SET(mask);
700
      SET(i);
7 7u83 701
      failer(WRONG_REGSIZE);
2 7u83 702
     };
703
  };
704
 
7 7u83 705
  while ((rs & mask)!= 0 && i > 0) {
2 7u83 706
    mask = (int)((unsigned int)mask << 1);
707
    --i;
708
  };
709
 
710
  if (i > 0) {			/* allocate */
711
    min_rfree |= mask;
712
    ru.can_do = 1;
713
    ru.ru_regs = mask;
714
    ru.ru_reg_free = rs | mask;
7 7u83 715
    return(ru);
2 7u83 716
  }
717
  else
718
    return alloc_reg_big(rs, sha, br, byteuse);
719
 
720
}
721
 
722
 
723
/* allocate floating point registers, if
724
   at least br are available */
725
static regu alloc_fl_small
7 7u83 726
(int rs, int br)
2 7u83 727
{
728
  int  mask,
729
        i,
730
        reg_left;
731
  regu ru;
7 7u83 732
  reg_left = nofl - bits_in[((unsigned int)rs >> 8) & 0xf]
2 7u83 733
		- bits_in[((unsigned int)rs >> 12) & 0xf];
734
 
735
 
736
  if ((reg_left) < (br)) {	/* can't allocate */
737
    ru.can_do = 0;
7 7u83 738
    return(ru);
2 7u83 739
  };
740
 
741
  mask = smallflmask;
742
  i = nofl;
743
 
7 7u83 744
  while ((rs & mask)!= 0 && i > 0) {
2 7u83 745
    mask = (int)((unsigned int)mask << 1);
746
    --i;
747
  };
748
 
749
  if (i > 0) {			/* allocate */
750
    ru.can_do = 1;
751
    ru.ru_regs = mask;
752
    ru.ru_reg_free = rs | mask;
753
  }
754
  else
755
    ru.can_do = 0;		/* can't allocate */
756
 
7 7u83 757
  return(ru);
2 7u83 758
}
759
 
760
/* allocate all registers */
761
static regu alloc_reg
7 7u83 762
(int rs, shape sha, int br, int big_reg, exp e)
2 7u83 763
{
7 7u83 764
  if (name(sha) >= shrealhd && name(sha) <= doublehd) {
2 7u83 765
#ifdef NEWDIAGS
766
    if (big_reg || diag_visible || round_after_flop ||
767
#else
768
    if (big_reg || diagnose || round_after_flop ||
769
#endif
770
	(is80586 && isvar(e))) {
771
      regu ru;
772
      ru.can_do = 0;
7 7u83 773
      return(ru);
2 7u83 774
    }
775
    else
7 7u83 776
      return(alloc_fl_small(rs, br));
2 7u83 777
  };
778
  if (big_reg)
7 7u83 779
    return(alloc_reg_big(rs, sha, br, isbyteuse(e)));
2 7u83 780
  else
7 7u83 781
    return(alloc_reg_small(rs, sha, br, isbyteuse(e)));
2 7u83 782
}
783
 
784
 
785
/************************************************************************
786
   def_where choose where to put a declaration. e is the declaration.
787
   def is the definition (for identity) or initialisation (for variable).
788
   stack is the ash for the current stack position. The alignment for the
789
   stack on the 80386 for the cc implementation is always 32 bits, but it
790
   might not be on other implementations.
791
   The dcl returned gives
792
     dcl_pl - code for where value is (eg reg_pl for registers). These
793
              codes are defined in codermacs.h
794
     dcl_n  - the offset (in bits) where the value starts if it is on the
795
              stack.
796
              the bit pattern for the registers if it is in registers.
797
     dcl_place - the ash for the stack after the allocation. This will
798
              be the same as stack if the allocation is in registers.
799
     dcl_new - 1 if this is a new declaration. 0 if it renaming an
800
              existing value, and the old one is being reused.
801
 
802
 ************************************************************************/
803
 
804
 
805
static dcl alloc_regable
7 7u83 806
(dcl dc, exp def, exp e, int big_reg)
2 7u83 807
{
808
  where alt;
809
  int defsize = shape_size(sh(def));
810
  regu ru;
7 7u83 811
  alt = equiv_reg(mw(def, 0), defsize);
2 7u83 812
 
813
  if (alt.where_exp != nilexp) {
7 7u83 814
    int  mask = no(son(alt.where_exp));
2 7u83 815
    if (mask != 1 && (!big_reg || mask >= 0x8)) {
7 7u83 816
      if ((mask & regsinuse)!= 0 && !isvar(e) &&
817
	 (defsize > 8 || mask < 0x10)) {
818
	if (no_side(bro(son(e)))) {
2 7u83 819
	  dc.dcl_pl = reg_pl;
820
	  dc.dcl_n = mask;
821
	  dc.dcl_new = 0;
7 7u83 822
	  return(dc);
2 7u83 823
	};
824
      };
825
    };
826
  };
827
 
828
 
7 7u83 829
  if (ru = alloc_reg(regsinuse, sh(def), no(e), big_reg, e),
2 7u83 830
      ru.can_do) {
831
    if (alt.where_exp != nilexp) {
7 7u83 832
      int  mask = no(son(alt.where_exp));
2 7u83 833
      if (mask != 1 && (!big_reg || mask >= 0x8)) {
834
	if ((mask & regsinuse) == 0 &&
7 7u83 835
	   (defsize > 8 || mask < 0x10)) {
2 7u83 836
	  dc.dcl_pl = reg_pl;
837
	  dc.dcl_n = mask;
7 7u83 838
	  return(dc);
2 7u83 839
	};
840
      };
841
    };
842
 
843
    dc.dcl_pl = reg_pl;
844
    dc.dcl_n = ru.ru_regs;
7 7u83 845
    return(dc);
2 7u83 846
  };
847
  dc.dcl_pl = 0;
7 7u83 848
  return(dc);
2 7u83 849
}
850
 
851
static dcl def_where
7 7u83 852
(exp e, exp def, ash stack)
2 7u83 853
{
854
  int big_reg = has_intnl_call(e);
855
  dcl dc;
856
  ash locash;
7 7u83 857
  exp body = bro(def);
2 7u83 858
  dc.dcl_place = stack;
859
  dc.dcl_new = 1;
860
 
861
 
7 7u83 862
  if (name(sh(def)) == tophd && !isvis(e)) {
2 7u83 863
    dc.dcl_pl = nowhere_pl;
864
    dc.dcl_n = 0;
7 7u83 865
    return(dc);
2 7u83 866
  };
867
 
868
  if (name(def) == name_tag && !isvar(son(def)) &&
869
        no(def) == 0 && isloadparam(def)) {
7 7u83 870
    if (regable(e) && (name(son(son(def))) ==formal_callee_tag ?
2 7u83 871
			 !has_same_callees : !has_tail_call)) {
872
	dcl ndc;
7 7u83 873
	ndc = alloc_regable(dc, def, e, big_reg);
2 7u83 874
	if (ndc.dcl_pl != 0)		/* local copy of arg in register */
7 7u83 875
	  return(ndc);
2 7u83 876
    };
7 7u83 877
    dc.dcl_pl = ptno(son(def));
878
    dc.dcl_n = no(son(def));
2 7u83 879
    dc.dcl_new = 0;
880
    return dc;
881
  };
882
 
883
 
7 7u83 884
  if (!isvar(e) &&
885
     ((name(def) == name_tag && !isvar(son(def)) &&
886
	 (!isglob(son(def)))
2 7u83 887
	) ||
7 7u83 888
	(name(def) == cont_tag && name(son(def)) == name_tag &&
889
	  isvar(son(son(def))) &&
890
	 (!isglob(son(son(def)))) &&
2 7u83 891
 
892
	  no_side(body)))) {
893
    /* either we are identifying something already identified or the
894
       contents of a variable which is not altered by the body of the
895
       definition */
7 7u83 896
    if (name(def) == name_tag) {
897
      dc.dcl_pl = ptno(son(def));
898
      dc.dcl_n = no(son(def)) + no(def);
2 7u83 899
    }
900
    else {
7 7u83 901
      dc.dcl_pl = ptno(son(son(def)));
902
      dc.dcl_n = no(son(son(def))) + no(son(def));
2 7u83 903
    };
904
    /* we have the declaration */
905
 
906
    if (dc.dcl_pl == reg_pl) {	/* if the old one was in registers, reuse
907
				   it. */
908
      dc.dcl_new = 0;
7 7u83 909
      return(dc);
2 7u83 910
    };
911
 
7 7u83 912
    if (regable(e)) {
2 7u83 913
	dcl ndc;
7 7u83 914
	ndc = alloc_regable(dc, def, e, big_reg);
2 7u83 915
	if (ndc.dcl_pl != 0)
7 7u83 916
	  return(ndc);
2 7u83 917
    };
918
 
919
    dc.dcl_new = 0;		/* if there was not room, reuse the old
920
				   dec */
7 7u83 921
    return(dc);
2 7u83 922
 
923
  };
924
 
925
  /* try to allocate in registers, except when narrowing fp variety */
7 7u83 926
  if (regable(e) &&
927
	(name(def)!= chfl_tag || name(sh(def)) >= name(sh(son(def))))) {
2 7u83 928
    dcl ndc;
7 7u83 929
    ndc = alloc_regable(dc, def, e, big_reg);
2 7u83 930
    if (ndc.dcl_pl != 0)
7 7u83 931
      return(ndc);
2 7u83 932
  };
933
 
934
 
935
  /* otherwise allocate on the stack */
936
 
937
  {
938
    int a = 32;
939
    shape s = sh(def);
940
    if (stack_aligned_8byte && (name(s) == realhd ||
941
			(name(s) == nofhd && ptno(s) == realhd)))
942
      a = 64;
943
 
944
    locash.ashalign = 32;
945
    dc.dcl_n = rounder(stack.ashsize, a);
946
 
947
    locash.ashsize = dc.dcl_n + shape_size(sh(def));
948
 
949
    dc.dcl_place = locash;
950
    dc.dcl_pl = local_pl;
7 7u83 951
    return(dc);
2 7u83 952
  };
953
 
954
}
955
 
956
/***********************************************************************
957
   solve produces the code for the solve construction.
958
    s is the whole list of braches
959
    l is the branches of which the label record have not been created.
960
    dest is the destination for the value produced by each branch
961
    jr is the jump record for the end of the construction.
962
    stack is the initial stack ash
963
 ***********************************************************************/
964
 
965
 
966
static void solve
7 7u83 967
(exp s, exp l, where dest, exp jr, ash stack)
2 7u83 968
{
969
  while (!last (l)) {		/* not the last branch */
7 7u83 970
    exp record = getexp(f_bottom, nilexp,
971
       (bool)(props(son(bro(l))) & 2),
2 7u83 972
        nilexp,
973
	nilexp, 0, 0, 0);
974
    sonno(record) = stack_dec;
975
    ptno(record) = next_lab();
976
    fstack_pos_of(record) = (prop)fstack_pos;	/* CAST:jmf: */
977
    /* record the floating point stack position, fstack_pos */
978
    /* record is jump record for the label */
979
    pt (son (bro (l))) = record;/* put it away */
7 7u83 980
    l = bro(l);
2 7u83 981
  };
982
 
983
  {
984
    int  r1 = regsinuse;	/* record regsinuse for the start of each
985
				   branch and for the end. */
986
    exp t;
7 7u83 987
    if (name(s)!= goto_tag || pt(s)!= bro(s))
2 7u83 988
      coder (dest, stack, s);	/* code the starting exp */
989
#ifdef NEWDIAGS
990
    else
7 7u83 991
      diag_arg(dest, stack, s);
2 7u83 992
#endif
993
    reset_fpucon();
994
    t = s;
995
    do {
996
      regsinuse = r1;
7 7u83 997
      if (name(sh(t))!= bothd) {
998
	jump(jr, in_fstack(dest.where_exp));
2 7u83 999
      };
1000
      /* only put in jump if needed */
7 7u83 1001
      t = bro(t);
1002
      align_label(2, pt(son(t)));
1003
      set_label(pt(son(t)));
1004
      coder(dest, stack, t);
2 7u83 1005
      reset_fpucon();
1006
    }
7 7u83 1007
    while (!last(t));
2 7u83 1008
    regsinuse = r1;
1009
    return;
1010
  }
1011
}
1012
 
1013
/**************************************************************************
1014
   caser produces the code for the case construction e, putting the
1015
   result into dest.
1016
 *************************************************************************/
1017
 
1018
static void caser
7 7u83 1019
(exp arg, int exhaustive, exp case_exp)
2 7u83 1020
{
1021
  exp t = arg;
1022
  int  n;
1023
  int i;
1024
  int *v;
1025
  int  sz;
1026
  int min;
1027
  int max;
1028
 
1029
  min=no(bro(arg));
1030
  do
1031
  {
1032
    t=bro(t);
1033
  }
1034
  while (bro(t)!=nilexp);
7 7u83 1035
  max= ((son(t) ==nilexp)? no(t): no(son(t)));
2 7u83 1036
 
1037
 
1038
  /* prepare to use jump table */
7 7u83 1039
  v = (int *)xcalloc(max - min + 1, sizeof(int));
2 7u83 1040
  for (i = 0; i < (max - min + 1); ++i)
1041
    v[i] = -1;
1042
  t = arg;
1043
  do {
1044
    exp lab;
7 7u83 1045
    t = bro(t);
2 7u83 1046
    lab = final_dest(pt(t));
7 7u83 1047
    n = ptno(pt(son(lab)));
1048
    for (i = no(t);
1049
	i <= ((son(t) == nilexp)? no(t): no(son(t)));
2 7u83 1050
	++i)
1051
      v[i - min] = n;
1052
  }
7 7u83 1053
  while (bro(t)!= nilexp);
2 7u83 1054
 
7 7u83 1055
  switch (name(sh(arg)))EXHAUSTIVE {
2 7u83 1056
    case scharhd:
1057
    case ucharhd:
1058
      sz = 8;
1059
      break;
1060
    case swordhd:
1061
    case uwordhd:
1062
      sz = 16;
1063
      break;
1064
    case slonghd:
1065
    case ulonghd:
1066
      sz = 32;
1067
      break;
1068
  };
1069
 
7 7u83 1070
  caseins(sz, arg, min, max,v, exhaustive, 0 , case_exp);
2 7u83 1071
		/* put in jump table */
1072
  return;
1073
}
1074
 
1075
 
1076
/********************************************************************
1077
   coder produces code for all constructions. It uses codec to
1078
   produce the code for the non side-effecting constructions. e is
1079
   the construction to be processed, dest is where the result is to go,
1080
   stack is the ash for the current stack.
1081
 ********************************************************************/
1082
 
1083
static ash stack_room
7 7u83 1084
(ash stack, where dest, int off)
2 7u83 1085
{
1086
  if (name(dest.where_exp) == ident_tag)
1087
   {
7 7u83 1088
     if (ptno(dest.where_exp)!= local_pl)
2 7u83 1089
       return stack;
1090
     if ((no(dest.where_exp) + off) > stack.ashsize)
1091
       stack.ashsize = no(dest.where_exp) + off;
1092
   };
1093
 
1094
  return stack;
1095
}
1096
 
1097
 
1098
 
1099
#ifdef NEWDIAGS
1100
static void coder1
1101
#else
1102
void coder
1103
#endif
7 7u83 1104
(where dest, ash stack, exp e)
2 7u83 1105
{
1106
  float old_scale;
7 7u83 1107
  switch (name(e)) {
2 7u83 1108
    case ident_tag:
1109
      {
7 7u83 1110
	exp def = son(e);
1111
	exp body = bro(def);
2 7u83 1112
	int  sz;
1113
	dcl dc;
1114
	int  old_fstack_pos;
1115
	if (isinlined(e) && dest.where_off == 0 &&
1116
		name(dest.where_exp) == ident_tag &&
7 7u83 1117
		(!has_intnl_call(e) || ptno(dest.where_exp)!= reg_pl ||
1118
		  (no(dest.where_exp) > 4 && no(dest.where_exp) < smallflmask))) {
2 7u83 1119
	  dc.dcl_pl = ptno(dest.where_exp);
1120
	  dc.dcl_n = no(dest.where_exp);
1121
	  dc.dcl_place.ashsize = stack.ashsize + shape_size(sh(def));
1122
	  dc.dcl_place.ashalign = 32;
1123
	  dc.dcl_new = 1;
1124
	}
1125
	else
1126
	  dc = def_where (e, def, stack);/* allocate space */
1127
 
1128
	sz = (dc.dcl_place).ashsize;
1129
 
1130
 
1131
	ptno (e) = dc.dcl_pl;	/* record the allocation in pt and no for
1132
				   when the value is used. */
7 7u83 1133
	no(e) = dc.dcl_n;
2 7u83 1134
 
7 7u83 1135
	if (ptno(e) == reg_pl && name(sh(def)) >= shrealhd &&
1136
	    name(sh(def)) <= doublehd) {
2 7u83 1137
	  /* if the value being defined is going in the floating point
1138
	     registers, record the floating point stack level, so that we
1139
	     can ensure that it is the same at the end of the construction
1140
	     */
1141
	  old_fstack_pos = fstack_pos;
1142
	};
1143
 
1144
        if (isenvoff(e)) {
1145
          set_env_off(-dc.dcl_n, e);
1146
        };
1147
 
1148
	if (dc.dcl_new) {	/* if it is new we must evaluate the def
1149
				*/
7 7u83 1150
	  if (ptno(e) == nowhere_pl)
2 7u83 1151
	    coder (zero, stack, def);/* discard the value */
1152
	  else
1153
           {
7 7u83 1154
	    coder(mw(e, 0), stack, def);
2 7u83 1155
           };
1156
 
7 7u83 1157
	  if (ptno(e) == reg_pl) {
2 7u83 1158
	    /* modify regsinuse if a register is being used */
1159
	    regsinuse |= dc.dcl_n;
1160
	  };
7 7u83 1161
	  if (ptno(e) == local_pl) {
2 7u83 1162
	    /* modify max_stack if the stack is being used */
1163
	    if (sz > max_stack)
1164
	      max_stack = sz;
1165
	  };
1166
	};
1167
 
1168
	coder (dest, dc.dcl_place, body);/* code the body */
1169
 
7 7u83 1170
	if (dc.dcl_new && ptno(e) == reg_pl) {
2 7u83 1171
	  regsinuse &= ~dc.dcl_n;/* restore regsinuse. It is done by
1172
				   removing the bits of this allocation,
1173
				   rather than restoring the old value, so
1174
				   that allocation and restoration need
1175
				   not nest */
7 7u83 1176
	  if (name(sh(def)) >= shrealhd && name(sh(def)) <= doublehd &&
1177
	      fstack_pos != (SET(old_fstack_pos)old_fstack_pos) &&
1178
	      ptno(e) == reg_pl &&
1179
	      name(sh(e))!= bothd) {
2 7u83 1180
	    /* restore the floating point registers if necessary */
1181
 
7 7u83 1182
	    if (ptno(e) == reg_pl &&
1183
		!in_fstack(dest.where_exp)) {
1184
	      int   rn = get_reg_no(no(e));
2 7u83 1185
	      if (rn == fstack_pos)
7 7u83 1186
		discard_fstack();
2 7u83 1187
	      else {
1188
		if (rn < fstack_pos)
7 7u83 1189
		  discard_st1();
2 7u83 1190
	      };
1191
	    };
1192
	  };
1193
	};
1194
 
7 7u83 1195
	if (dc.dcl_new && ptno(e) == local_pl) {
1196
	  exp temp = getexp(f_top, nilexp, 1, e, nilexp, 0, 0, name_tag);
2 7u83 1197
	  if (isvar(e))
7 7u83 1198
	    temp = getexp(f_top, nilexp, 1, temp, nilexp, 0, 0, cont_tag);
1199
	  invalidate_dest(mw(temp, 0));
2 7u83 1200
	  if (isvar(e))
7 7u83 1201
	    retcell(son(temp));
1202
	  retcell(temp);
2 7u83 1203
	}
1204
 
1205
	if (isenvoff(e)) {	/* prepare for possible later constant evaluation */
7 7u83 1206
	  hasenvoff_list = getexp(f_bottom, hasenvoff_list, 0, e, nilexp, 0, 0, 0);
2 7u83 1207
	}
1208
 
1209
	return;
1210
      };
1211
    case seq_tag:
1212
      {
7 7u83 1213
	exp t = son(son(e));
2 7u83 1214
	int no_bottom;
7 7u83 1215
	while (coder(zero, stack, t),
2 7u83 1216
	/* code and discard the statements */
7 7u83 1217
	    no_bottom = (name(sh(t))!= bothd),
1218
	    !last(t))
1219
	  t = bro(t);
2 7u83 1220
	if (no_bottom)
7 7u83 1221
	  coder(dest, stack, bro(son(e)));
2 7u83 1222
#ifdef NEWDIAGS
1223
	else
1224
	if (diagnose) {			/* Beware lost information !!! */
1225
	  name(bro(son(e))) = top_tag;
1226
	  son(bro(son(e))) = nilexp;
1227
	  dgf(bro(son(e))) = nildiag;
1228
	}
1229
#endif
1230
	return;
1231
      };
1232
    case cond_tag:
1233
      {
1234
	int  old_fstack_pos = fstack_pos;
7 7u83 1235
	exp first = son(e);
1236
	exp alt = bro(first);
2 7u83 1237
	exp record;	/* jump record for alt */
1238
	int  r1;
1239
	exp jr = nilexp;/* jump record for end of construction */
1240
 
7 7u83 1241
	if (no(son(alt)) == 0) {
2 7u83 1242
	  coder(dest, stack, first);
1243
#ifdef NEWDIAGS
1244
	  if (diagnose) {		/* Beware lost information !!! */
1245
	    name(bro(son(alt))) = top_tag;
1246
	    son(bro(son(alt))) = nilexp;
1247
	    dgf(bro(son(alt))) = nildiag;
1248
	  }
1249
#endif
1250
	  return;
1251
	};
1252
 
1253
	clean_stack();
1254
 
1255
 
7 7u83 1256
	record = getexp(f_bottom, nilexp, 0,
2 7u83 1257
	      nilexp, nilexp,
1258
	      0, 0, 0);
1259
        sonno(record) = stack_dec;
1260
        fstack_pos_of(record) = (prop)fstack_pos;
7 7u83 1261
	if (pt(son(alt))!= nilexp)
2 7u83 1262
	    ptno(record) = ptno(pt(son(alt)));
1263
	else
1264
            ptno(record) = next_lab();
1265
 
1266
 
7 7u83 1267
	if (name(bro(son(alt))) == top_tag && stack_dec == 0 && !is_loaded_lv(alt)) {
2 7u83 1268
	  int extract = take_out_of_line(first, alt, repeat_level > 0, scale);
1269
 
1270
	  if (extract) {
1271
	    exp t = son(son(first));
1272
	    exp p, s, z;
1273
	    int test_n;
1274
	    shape sha;
1275
	    outofline * rec;
7 7u83 1276
	    exp tst = (is_tester(t, 0))? t : bro(son(t));
1277
	      jr = getexp(f_bottom, nilexp, 0, nilexp, nilexp, 0,
2 7u83 1278
	        0, 0);
1279
              sonno(jr) = stack_dec;
1280
              ptno(jr) = next_lab();
1281
              fstack_pos_of(jr) = (prop)fstack_pos;
1282
	    sha = sh(son(tst));
1283
	    rec = (outofline*)xmalloc(sizeof(outofline));
1284
	    rec->next = odd_bits;
1285
	    odd_bits = rec;
1286
	    rec->dest = dest;
1287
	    rec->stack = stack;
1288
	    rec->regsinuse = regsinuse;
1289
	    rec->fstack_pos = fstack_pos;
1290
	    rec->labno = next_lab();	/* number for outofline bit */
1291
	    rec->repeat_level = repeat_level;
1292
	    rec->scale = (float)0.5 * scale;
1293
	    rec->jr = jr;	/* jump record for return from bit */
1294
 
1295
	    if (last(t))
1296
	      first = bro(son(first));
1297
	    else
1298
	      son(son(first)) = bro(son(son(first)));
1299
 
1300
	    rec->body = first;
7 7u83 1301
	    pt(son(alt)) = record;
2 7u83 1302
 
1303
	    test_n = (int)test_number(tst);
1304
	    if (name(sha) < shrealhd || name(sha) > doublehd)
1305
	      test_n = (int)int_inverse_ntest[test_n];
1306
	    else
1307
	      test_n = (int)real_inverse_ntest[test_n];
1308
 
1309
	    settest_number(tst, test_n);
7 7u83 1310
	    z = getexp(f_bottom, nilexp, 0, nilexp, nilexp, 0, 0, 0);
2 7u83 1311
	    sonno(z) = stack_dec;
1312
	    fstack_pos_of(z) = (prop)fstack_pos;
1313
	    ptno(z) = rec->labno;
1314
	    s = getexp(sha, nilexp, 0, nilexp, z, 0, 0, 0);
1315
	    p = getexp(sha, tst, 0, s, nilexp, 0, 0, 0);
1316
	    pt(tst) = p;
1317
	    coder(zero, stack, t);
7 7u83 1318
	    if (name(sh(first))!= bothd) {
2 7u83 1319
	      reset_fpucon();
1320
	      set_label(jr);
1321
#ifdef NEWDWARF
7 7u83 1322
	      START_BB();
2 7u83 1323
#endif
1324
	      clear_reg_record(crt_reg_record);
1325
	    };
1326
 
1327
	    rec->cond1_set = cond1_set;
1328
	    rec->cond2_set = cond2_set;
1329
	    rec->cond1 = cond1;
1330
	    rec->cond2a = cond2a;
1331
	    rec->cond2b = cond2b;
1332
#if 0
1333
#ifdef NEWDWARF
1334
	    if (dwarf2) {
1335
	      rec->dw2_hi = next_dwarf_label();
1336
	      rec->dw2_slave = next_dwarf_label();
7 7u83 1337
	      dw2_extend_scope(rec->labno, rec->dw2_hi, rec->dw2_slave);
2 7u83 1338
	    }
1339
#endif
1340
#endif
1341
	    return;
1342
	  };
1343
	};
1344
 
1345
        old_scale = scale;
1346
        scale = (float)0.5*scale;
1347
 
1348
	/* record floating point stack position so that we can align the
1349
	   positions */
1350
	/* jump record set up for alt */
7 7u83 1351
	pt(son(alt)) = record;
2 7u83 1352
	/* set the record in for use by jumps in first. */
1353
 
1354
	r1 = regsinuse;		/* regsinuse is the same at the start of
1355
				   first and alt, and at the end of the
1356
				   construction. */
7 7u83 1357
	coder(dest, stack, first);
2 7u83 1358
	reset_fpucon();
1359
	clean_stack();
1360
 
1361
	regsinuse = r1;		/* restore regsinuse for alt */
1362
 
7 7u83 1363
	if (name(bro(son(alt))) == top_tag && !is_loaded_lv(alt)) {
2 7u83 1364
	  /* if alt is only load top, do nothing but set the label */
7 7u83 1365
	  if (name(sh(first)) == bothd && no(son(alt))!= 0)
2 7u83 1366
	    align_label(2, record);
1367
 
1368
	  if (name(first) == seq_tag &&
1369
		  name(bro(son(first))) == seq_tag &&
1370
		  name(bro(son(bro(son(first))))) == apply_tag)
1371
	    align_label(0, record);
7 7u83 1372
	  set_label(record);
2 7u83 1373
#ifdef NEWDWARF
7 7u83 1374
	  START_BB();
2 7u83 1375
#endif
1376
	  fstack_pos = old_fstack_pos;
7 7u83 1377
	  clear_reg_record(crt_reg_record);
2 7u83 1378
          scale = old_scale;
1379
	  return;
1380
	};
1381
 
7 7u83 1382
	if (name(sh(first))!= bothd &&
1383
		(no(son(alt))!= 0 || name(bro(son(alt)))!= goto_tag)) {
2 7u83 1384
	  /* if the first did not end with jump or ret, put in a jump to
1385
	     the end of the construction, and make a jump record for it */
7 7u83 1386
	    jr = getexp(f_bottom, nilexp, 0, nilexp, nilexp, 0,
2 7u83 1387
	        0, 0);
1388
            sonno(jr) = stack_dec;
1389
            ptno(jr) = next_lab();
1390
            fstack_pos_of(jr) = (prop)fstack_pos;
7 7u83 1391
	  jump(jr, in_fstack(dest.where_exp));
2 7u83 1392
	};
1393
 
7 7u83 1394
	if (no(son(alt))!= 0 || name(bro(son(alt)))!= goto_tag) {
1395
	if (no(son(alt))!= 0)
2 7u83 1396
          align_label(2, record);
1397
	set_label (record);	/* the label for the start of alt */
1398
	fstack_pos = old_fstack_pos;
7 7u83 1399
	coder(dest, stack, alt);
2 7u83 1400
	reset_fpucon();
1401
	regsinuse = r1;		/* restore regsinuse for end of
1402
				   construction */
7 7u83 1403
	if (name(sh(first))!= bothd) {
2 7u83 1404
	  /* set the label for the end of the construction if first needed
1405
	     it. */
1406
	  SET(jr);
1407
	  if (name(sh(alt)) == bothd)
1408
	    align_label(2, jr);
7 7u83 1409
	  set_label(jr);
2 7u83 1410
#ifdef NEWDWARF
7 7u83 1411
	  START_BB();
2 7u83 1412
#endif
1413
	};
1414
      };
1415
	cond1_set = 0;
1416
	cond2_set = 0;		/* we don't know what condition flags are
1417
				   set */
1418
        scale = old_scale;
1419
	return;
1420
      };
1421
    case labst_tag: 		/* code a labelled statement */
1422
      {
7 7u83 1423
	clear_reg_record(crt_reg_record);
2 7u83 1424
	cond1_set = 0;
1425
	cond2_set = 0;
1426
	fpucon = normal_fpucon;
1427
 
1428
        if (is_loaded_lv(e)) {
1429
	  set_lv_label(e);
1430
	  if (need_preserve_stack)
7 7u83 1431
	    restore_stack();
2 7u83 1432
	  else if (!has_alloca)
1433
            set_stack_from_bp();
1434
	};
1435
        fstack_pos = (int)fstack_pos_of(pt(son(e)));
1436
        stack_dec = sonno(pt(son(e)));
1437
 
1438
        old_scale = scale;
1439
#ifdef NEWDWARF
7 7u83 1440
	START_BB();
2 7u83 1441
#endif
7 7u83 1442
	coder(dest, stack, bro(son(e)));
2 7u83 1443
        scale = old_scale;
1444
 
7 7u83 1445
	clear_reg_record(crt_reg_record);
2 7u83 1446
	clean_stack();
1447
	return;
1448
      };
1449
    case rep_tag:
1450
      {
7 7u83 1451
	exp start = son(e);
1452
	exp body = bro(start);
2 7u83 1453
	exp record;		/* jump record for loop label */
1454
        ++repeat_level;
7 7u83 1455
	coder(mw(body, 0), stack, start);
2 7u83 1456
	/* code the starter of the loop */
1457
	reset_fpucon();
1458
	clean_stack();
7 7u83 1459
	record = getexp(f_bottom, nilexp, 1, nilexp,
2 7u83 1460
	    nilexp, 0, 0, 0);
1461
        sonno(record) = stack_dec;
1462
        ptno(record) = next_lab();
1463
        fstack_pos_of(record) = (prop)fstack_pos;
1464
	cond1_set = 0;
1465
	cond2_set = 0;
1466
        align_label(1, record);
1467
	set_label (record);	/* set the label at the start of body */
7 7u83 1468
	pt(son(body)) = record;
2 7u83 1469
        old_scale = scale;
1470
        if (scale < 1e30)
1471
		scale = (float)20.0 * scale;
7 7u83 1472
	coder(dest, stack, body);
2 7u83 1473
        scale = old_scale;
1474
        --repeat_level;
1475
	return;
1476
      };
1477
    case prof_tag:
1478
      scale = (float)no(e);
1479
      return;
1480
    case goto_tag:
1481
      {
1482
	exp lab;
1483
        clean_stack();
1484
	lab = final_dest(pt(e));
1485
#ifdef NEWDWARF
1486
	if (current_dg_info) {
7 7u83 1487
	  current_dg_info->data.i_tst.brk = set_dw_text_label();
1488
	  current_dg_info->data.i_tst.jlab.u.l = ptno(pt(son(lab)));
2 7u83 1489
	  current_dg_info->data.i_tst.jlab.k = LAB_CODE;
1490
	}
1491
#endif
1492
	if (label_is_next(lab, e)) {
7 7u83 1493
	  int  fs_dest = (int)fstack_pos_of(pt(son(lab)));
2 7u83 1494
	  int  good_fs = fstack_pos;
1495
	  while (fstack_pos > fs_dest)
7 7u83 1496
	    discard_fstack();
2 7u83 1497
	  reset_fpucon();
1498
	  fstack_pos = good_fs;
1499
	  return;
1500
	};
7 7u83 1501
	jump(pt(son(lab)), 0);
2 7u83 1502
	return;
1503
      };
1504
    case goto_lv_tag:
1505
      {
1506
	clean_stack();
1507
	reset_fpucon();
1508
        jumpins(son(e));
1509
        return;
1510
      };
1511
    case long_jump_tag:
1512
      {
7 7u83 1513
	coder(pushdest, stack, bro(son(e)));
2 7u83 1514
	extra_stack += 32;
7 7u83 1515
	coder(pushdest, stack, son(e));
2 7u83 1516
	extra_stack += 32;
1517
	check_stack_max;
1518
	reset_fpucon();
1519
	long_jump(e);
1520
	extra_stack -= 64;
1521
	return;
1522
      };
1523
    case testbit_tag:
1524
      {				/* not more than one argument will not be
1525
				   a possible 80386 operand */
1526
	exp lab = pt(e);
1527
	exp temp;
1528
	ntest testno = test_number(e);
1529
	int isret = 0;
1530
 
1531
	if (name(lab) == labst_tag) {
1532
	  exp q = short_next_jump(e);
1533
	  if (q != nilexp &&
1534
		(name(q) == goto_tag ||
7 7u83 1535
		  (name(q) == res_tag && name(son(q)) == top_tag)) &&
2 7u83 1536
		label_is_next(lab, q)) {
1537
	    shape sha = sh(son(e));
1538
	    if (name(q) == goto_tag) {
1539
	      temp = pt(q);
1540
	      pt(q) = lab;
1541
	    }
1542
	    else {
7 7u83 1543
              temp = getexp(f_bottom, nilexp, 0, nilexp,
2 7u83 1544
                                nilexp, 0, 0, 0);
1545
	      ptno(temp) = crt_ret_lab;
1546
	      fstack_pos_of(temp) = (prop)first_fl_reg;
1547
	      temp = getexp(f_top, nilexp, 0, nilexp, temp,
1548
				 0, 0, 0);
1549
	      temp = getexp(f_top, lab, 0, temp, nilexp,
1550
				 0, 0, labst_tag);
1551
	      crt_ret_lab_used = 1;
1552
	      pt(q) = lab;
1553
	      name(q) = goto_tag;
1554
	      isret = 1;
1555
	    };
1556
	    lab = temp;
1557
	    pt(e) = lab;
1558
	    if (name(sha) < shrealhd || name(sha) > doublehd)
7 7u83 1559
	      settest_number(e,(int)int_inverse_ntest[testno]);
2 7u83 1560
	    else
7 7u83 1561
	      settest_number(e,(int)real_inverse_ntest[testno]);
2 7u83 1562
#ifdef NEWDIAGS
1563
	    if (current_dg_info)
1564
	      current_dg_info->data.i_tst.inv = 1 - current_dg_info->data.i_tst.inv;
1565
#endif
1566
	  };
1567
        };
1568
	if (!isret)
1569
	  temp = final_dest_test(lab, e);
1570
	SET(temp);
1571
	if (pt(son(temp)) == nilexp) {
1572
	  ++no(son(temp));
1573
	  pt(son(temp)) = copyexp(pt(son(lab)));
1574
	  ptno(pt(son(temp))) = next_lab();
1575
	}
1576
	else
1577
	if (temp != lab) {
1578
	  --no(son(lab));
1579
	  ++no(son(temp));
1580
	};
1581
	pt(e) = temp;
1582
       {
1583
	where qw;
7 7u83 1584
	exp lab_exp = pt(e);
1585
	exp jr = pt(son(lab_exp));
1586
	exp arg1 = son(e);
1587
	exp arg2 = bro(arg1);
1588
	if (!is_o(name(arg1)) || is_crc(arg1)) {
2 7u83 1589
	  /* arg1 is not a possible 80386 operand, precompute it in reg0
1590
	  */
7 7u83 1591
	  qw.where_exp = copyexp(reg0.where_exp);
1592
	  sh(qw.where_exp) = sh(arg1);
2 7u83 1593
	  qw.where_off = 0;
7 7u83 1594
	  coder(qw, stack, arg1);
2 7u83 1595
	  arg1 = qw.where_exp;
1596
	};
7 7u83 1597
	if (!is_o(name(arg2)) || is_crc(arg2)) {
2 7u83 1598
	  /* arg2 is not a possible 80386 operand, precompute it in reg0
1599
	  */
7 7u83 1600
	  qw.where_exp = copyexp(reg0.where_exp);
1601
	  sh(qw.where_exp) = sh(arg2);
2 7u83 1602
	  qw.where_off = 0;
7 7u83 1603
	  coder(qw, stack, arg2);
2 7u83 1604
	  arg2 = qw.where_exp;
1605
	};
1606
 
1607
	clean_stack();
1608
#ifdef NEWDWARF
1609
	if (current_dg_info) {
7 7u83 1610
	  current_dg_info->data.i_tst.brk = set_dw_text_label();
2 7u83 1611
	  current_dg_info->data.i_tst.jlab.u.l = ptno(jr);
1612
	  current_dg_info->data.i_tst.jlab.k = LAB_CODE;
1613
	}
1614
#endif
7 7u83 1615
	test(sh(arg1), mw(arg1, 0), mw(arg2, 0));
1616
	branch((int)test_number(e), jr, 1,(int)name(sh(arg1)));
2 7u83 1617
#ifdef NEWDWARF
7 7u83 1618
	START_BB();
2 7u83 1619
	if (current_dg_info)
7 7u83 1620
	  current_dg_info->data.i_tst.cont = set_dw_text_label();
2 7u83 1621
#endif
1622
	return;
1623
       };
1624
      };
1625
    case absbool_tag:
1626
    case test_tag:
1627
      {				/* not more than one argument will not be
1628
				   a possible 80386 operand */
1629
	exp lab = pt(e);
1630
	exp temp;
1631
	ntest testno = test_number(e);
1632
	int isret = 0;
1633
	exp original_lab = lab;		/* preserve for extra_diags */
1634
 
1635
	if (name(e) == test_tag) {
1636
	  if (name(lab) == labst_tag) {
1637
	    exp q = short_next_jump(e);
1638
	    if (q != nilexp &&
7 7u83 1639
		 (name(q) == goto_tag ||
1640
		    (name(q) == res_tag && name(son(q)) == top_tag)) &&
2 7u83 1641
		  label_is_next(lab, q)) {
1642
	      shape sha = sh(son(e));
1643
	      if (name(q) == goto_tag) {
1644
	        temp = pt(q);
1645
	        pt(q) = lab;
1646
	      }
1647
	      else {
7 7u83 1648
                temp = getexp(f_bottom, nilexp, 0, nilexp,
2 7u83 1649
                                nilexp, 0, 0, 0);
1650
		ptno(temp) = crt_ret_lab;
1651
		fstack_pos_of(temp) = (prop)first_fl_reg;
1652
	        temp = getexp(f_top, nilexp, 0, nilexp, temp,
1653
				 0, 0, 0);
1654
	        temp = getexp(f_top, lab, 0, temp, nilexp,
1655
				 0, 0, labst_tag);
1656
		crt_ret_lab_used = 1;
1657
	        pt(q) = lab;
1658
	        name(q) = goto_tag;
1659
	        isret = 1;
1660
	      };
1661
	      lab = temp;
1662
	      pt(e) = lab;
1663
	      if (name(sha) < shrealhd || name(sha) > doublehd)
7 7u83 1664
	        settest_number(e,(int)int_inverse_ntest[testno]);
2 7u83 1665
	      else
7 7u83 1666
	        settest_number(e,(int)real_inverse_ntest[testno]);
2 7u83 1667
#ifdef NEWDIAGS
1668
	      if (current_dg_info)
1669
		current_dg_info->data.i_tst.inv = 1 - current_dg_info->data.i_tst.inv;
1670
#endif
1671
	    };
1672
          };
1673
	  if (!isret)
1674
	    temp = final_dest_test(lab, e);
1675
	  SET(temp);
1676
	  if (pt(son(temp)) == nilexp) {
1677
	    ++no(son(temp));
1678
	    pt(son(temp)) = copyexp(pt(son(lab)));
1679
	    ptno(pt(son(temp))) = next_lab();
1680
	  }
1681
	  else
1682
	  if (temp != lab) {
1683
	    --no(son(lab));
1684
	    ++no(son(temp));
1685
	  };
1686
	  pt(e) = temp;
1687
	};
1688
	{
1689
	  where qw;
7 7u83 1690
	  exp arg1 = son(e);
1691
	  exp arg2 = bro(arg1);
1692
	  unsigned char  test_n = test_number(e);
1693
	  exp lab_exp = pt(e);
2 7u83 1694
	  exp jr;
1695
	  int sg;
7 7u83 1696
	  if (name(e) ==test_tag)
1697
	    jr = pt(son(lab_exp));
1698
	  if (!is_o(name(arg1)) || is_crc(arg1)) {
2 7u83 1699
	    /* arg1 is not a possible 80386 operand, precompute it in reg0
1700
	       */
7 7u83 1701
	    qw.where_exp = copyexp(reg0.where_exp);
1702
	    sh(qw.where_exp) = sh(arg1);
2 7u83 1703
	    qw.where_off = 0;
7 7u83 1704
	    coder(qw, stack, arg1);
2 7u83 1705
	    arg1 = qw.where_exp;
1706
	  }
1707
#ifdef NEWDIAGS
1708
	  else
7 7u83 1709
	    diag_arg(dest, stack, arg1);
2 7u83 1710
#endif
7 7u83 1711
	  if (!is_o(name(arg2)) || is_crc(arg2)) {
2 7u83 1712
	    /* arg2 is not a possible 80386 operand, precompute it in reg0
1713
	       */
7 7u83 1714
	    qw.where_exp = copyexp(reg0.where_exp);
1715
	    sh(qw.where_exp) = sh(arg2);
2 7u83 1716
	    qw.where_off = 0;
7 7u83 1717
	    coder(qw, stack, arg2);
2 7u83 1718
	    arg2 = qw.where_exp;
1719
	  }
1720
#ifdef NEWDIAGS
1721
	  else
7 7u83 1722
	    diag_arg(dest, stack, arg2);
2 7u83 1723
#endif
1724
 
7 7u83 1725
	  switch (name(sh(arg1))) {
2 7u83 1726
	    case scharhd:
1727
	    case swordhd:
1728
	    case slonghd:
1729
	    case offsethd:
1730
	      sg = 1;
1731
	      break;
1732
	    case ucharhd:
1733
	    case uwordhd:
1734
	    case ulonghd:
1735
	    case shrealhd:
1736
	    case realhd:
1737
	    case doublehd:
1738
	    case ptrhd:
1739
	      sg = 0;
1740
	      break;
1741
	    default:
1742
	      sg = is_signed(sh(arg1));
1743
	      break;
1744
	  };
1745
 
7 7u83 1746
	  if (name(arg1) == val_tag || name(arg1) == env_offset_tag ||
1747
		(name(arg1) == name_tag && isvar(son(arg1)) && isglob(son(arg1)))) {
2 7u83 1748
		/* if only one constant, cmp expects it to be arg2 */
1749
	    exp holde = arg1;
1750
	    arg1 = arg2;
1751
	    arg2 = holde;
1752
	    test_n = exchange_ntest[test_n];
1753
#ifdef NEWDIAGS
1754
	    if (current_dg_info)
1755
	      current_dg_info->data.i_tst.inv = 1 - current_dg_info->data.i_tst.inv;
1756
#endif
1757
	  };
1758
 
7 7u83 1759
	  if (name(arg1) == null_tag) {
2 7u83 1760
	    failer("test_tag of wrong form");
1761
	  }
1762
	  else {
1763
	    clean_stack();
1764
	    if (name(e) == absbool_tag && sg &&
1765
		(test_n == f_greater_than || test_n == f_less_than_or_equal)) {
1766
	      cond1_set = 0;	/* avoid cmp(0) optimisation to clear overflow */
1767
	    }
7 7u83 1768
	    if (cmp(sh(arg1), mw(arg1, 0), mw(arg2, 0), (int)test_n, e)) {
2 7u83 1769
	      if (sg) {
1770
		sg = -1;   /* ignore overflow when testing sign bit */
1771
	      }
1772
	    }
1773
	    if (name(e) == test_tag) {
1774
	      SET(jr);
1775
#ifdef NEWDWARF
1776
	      if (current_dg_info) {
7 7u83 1777
		current_dg_info->data.i_tst.brk = set_dw_text_label();
2 7u83 1778
		current_dg_info->data.i_tst.jlab.u.l = ptno(jr);
1779
		current_dg_info->data.i_tst.jlab.k = LAB_CODE;
1780
	      }
1781
#endif
7 7u83 1782
	      branch((int)test_n, jr, sg,(int)name(sh(arg1)));
2 7u83 1783
#ifdef NEWDWARF
7 7u83 1784
	      START_BB();
2 7u83 1785
	      if (current_dg_info)
7 7u83 1786
	        current_dg_info->data.i_tst.cont = set_dw_text_label();
2 7u83 1787
#endif
1788
	    }
1789
	    else
7 7u83 1790
	    if (!eq_where(dest, zero)) {
2 7u83 1791
	      setcc((int)int_inverse_ntest[test_n], sg,
7 7u83 1792
			(int)name(sh(arg1)));
2 7u83 1793
	      if (shape_size(sh(e)) > 8)
1794
	        and(slongsh, reg0, mw(zeroe, 0xff), reg0);
1795
	      move(sh(e), reg0, dest);
1796
	    };
1797
	  };
1798
	  pt(e) = original_lab;		/* may be needed for extra_diags */
1799
	  return;
1800
	};
1801
      };
1802
    case ass_tag:
1803
    case assvol_tag:
1804
      {
7 7u83 1805
	exp assdest = son(e);
1806
	exp assval = bro(assdest);
2 7u83 1807
 
1808
        if (!newcode && name(sh(assval)) == bitfhd)
1809
         {
1810
           bits_to_mem(assval, e, stack);
1811
           return;
1812
         };
1813
 
7 7u83 1814
	coder(mw(e, 0), stack, assval);
2 7u83 1815
	/* set the destination and code the rest */
1816
	return;
1817
      };
1818
    case concatnof_tag:
1819
     {
1820
      int off = dest.where_off + shape_size(sh(son(e)));
1821
      coder(dest, stack, son(e));
1822
      coder(mw(dest.where_exp, off),
1823
             stack_room(stack, dest, off), bro(son(e)));
1824
      return;
1825
     };
1826
    case ncopies_tag:
1827
     {
1828
       int i;
1829
       int sz;
1830
       int off;
1831
       if (no(e) == 0)
1832
         return;
1833
 
7 7u83 1834
       sz = shape_size(sh(e)) /no(e);
2 7u83 1835
       for (i = 0; i < no(e); ++i)
1836
        {
1837
          off = dest.where_off + i*sz;
1838
          coder(mw(dest.where_exp, off),
1839
                stack_room(stack, dest, off), copyexp(son(e)));
1840
        };
1841
       return;
1842
      };
1843
    case nof_tag:
1844
      {
1845
        exp v = son(e);
1846
        shape sha;
1847
        int off;
1848
        int crt = 0;
1849
 
1850
        if (v == nilexp)
1851
          return;
1852
 
1853
        sha = sh(v);
1854
        off = rounder(shape_size(sha), shape_align(sha));
1855
 
1856
        while (1)
1857
         {
1858
           coder(mw(dest.where_exp, dest.where_off + crt),
1859
                 stack_room(stack, dest, dest.where_off + crt), v);
1860
           if (last(v))
1861
             return;
1862
           crt += off;
1863
           v = bro(v);
1864
         };
1865
      };
1866
    case compound_tag:
1867
      {
1868
        exp v = son(e);
1869
        if (v == nilexp)
1870
          return;
1871
 
1872
        while (1)
1873
         {
1874
           coder(mw(dest.where_exp, dest.where_off + no(v)),
1875
                 stack_room(stack, dest, dest.where_off + no(v)), bro(v));
1876
           if (last(bro(v)))
1877
             return;
1878
           v = bro(bro(v));
1879
         };
1880
      };
1881
    case apply_tag:
1882
    case apply_general_tag:
1883
      {
7 7u83 1884
	exp proc = son(e);
1885
	exp arg = (!last(proc))? bro(proc): nilexp;
2 7u83 1886
	exp cees = nilexp;
1887
	exp postlude = nilexp;
1888
	int untidy_call = 0;
1889
	int has_checkstack = 0;
1890
	int  longs, more_longs, old_regsinuse, prev_use_bp;
1891
	int multi_reg = (shape_size(sh(e)) > 32 && reg_result(sh(e))
1892
				 && !is_floating(name(sh(e))));
1893
	int old_nip = not_in_params;
1894
	int push_result = 0;
1895
	int post_offset = 0;
1896
	int ret_stack_dec;
1897
 
1898
	if (builtinproc(e)) {
7 7u83 1899
	  dec* dp = brog(son(proc));
2 7u83 1900
	  char *id = dp -> dec_u.dec_val.dec_id;
7 7u83 1901
	  special_ins(id + prefix_length, arg, dest);
2 7u83 1902
	  return;
1903
	}
1904
 
7 7u83 1905
	if (name(e) ==apply_general_tag) {
2 7u83 1906
	  arg = son(arg);
1907
	  cees = bro(bro(proc));
7 7u83 1908
	  if (name(bro(cees))!= top_tag)
2 7u83 1909
	    postlude = bro(cees);
1910
	  untidy_call = call_is_untidy(e);
1911
	  has_checkstack = call_has_checkstack(e);
1912
	}
1913
 
1914
	not_in_params = 0;
7 7u83 1915
	longs = procargs(stack, arg, has_checkstack);
2 7u83 1916
	ret_stack_dec = stack_dec;
1917
 
1918
	prev_use_bp = must_use_bp;	/* may be altered by push_cees */
1919
	if (cees == nilexp)
1920
	  more_longs = 0;
1921
	else {
1922
	  switch (name(cees)) {
1923
	    case make_callee_list_tag:
1924
	      {
7 7u83 1925
		more_longs = procargs(stack, son(cees), has_checkstack);
2 7u83 1926
		if (call_has_vcallees(cees)) {
7 7u83 1927
		  ins2(leal, 32, 32, mw(ind_sp.where_exp, more_longs), reg0);
1928
		  ins0(pusheax);
2 7u83 1929
		  stack_dec -= 32;
1930
		  more_longs += 32;
1931
		}
1932
		break;
1933
	      }
1934
	    case make_dynamic_callee_tag:
1935
	      {
1936
		exp ptr = son(cees);
1937
		exp siz = bro(ptr);
7 7u83 1938
		more_longs = push_cees(ptr, siz, call_has_vcallees(cees), stack);
2 7u83 1939
		break;
1940
	      }
1941
	    case same_callees_tag:
1942
	      {
7 7u83 1943
		more_longs = push_cees(nilexp, nilexp, call_has_vcallees(cees), stack);
2 7u83 1944
		break;
1945
	      }
1946
	  }
1947
	}
1948
 
1949
	check_stack_max;
1950
	reset_fpucon();
1951
	not_in_params = old_nip;
1952
	if (remove_struct_ref) {
1953
	  longs -= no(e);		/* struct return address removed by call */
1954
	  ret_stack_dec += no(e);
1955
	  post_offset = no(e);
1956
	}
1957
	if (postlude == nilexp && !untidy_call) {
1958
	  old_regsinuse = regsinuse;
1959
	  if (multi_reg)
1960
	    regsinuse |= 0x2;	/* prevent callins using pop edx */
7 7u83 1961
	  callins(longs, son(e), ret_stack_dec);
2 7u83 1962
	  regsinuse = old_regsinuse;
1963
	}
1964
	else {
1965
	  callins (0, son (e), ret_stack_dec);	/* delay arg stack return */
1966
	  if (untidy_call) {
1967
	    stack_dec = 0;	/* as alloca, must_use_bp */
1968
	    if (need_preserve_stack)
7 7u83 1969
	      save_stack();
2 7u83 1970
	  };
1971
	}
1972
	must_use_bp = prev_use_bp;
1973
 
7 7u83 1974
	invalidate_dest(mw(nilexp, 0));
2 7u83 1975
 
7 7u83 1976
	clear_low_reg_record(crt_reg_record);
2 7u83 1977
	cond1_set = 0;
1978
	cond2_set = 0;		/* we don't know the state of the
1979
				   conditions */
7 7u83 1980
	if (eq_where(dest, zero))
2 7u83 1981
	{
1982
	  if (reg_result (sh (e))) {/* answer in register */
7 7u83 1983
	    if (name(sh(e)) >= shrealhd && name(sh(e)) <= doublehd) {
2 7u83 1984
	      push_fl;
1985
	      discard_fstack();
1986
	    }
1987
	  }
1988
	}
1989
	else {
1990
	  where temp_dest;
1991
	  if (postlude == nilexp)
1992
	    temp_dest = dest;
1993
	  else {
1994
	    push_result = 1;
1995
	    temp_dest = pushdest;
1996
	  }
1997
	  if (reg_result (sh (e))) {/* answer in register */
7 7u83 1998
	    if (name(sh(e)) >= shrealhd && name(sh(e)) <= doublehd) {
2 7u83 1999
	      push_fl;
7 7u83 2000
	      move(sh(e), flstack, temp_dest);
2 7u83 2001
	    }
2002
	    else
7 7u83 2003
	      move(sh(e), reg0, temp_dest);
2 7u83 2004
	  }
2005
	  else
2006
	    failer(STRUCT_RES);  /* compound result */
2007
	}
2008
 
2009
	if (postlude != nilexp) {
7 7u83 2010
	  int sz = rounder(shape_size(sh(e)), param_align);
2 7u83 2011
	  old_nip = not_in_postlude;
2012
	  not_in_postlude = 0;
2013
	  while (name(postlude) == ident_tag && name(son(postlude)) == caller_name_tag) {
2014
	    int n = no(son(postlude));
2015
	    exp a = arg;
2016
	    while (n != 0) {
2017
	      a = bro(a);
2018
	      n--;
2019
	    }
7 7u83 2020
	    if (name(a)!= caller_tag)
2 7u83 2021
	      failer(BAD_POSTLUDE);
2022
	    no(postlude) = no(a) + stack_dec - post_offset;
2023
	    ptno(postlude) = callstack_pl;
2024
	    postlude = bro(son(postlude));
2025
	  }
2026
	  if (push_result) {
2027
	    stack_dec -= sz;
2028
	    check_stack_max;
2029
	  }
7 7u83 2030
	  coder(zero, stack, postlude);
2 7u83 2031
	  if (push_result) {
7 7u83 2032
	    if (name(dest.where_exp) == apply_tag) {
2 7u83 2033
	      move(sh(e), ind_sp, dest);
2034
	      stack_dec += sz;
2035
	    }
2036
	    else {
2037
	      longs += shape_size(sh(e));
2038
	      if (dest.where_exp == ind_sp.where_exp)
2039
		dest.where_off += longs;
2040
	      move(sh(e), ind_sp, dest);
2041
	    }
2042
	  }
7 7u83 2043
	  stack_return(longs);
2 7u83 2044
	  not_in_postlude = old_nip;
2045
	}
2046
 
2047
	return;
2048
      };
2049
    case tail_call_tag:
2050
      {
7 7u83 2051
	exp proc = son(e);
2 7u83 2052
	exp cees = bro(proc);
2053
	int longs;
2054
	int prev_use_bp = must_use_bp;	/* may be altered by push_cees */
2055
	int old_nip = not_in_params;
2056
	int old_stack_dec = stack_dec;
2057
	not_in_params = 0;
2058
	switch (name(cees)) {
2059
	  case make_callee_list_tag:
2060
	    {
2061
	      not_in_params = 0;
7 7u83 2062
	      longs = procargs(stack, son(cees), call_has_checkstack(e));
2 7u83 2063
	      not_in_params = old_nip;
2064
	      break;
2065
	    }
2066
	  case make_dynamic_callee_tag:
2067
	    {
7 7u83 2068
	      longs = push_cees(son(cees), bro(son(cees)), 0, stack);
2 7u83 2069
	      break;
2070
	    }
2071
	  case same_callees_tag:
2072
	    {
2073
	      longs = 0;
2074
	      break;
2075
	    }
2076
	}
2077
	check_stack_max;
2078
 
2079
	/* clear off any unwanted fstack registers */
2080
	{
2081
	  int good_fs = fstack_pos;
2082
	  while (fstack_pos > first_fl_reg)
7 7u83 2083
	    discard_fstack();
2 7u83 2084
	  fstack_pos = good_fs;
2085
	  reset_fpucon();
2086
	}
2087
 
2088
	if (longs == 0) {
2089
	  coder (reg0, stack, proc);	/* proc value to %eax */
7 7u83 2090
	  restore_callregs(0);
2 7u83 2091
		/* stack reduced to old callees and return address */
2092
 
2093
	  if (name(cees) == same_callees_tag) {
2094
	    if (callee_size < 0 && !call_has_vcallees(cees)) {
7 7u83 2095
	      outs(" popl %ecx\n");
2096
	      outs(" movl %ecx, (%esp)\n");
2 7u83 2097
	    }
2098
	    if (callee_size >= 0 && call_has_vcallees(cees)) {
7 7u83 2099
	      outs(" popl %ecx\n");
2100
	      outs(" leal "); outn((long)callee_size/8); outs("(%esp),%edx\n");
2101
	      outs(" pushl %edx\n");
2102
	      outs(" pushl %ecx\n");
2 7u83 2103
	    }
2104
	  }
2105
	  else {
2106
	    if (callee_size != 0 || call_has_vcallees(cees)) {
7 7u83 2107
	      outs(" popl %ecx\n");
2 7u83 2108
	      if (callee_size < 0) {
7 7u83 2109
		outs(" popl %edx\n");
2110
		outs(" movl %edx,%esp\n");
2 7u83 2111
	      }
2112
	      else
2113
	      if (callee_size == 0)
7 7u83 2114
		outs(" movl %esp %edx\n");
2 7u83 2115
	      else {
7 7u83 2116
		outs(" leal "); outn((long)callee_size/8); outs("(%esp),%edx\n");
2117
		outs(" movl %edx,%esp\n");
2 7u83 2118
	      }
2119
	      if (call_has_vcallees(cees))
7 7u83 2120
		outs(" pushl %edx\n");
2121
	      outs(" pushl %ecx\n");
2 7u83 2122
	    }
2123
	  }
7 7u83 2124
	  outs(" jmp *%eax\n\n");
2 7u83 2125
	}
2126
	else {
2127
			/* callees have been pushed */
2128
	  if (call_has_vcallees(cees)) {
2129
	    if (callee_size >= 0) {
7 7u83 2130
	      outs(" leal ");
2131
	      rel_ap(4 + callee_size/8, 1);
2132
	      outs(",%eax\n");
2133
	      ins0(pusheax);
2 7u83 2134
	    }
2135
	    else {
7 7u83 2136
	      outs(" pushl ");
2137
	      rel_ap(4, 1);
2 7u83 2138
	    }
2139
	    outnl();
2140
	    stack_dec -= 32;
2141
	  }
7 7u83 2142
	  outs(" pushl ");
2 7u83 2143
	  rel_ap (0, 1);	/* push return address after callees */
2144
	  outnl();
2145
	  stack_dec -= 32;
2146
	  coder (pushdest, stack, proc);	/* push proc for call by return */
2147
	  stack_dec -= 32;
2148
	  check_stack_max;
2149
	  if (longs < 0) {	/* must be dynamic_callees */
2150
	    exp sz = bro(son(cees));
7 7u83 2151
	    move(slongsh, mw(sz,0), reg2);
2 7u83 2152
	    if (al2(sh(sz)) < param_align) {
2153
	      if (al2(sh(sz)) == 1) {
7 7u83 2154
		outs(" addl $31,%ecx\n");
2155
		outs(" shrl $3,%ecx\n");
2 7u83 2156
	      }
2157
	      else
7 7u83 2158
		outs(" addl $3,%ecx\n");
2159
	      outs(" andl $-4,%ecx\n");
2 7u83 2160
	    }
2161
	  }
2162
	  if (!call_has_vcallees(cees)) {
2163
	    if (callee_size >= 0) {
7 7u83 2164
	      outs(" leal ");
2165
	      rel_ap(4 + callee_size/8, 1);
2166
	      outs(",%eax\n");
2 7u83 2167
	    }
2168
	    else {
7 7u83 2169
	      outs(" movl ");
2170
	      rel_ap(4, 1);
2171
	      outs(",%eax\n");
2 7u83 2172
	    }
2173
	  }
2174
 
7 7u83 2175
	  restore_callregs(1);
2 7u83 2176
 
2177
		/* callees, return and proc to call are stacked */
2178
		/* size in %ecx if longs<0; callers at %eax unless stacked for vcallees */
7 7u83 2179
	  outs(" pushl %esi\n");
2180
	  outs(" pushl %edi\n");
2 7u83 2181
	  if (call_has_vcallees(cees))
7 7u83 2182
	    outs(" movl 16(%esp),%edi\n");
2 7u83 2183
	  else
7 7u83 2184
	    outs(" movl %eax,%edi\n");
2 7u83 2185
	  if (longs < 0) {
7 7u83 2186
	    outs(" addl $");
2187
	    outn((long)(call_has_vcallees(cees)? 20 : 16));
2188
	    outs(", %ecx\n");
2189
	    outs(" leal -4(%esp),%esi\n");
2190
	    outs(" addl %ecx,%esi\n");
2191
	    outs(" shrl $2,%ecx\n");
2 7u83 2192
	  }
2193
	  else {
7 7u83 2194
	    outs(" movl $");
2195
	    outn((long)(longs/32 + (call_has_vcallees(cees)? 5 : 4)));
2196
	    outs(",%ecx\n");
2197
	    outs(" leal ");
2198
	    outn((long)(longs/8 + (call_has_vcallees(cees)? 16 : 12)));
2199
	    outs("(%esp),%esi\n");
2 7u83 2200
	  }
7 7u83 2201
	  outs(" subl $4,%edi\n");
2202
	  outs(" std\n rep\n movsl\n cld\n");
2203
	  outs(" leal 4(%edi),%esp\n");
2204
	  outs(" popl %edi\n");
2205
	  outs(" popl %esi\n");
2206
	  outs(" ret\n");
2 7u83 2207
	}
2208
 
2209
	cond1_set = 0;
2210
	cond2_set = 0;
2211
	stack_dec = old_stack_dec;
2212
	must_use_bp = prev_use_bp;
2213
	return;
2214
      };
2215
    case alloca_tag:
2216
      {
2217
	where sz_where;
2218
        if (name(son(e)) == val_tag)
2219
          {
2220
	    int n = no(son(e));
7 7u83 2221
	    if (name(sh(son(e)))!= offsethd)
2 7u83 2222
	      n = 8 * n;
7 7u83 2223
	    sz_where = mw(zeroe, rounder(n, stack_align) /8);
2 7u83 2224
          }
2225
        else {
2226
	  exp temp = getexp(slongsh, nilexp, 0, nilexp, nilexp, 0, 0, val_tag);
2227
          if (name(sh(son(e))) == offsethd && al2(sh(son(e))) == 1) {
2228
	    no(temp) = 31;
7 7u83 2229
	    bop(add, ulongsh, temp, son(e), reg0, stack);
2230
            shiftr(ulongsh, mw(zeroe,3), reg0, reg0);
2231
	    and(ulongsh, mw(zeroe, -4), reg0, reg0);
2 7u83 2232
	    sz_where = reg0;
2233
          }
2234
          else if (al2(sh(son(e))) < 32) {
2235
	    no(temp) = 3;
7 7u83 2236
	    bop(add, ulongsh, temp, son(e), reg0, stack);
2237
	    and(ulongsh, mw(zeroe, -4), reg0, reg0);
2 7u83 2238
	    sz_where = reg0;
2239
          }
2240
	  else {
2241
	    sz_where = reg0;
7 7u83 2242
	    coder(sz_where, stack, son(e));
2 7u83 2243
	  }
7 7u83 2244
	  retcell(temp);
2 7u83 2245
        };
2246
	if (checkalloc(e))
2247
	  checkalloc_stack(sz_where, 1);	/* uses reg1 */
2248
	else
7 7u83 2249
	  sub(ulongsh, sz_where, sp, sp);
2250
	if (!eq_where(dest, zero))
2251
	  move(sh(e), sp, dest);
2 7u83 2252
	if (need_preserve_stack)
7 7u83 2253
	  save_stack();
2 7u83 2254
	return;
2255
      };
2256
    case last_local_tag:
2257
      {
7 7u83 2258
	move(sh(e), sp, dest);
2 7u83 2259
	return;
2260
      };
2261
    case local_free_tag:
2262
        move(slongsh, mw(son(e),0), sp);
2263
        if (name(bro(son(e))) == val_tag)
2264
          {
2265
            int sz;
2266
	    int n = no(bro(son(e)));
7 7u83 2267
	    if (name(sh(bro(son(e))))!= offsethd)
2 7u83 2268
	      n = 8 * n;
2269
	    sz = rounder(n, stack_align);
2270
            add(slongsh, mw(zeroe, sz/8), sp, sp);
2271
          }
2272
	else
2273
	    add(slongsh, mw(bro(son(e)), 0), sp, sp);
2274
	add(slongsh, mw(zeroe, 3), sp, sp);
7 7u83 2275
	and(slongsh, mw(zeroe, -stack_align/8), sp, sp);
2 7u83 2276
	if (need_preserve_stack)
7 7u83 2277
	  save_stack();
2 7u83 2278
        return;
2279
    case local_free_all_tag:
2280
        set_stack_from_bp();
2281
	if (need_preserve_stack)
7 7u83 2282
	  save_stack();
2 7u83 2283
        return;
2284
    case ignorable_tag:
2285
	coder(dest, stack, son(e));
2286
	return;
2287
    case res_tag:
2288
    case untidy_return_tag:
2289
      {
2290
	int old_stack_dec = stack_dec;
2291
#ifdef NEWDWARF
2292
	long over_lab;
2293
#endif
2294
	cond1_set = 0;
2295
	cond2_set = 0;
2296
	{
2297
	  /* procedure call not inlined, this res is for a procedure */
2298
	  if (reg_result (sh (son (e)))) {/* answer to registers */
2299
	    int with_fl_reg = 0;
2300
	    /* int simple_res = (name(son(e)) == val_tag); */
2301
	    int  good_fs;
2302
 
2303
	    /* if (!simple_res) */
2304
	    {
7 7u83 2305
	      if (name(sh(son(e))) >= shrealhd &&
2306
		  name(sh(son(e))) <= doublehd) {
2307
	        coder(flstack, stack, son(e));
2 7u83 2308
	        with_fl_reg = 1;
2309
	      }
2310
	      else {
7 7u83 2311
	        coder(reg0, stack, son(e));
2 7u83 2312
	      };
2313
	    };
2314
 
7 7u83 2315
	    if (name(sh(son(e)))!= bothd) {
2 7u83 2316
	      good_fs = fstack_pos;
2317
	      if (with_fl_reg) {/* jumping with a floating value */
2318
	        /* clear off any unwanted stack registers */
2319
	        while (fstack_pos > (first_fl_reg + 1))
7 7u83 2320
	          discard_st1();
2 7u83 2321
	        fstack_pos = good_fs - 1;
2322
	      }
2323
	      else {
2324
	        /* clear off any unwanted stack registers */
2325
	         while (fstack_pos > first_fl_reg)
7 7u83 2326
	          discard_fstack();
2 7u83 2327
	        fstack_pos = good_fs;
2328
	      };
2329
	      reset_fpucon();
7 7u83 2330
	      if (name(e) ==untidy_return_tag) {
2 7u83 2331
		int old_regsinuse = regsinuse;
2332
		regsinuse &= ~0x6;	/* %ecx, %edx not preserved */
2333
		if (shape_size(sh(son(e))) > 32 && !with_fl_reg)
2334
		  regsinuse |= 0x2;	/* %edx used for return value */
2335
		if (stack_dec != 0)
7 7u83 2336
		  stack_return(- stack_dec);
2 7u83 2337
		regsinuse = old_regsinuse;
7 7u83 2338
		outs(" pushl ");
2 7u83 2339
		rel_ap (0, 1);	/* push return address for return after pops */
2340
		outnl();
2341
#ifdef NEWDWARF
2342
		if (diagnose && dwarf2)
7 7u83 2343
		  dw2_untidy_return();
2 7u83 2344
#endif
2345
	      }
2346
#ifdef NEWDWARF
2347
	      if (diagnose && dwarf2) {
7 7u83 2348
		over_lab = next_dwarf_label();
2349
		dw2_return_pos(over_lab);
2 7u83 2350
	      }
2351
#endif
7 7u83 2352
	      restore_callregs(name(e) ==untidy_return_tag);
2 7u83 2353
#if 0
2354
	      if (simple_res) {	/* now done earlier for dw2_returns consistency */
7 7u83 2355
	        coder(reg0, stack, son(e));
2 7u83 2356
	      };
2357
#endif
2358
 
7 7u83 2359
	      if (name(e) ==untidy_return_tag)
2 7u83 2360
		ins0(ret);
2361
	      else
2362
		retins();
2363
	      outnl();
2364
#ifdef NEWDWARF
2365
	      if (diagnose && dwarf2)
7 7u83 2366
		dw2_after_fde_exit(over_lab);
2 7u83 2367
#endif
2368
	    };
2369
	    stack_dec = old_stack_dec;
2370
	    return;
2371
	  };
2372
	  failer(STRUCT_RETURN);
2373
	  return;
2374
	};
2375
      };
2376
    case return_to_label_tag:
2377
      {
2378
	int good_fs = fstack_pos;
2379
		/* clear off any unwanted stack registers */
2380
	while (fstack_pos > first_fl_reg)
7 7u83 2381
	  discard_fstack();
2 7u83 2382
	fstack_pos = good_fs;
2383
	reset_fpucon();
2384
	move(slongsh, mw(son(e), 0), reg0);
2385
	restore_callregs(0);
7 7u83 2386
	ins0("jmp *%eax");
2 7u83 2387
	return;
2388
      };
2389
    case movecont_tag:
2390
      {
7 7u83 2391
	exp frome = son(e);
2392
	exp toe = bro(frome);
2393
	exp lengthe = bro(toe);
2394
	movecont(mw(frome, 0), mw(toe, 0), mw(lengthe, 0),
2 7u83 2395
		  isnooverlap(e));
2396
	return;
2397
      };
2398
    case solve_tag:
2399
      {
7 7u83 2400
	exp jr = getexp(f_bottom, nilexp, 0, nilexp, nilexp, 0,
2 7u83 2401
	    0, 0);
2402
	clean_stack();
2403
        sonno(jr) = stack_dec;
2404
        ptno(jr) = next_lab();
2405
        fstack_pos_of(jr) = (prop)fstack_pos;
2406
	/* jump record for end */
7 7u83 2407
	solve(son(e), son(e), dest, jr, stack);
2408
	if (name(sh(e))!= bothd) {
2 7u83 2409
	  align_label(0, jr);
7 7u83 2410
	  set_label(jr);
2 7u83 2411
#ifdef NEWDWARF
7 7u83 2412
	  START_BB();
2 7u83 2413
#endif
2414
	};
2415
	fpucon = normal_fpucon;
2416
	cond1_set = 0;
2417
	cond2_set = 0;
2418
	return;
2419
      };
2420
    case case_tag:
2421
      {
2422
	where qw;
7 7u83 2423
	exp arg1 = son(e);
2424
	exp b = bro(arg1);
2 7u83 2425
	exp t = arg1;
7 7u83 2426
	while (!last(t))
2427
	  t = bro(t);
2428
	bro(t) = nilexp;
2 7u83 2429
 
7 7u83 2430
	if (!is_o(name(arg1)) || is_crc(arg1)) {
2 7u83 2431
				/* argument is not a possible 80386
2432
				   operand, precompute it in reg0 */
7 7u83 2433
	  qw.where_exp = copyexp(reg0.where_exp);
2434
	  sh(qw.where_exp) = sh(arg1);
2 7u83 2435
	  qw.where_off = 0;
7 7u83 2436
	  coder(qw, stack, arg1);
2 7u83 2437
	  arg1 = qw.where_exp;
7 7u83 2438
	  bro(arg1) = b;
2 7u83 2439
	};
2440
 
2441
	clean_stack();
2442
 
7 7u83 2443
	IGNORE caser(arg1, name(sh(e)) == bothd, e);
2 7u83 2444
 
2445
	return;
2446
      };
2447
#ifndef NEWDIAGS
2448
    case diagnose_tag:  {
2449
	diag_info * d = dno(e);
7 7u83 2450
	if (d->key == DIAG_INFO_SOURCE) {
2 7u83 2451
	  crt_lno = natint(d -> data.source.beg.line_no);
2452
	  crt_charno = natint(d -> data.source.beg.char_off);
2453
	  crt_flnm = d -> data.source.beg.file->file.ints.chars;
2454
	};
2455
        output_diag(d, crt_proc_id, e);
2456
        coder(dest, stack, son(e));
2457
        output_end_scope(d, e);
2458
        return;
2459
      };
2460
#endif
2461
    case trap_tag: {
7 7u83 2462
	trap_ins(no(e));
2 7u83 2463
	return;
2464
      }
2465
    case asm_tag: {
2466
	if (props(e))
7 7u83 2467
	  asm_ins(e);
2 7u83 2468
	else {
7 7u83 2469
	  start_asm();
2 7u83 2470
          coder(dest, stack, son(e));
7 7u83 2471
	  end_asm();
2 7u83 2472
	}
7 7u83 2473
	clear_low_reg_record(crt_reg_record);
2 7u83 2474
	return;
2475
      }
2476
    default:
7 7u83 2477
      if (!is_a(name(e))) {
2478
	failer(BADOP);
2 7u83 2479
	return;
2480
      };
2481
 
7 7u83 2482
      if (name(dest.where_exp)!= val_tag)
2483
	codec(dest, stack, e);
2 7u83 2484
      else
2485
      if (!optop(e)) {
2486
	if (name(sh(e)) >= shrealhd && name(sh(e)) <= doublehd) {
7 7u83 2487
	  codec(flstack, stack, e);
2488
	  discard_fstack();
2 7u83 2489
	}
2490
	else
7 7u83 2491
	  codec(reg0, stack, e);
2 7u83 2492
      }
2493
      else
2494
      if (name(e)!=name_tag && name(e)!=env_offset_tag && son(e)!=nilexp) {
2495
	exp l = son(e);		/* catch all discards with side-effects */
2496
	for (;;) {
7 7u83 2497
	  coder(dest, stack, l);
2498
	  if (last(l))break;
2 7u83 2499
	  l = bro(l);
2500
	}
2501
      }
2502
      return;
2503
  };
2504
}
2505
 
2506
#ifdef NEWDIAGS
2507
struct coder_args {
2508
	where dest;
2509
	ash stack;
2510
	exp e;
2511
};
2512
 
2513
static void coder2
7 7u83 2514
(void * args)
2 7u83 2515
{
7 7u83 2516
  struct coder_args * x = (struct coder_args *)args;
2517
  coder1(x->dest, x->stack, x->e);
2 7u83 2518
  return;
2519
}
2520
 
2521
static dg_where dg_where_dest
7 7u83 2522
(exp e)
2 7u83 2523
{
2524
  dg_where w;
2525
  if (name(e) == name_tag || name(e) == reff_tag) {
7 7u83 2526
    w = dg_where_dest(son(e));
2527
    w.o += no(e) /8;
2 7u83 2528
    return w;
2529
  }
7 7u83 2530
  if (name(e)!= ident_tag)
2531
    failer("bad dg_where");
2532
  if (isglob(e)) {
2 7u83 2533
    w.k = WH_STR;
7 7u83 2534
    w.u.s = (brog(e)) ->dec_u.dec_val.dec_id;
2 7u83 2535
    w.o = 0;
2536
    return w;
2537
  }
2538
  if (ptno(e) < 0 || ptno(e) > 10)	/* contop case */
7 7u83 2539
    return(dg_where_dest(son(e)));
2540
  switch (ptno(e)) {
2 7u83 2541
    case local_pl: {
2542
      w.k = WH_REGOFF;
2543
      w.u.l = -2;
7 7u83 2544
      w.o = no(e) /8;
2 7u83 2545
      break;
2546
    }
2547
    case par_pl: {
2548
      w.k = WH_REGOFF;
2549
      w.u.l = -1;
7 7u83 2550
      w.o = (no(e) /8) + 4;
2 7u83 2551
      break;
2552
    }
2553
    case reg_pl: {
2554
      w.k = WH_REG;
7 7u83 2555
      w.u.l = get_reg_no(no(e));
2 7u83 2556
      break;
2557
    }
2558
    default:
7 7u83 2559
      failer("bad dg_where");
2 7u83 2560
      SET(w);
2561
  }
2562
  return w;
2563
}
2564
 
2565
static dg_where contop_where
7 7u83 2566
(exp id)
2 7u83 2567
{
7 7u83 2568
  return(dg_where_dest(bro(son(id))));
2 7u83 2569
}
2570
 
2571
 
2572
dg_where find_diag_res
7 7u83 2573
(void * args)
2 7u83 2574
{
7 7u83 2575
  struct coder_args * x = (struct coder_args *)args;
2 7u83 2576
  exp e = x->dest.where_exp;
2577
  dg_where w;
2578
  switch (name(e)) {
2579
    case val_tag: {
2580
      w.k = NO_WH;
2581
      break;
2582
    }
2583
    case ident_tag:
2584
    case name_tag: {
7 7u83 2585
      w = dg_where_dest(e);
2 7u83 2586
      break;
2587
    }
2588
    case ass_tag: {
2589
      if (name(son(e)) == ident_tag)
7 7u83 2590
	w = contop_where(son(e));
2 7u83 2591
      else
7 7u83 2592
	w = dg_where_dest(son(e));
2 7u83 2593
      break;
2594
    }
2595
    case apply_tag: {
2596
      w.k = WH_REGOFF;
7 7u83 2597
      w.u.l = get_reg_no(no(son(sp.where_exp)));
2 7u83 2598
      w.o = 0;
2599
      break;
2600
    }
2601
    default:
7 7u83 2602
      failer("unexpected diag_res dest");
2 7u83 2603
      SET(w);
2604
  }
2605
  return w;
2606
}
2607
 
2608
void coder
7 7u83 2609
(where dest, ash stack, exp e)
2 7u83 2610
{
2611
  dg_info d;
2612
  dg_info was_current = current_dg_info;
2613
  current_dg_info = nildiag;
2614
  if (extra_diags) {
7 7u83 2615
    switch (name(e)) {
2 7u83 2616
      case apply_tag:
2617
      case apply_general_tag: {
2618
	d = dgf(e);
2619
	while (d && d->key != DGA_CALL)
2620
	  d = d->more;
2621
	if (!d) {
7 7u83 2622
	  d = new_dg_info(DGA_CALL);
2 7u83 2623
	  d->data.i_call.clnam = (char*)0;
2624
	  d->data.i_call.pos = no_short_sourcepos;
2625
	  d->data.i_call.ck = 0;
7 7u83 2626
	  dgf(e) = combine_diaginfo(dgf(e), d);
2 7u83 2627
	}
2628
	break;
2629
      }
2630
      case test_tag: {
2631
	d = dgf(e);
2632
	if (dw_doing_branch_tests)
2633
	  break;
2634
	while (d && d->key != DGA_TEST)
2635
	  d = d->more;
2636
	if (!d) {
7 7u83 2637
	  d = new_dg_info(DGA_TEST);
2 7u83 2638
	  d->data.i_tst.pos = no_short_sourcepos;
2639
	  d->data.i_tst.inv = 0;
7 7u83 2640
	  dgf(e) = combine_diaginfo(dgf(e), d);
2 7u83 2641
	}
2642
	break;
2643
      }
2644
      case goto_tag: {
2645
	short_sourcepos p;
2646
	d = dgf(e);
2647
	if (dw_doing_branch_tests)
2648
	  break;
2649
	p = no_short_sourcepos;
2650
	while (d && d->key != DGA_JUMP) {
2651
	  if (d->key == DGA_SRC)
2652
	    p = d->data.i_src.startpos;
2653
	  d = d->more;
2654
	}
2655
	if (!d) {
7 7u83 2656
	  d = new_dg_info(DGA_JUMP);
2 7u83 2657
	  d->data.i_tst.pos = p;
7 7u83 2658
	  dgf(e) = combine_diaginfo(dgf(e), d);
2 7u83 2659
	}
2660
	break;
2661
      }
2662
      case goto_lv_tag:
2663
      case return_to_label_tag:
2664
      case long_jump_tag:
2665
      case tail_call_tag: {
2666
	d = dgf(e);
2667
	if (dw_doing_branch_tests)
2668
	  break;
2669
	while (d && d->key != DGA_LJ)
2670
	  d = d->more;
2671
	if (!d) {
7 7u83 2672
	  d = new_dg_info(DGA_LJ);
2 7u83 2673
	  d->data.i_tst.pos = no_short_sourcepos;
7 7u83 2674
	  dgf(e) = combine_diaginfo(dgf(e), d);
2 7u83 2675
	}
2676
	break;
2677
      }
2678
    }
2679
  }
2680
  d = dgf(e);
2681
  if (d != nildiag) {
2682
    dg_info dpos = nildiag;
2683
    struct coder_args args;
2684
    args.dest = dest;
2685
    args.stack = stack;
2686
    current_dg_exp = args.e = e;
2687
    while (d != nildiag) {
7 7u83 2688
      if (d->key == DGA_SRC && d->data.i_src.startpos.file) {
2 7u83 2689
	crt_lno = d->data.i_src.startpos.line;
2690
	crt_charno = d->data.i_src.startpos.column;
2691
	crt_flnm = d->data.i_src.startpos.file->file_name;
7 7u83 2692
        if (d->data.i_src.endpos.file) {
2 7u83 2693
	  dpos = d;
2694
	  break;
2695
	}
2696
      };
2697
      d = d->more;
2698
    };
2699
#ifdef NEWDWARF
7 7u83 2700
    CODE_DIAG_INFO(dgf(e), crt_proc_id, coder2,(void*) &args);
2 7u83 2701
#else
7 7u83 2702
    code_diag_info(dgf(e), crt_proc_id, coder2,(void*) &args);
2 7u83 2703
#endif
2704
    if (dpos) {
2705
      crt_lno = dpos->data.i_src.endpos.line;
2706
      crt_charno = dpos->data.i_src.endpos.column;
2707
      crt_flnm = dpos->data.i_src.endpos.file->file_name;
2708
    };
2709
  }
2710
  else
7 7u83 2711
    coder1(dest, stack, e);
2 7u83 2712
  current_dg_info = was_current;
2713
  return;
2714
}
2715
 
2716
 
2717
 
2718
static void done_arg
7 7u83 2719
(void * args)
2 7u83 2720
{
7 7u83 2721
  UNUSED(args);
2 7u83 2722
  return;
2723
}
2724
 
2725
void diag_arg
7 7u83 2726
(where dest, ash stack, exp e)
2 7u83 2727
{
2728
  if (dgf(e)) {
2729
    struct coder_args args;
2730
    args.dest = dest;
2731
    args.stack = stack;
2732
    current_dg_exp = args.e = e;
2733
#ifdef NEWDWARF
7 7u83 2734
    CODE_DIAG_INFO(dgf(e), crt_proc_id, done_arg,(void*) &args);
2 7u83 2735
#else
7 7u83 2736
    code_diag_info(dgf(e), crt_proc_id, done_arg,(void*) &args);
2 7u83 2737
#endif
2738
  }
2739
  return;
2740
}
2741
 
2742
 
2743
#endif
2744