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
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/* 80x86/instr386.c */
32
 
33
/**********************************************************************
34
$Author: pwe $
35
$Date: 1998/03/15 16:00:20 $
36
$Revision: 1.3 $
37
$Log: instr386.c,v $
38
 * Revision 1.3  1998/03/15  16:00:20  pwe
39
 * regtrack dwarf dagnostics added
40
 *
41
 * Revision 1.2  1998/02/18  11:22:03  pwe
42
 * test corrections
43
 *
44
 * Revision 1.1.1.1  1998/01/17  15:55:51  release
45
 * First version to be checked into rolling release.
46
 *
47
 * Revision 1.56  1997/11/06  09:35:49  pwe
48
 * ANDF-DE V1.8
49
 *
50
 * Revision 1.55  1997/10/28  10:26:40  pwe
51
 * correct extra diags / locations
52
 *
53
 * Revision 1.54  1997/10/23  09:37:08  pwe
54
 * extra_diags
55
 *
56
 * Revision 1.53  1997/10/10  18:25:13  pwe
57
 * prep ANDF-DE revision
58
 *
59
 * Revision 1.52  1997/08/23  13:45:35  pwe
60
 * initial ANDF-DE
61
 *
62
 * Revision 1.51  1997/06/13  13:29:38  pwe
63
 * invalidate edx after 1-byte mul/imul
64
 *
65
 * Revision 1.50  1997/04/24  09:05:02  pwe
66
 * reg record correction in compare
67
 *
68
 * Revision 1.49  1997/03/24  11:15:21  pwe
69
 * dwarf2 option/default
70
 *
71
 * Revision 1.48  1997/03/20  16:23:48  pwe
72
 * dwarf2
73
 *
74
 * Revision 1.47  1997/02/18  11:42:58  pwe
75
 * NEWDIAGS for debugging optimised code
76
 *
77
 * Revision 1.46  1996/12/13  15:38:47  pwe
78
 * mult (inmem, 2) optimisation
79
 *
80
 * Revision 1.45  1996/12/10  15:11:42  pwe
81
 * prep NEWDIAGS
82
 *
83
 * Revision 1.44  1996/11/08  16:27:14  pwe
84
 * track stack movement when calling memmove
85
 *
86
 * Revision 1.43  1996/11/08  16:19:10  pwe
87
 * check_stack to check before modifying stack
88
 *
89
 * Revision 1.42  1996/07/31  12:57:03  pwe
90
 * restore alloca stack after longjump
91
 *
92
 * Revision 1.41  1996/07/09  09:43:46  pwe
93
 * caller env_offset if callees present, and tidy
94
 *
95
 * Revision 1.40  1996/06/25  09:46:32  pwe
96
 * correct round toward zero unsigned
97
 *
98
 * Revision 1.39  1996/05/23  11:46:17  pwe
99
 * round to 64
100
 *
101
 * Revision 1.38  1996/05/20  14:30:21  pwe
102
 * improved 64-bit handling
103
 *
104
 * Revision 1.37  1996/05/09  17:30:33  pwe
105
 * shift invalidate_dest, and stabs postlude
106
 *
107
 * Revision 1.35  1996/04/19  16:13:56  pwe
108
 * simplified use of global id = id, correcting linux call problem
109
 *
110
 * Revision 1.34  1996/03/12  12:44:16  pwe
111
 * 64-bit ints compatible with gcc long long
112
 *
113
 * Revision 1.33  1996/02/20  14:45:06  pwe
114
 * linux/elf return struct
115
 *
116
 * Revision 1.32  1996/02/16  10:36:05  pwe
117
 * move char/bitfield
118
 *
119
 * Revision 1.31  1996/01/31  12:24:19  pwe
120
 * is_crc v is_opnd  &  end_contop must not preceed move_reg
121
 *
122
 * Revision 1.30  1996/01/18  16:09:56  pwe
123
 * longc_mult invalidates reg0
124
 *
125
 * Revision 1.29  1996/01/10  13:59:53  pwe
126
 * apply with varcallees within postlude
127
 *
128
 * Revision 1.28  1995/11/01  18:41:19  pwe
129
 * PIC tail_call and exception handling
130
 *
131
 * Revision 1.27  1995/10/25  17:41:16  pwe
132
 * PIC_code current_env and callees
133
 *
134
 * Revision 1.26  1995/09/27  17:53:07  pwe
135
 * maintain fpucon mask where poss
136
 *
137
 * Revision 1.25  1995/09/26  16:46:54  pwe
138
 * compare with zero to ignore previous overflow
139
 *
140
 * Revision 1.24  1995/09/21  16:32:16  pwe
141
 * mult by unsigned or 8-bit constant
142
 *
143
 * Revision 1.23  1995/09/20  14:28:42  pwe
144
 * fpu overflow on sco,linux
145
 *
146
 * Revision 1.22  1995/09/19  15:42:48  pwe
147
 * round, fp overflow etc
148
 *
149
 * Revision 1.21  1995/09/15  17:39:20  pwe
150
 * tidy and correct fistp
151
 *
152
 * Revision 1.20  1995/09/13  14:25:09  pwe
153
 * tidy for gcc
154
 *
155
 * Revision 1.19  1995/09/08  12:51:14  pwe
156
 * exceptions improved
157
 *
158
 * Revision 1.18  1995/09/06  16:29:26  pwe
159
 * exceptions now OK
160
 *
161
 * Revision 1.17  1995/09/05  16:24:56  pwe
162
 * specials and exception changes
163
 *
164
 * Revision 1.16  1995/09/01  17:30:10  pwe
165
 * traps and Build scripts
166
 *
167
 * Revision 1.15  1995/08/30  16:06:39  pwe
168
 * prepare exception trapping
169
 *
170
 * Revision 1.14  1995/08/23  09:42:47  pwe
171
 * track fpu control word for trap etc
172
 *
173
 * Revision 1.13  1995/08/14  13:53:41  pwe
174
 * several corrections, tail calls and error jumps
175
 *
176
 * Revision 1.12  1995/08/04  08:29:28  pwe
177
 * 4.0 general procs implemented
178
 *
179
 * Revision 1.11  1995/03/24  09:21:33  pwe
180
 * global proc renaming avoided for SCO
181
 *
182
 * Revision 1.10  1995/02/24  16:11:06  pwe
183
 * dynamic offsets, including mixed bit/byte representations
184
 *
185
 * Revision 1.9  1995/02/22  11:49:19  pwe
186
 * compare env_offset
187
 *
188
 * Revision 1.8  1995/02/21  11:47:52  pwe
189
 * Corrected move(offset) for movecont
190
 *
191
 * Revision 1.7  1995/02/16  18:47:11  pwe
192
 * transformed subtract inverts, sets and adds carry in case of error_jump
193
 *
194
 * Revision 1.6  1995/02/08  13:32:42  pwe
195
 * multiply const by const
196
 *
197
 * Revision 1.5  1995/01/30  12:56:20  pwe
198
 * Ownership -> PWE, tidy banners
199
 *
200
 * Revision 1.4  1995/01/06  11:59:47  jmf
201
 * Because of bug in gas, fixed fadd etc. to use long form.
202
 *
203
 * Revision 1.3  1994/11/08  17:21:05  jmf
204
 * Cleaned up t in movecont
205
 *
206
 * Revision 1.2  1994/11/08  09:18:01  jmf
207
 * Don't /8 in movecont, it's done in operand
208
 *
209
 * Revision 1.1  1994/10/27  14:15:22  jmf
210
 * Initial revision
211
 *
212
 * Revision 1.8  1994/08/11  09:41:12  jmf
213
 * Corrected rotshiftr if from and to are both ecx and ecx not in use due
214
 * to from being a def part of an identity.
215
 *
216
 * Revision 1.7  1994/08/10  16:56:46  jmf
217
 * Check all but one uses of fopr and annotated them.
218
 *
219
 * Revision 1.6  1994/08/09  16:47:50  jmf
220
 * Checking off uses of fopr.
221
 *
222
 * Revision 1.5  1994/08/09  11:48:45  jmf
223
 * Corrected fl_binop: case 0 and 1.
224
 *
225
 * Revision 1.4  1994/08/05  08:26:08  jmf
226
 * Also call stack_return from callins if 64 and Pentium
227
 *
228
 * Revision 1.3  1994/08/04  14:37:38  jmf
229
 * Use two pops for pentium in stack_return
230
 *
231
 * Revision 1.2  1994/07/15  13:58:52  jmf
232
 * Improve fl_bin for livermore loops.
233
 *
234
 * Revision 1.1  1994/07/12  14:34:22  jmf
235
 * Initial revision
236
 *
237
**********************************************************************/
238
 
239
 
240
 
241
/**********************************************************************
242
                          instr386.c
243
 
244
   Defines 80386 instructions such as add, sub etc.
245
 
246
**********************************************************************/
247
 
248
 
249
#include "config.h"
250
#include "common_types.h"
251
#include "operand.h"
252
#include "instr.h"
253
#include "shapemacs.h"
254
#include "instrmacs.h"
255
#include "tags.h"
256
#include "exp.h"
257
#include "basicread.h"
258
#include "expmacs.h"
259
#include "flpt.h"
260
#include "flpttypes.h"
261
#include "coder.h"
262
#include "check.h"
263
#include "out.h"
264
#include "reg_record.h"
265
#include "codermacs.h"
266
#include "install_fns.h"
267
#include "externs.h"
268
#include "localflags.h"
269
#include "flags.h"
270
#include "overlap.h"
271
#include "messages_8.h"
272
#include "machine.h"
273
#include "f64.h"
274
#include "installglob.h"
275
#include "instr386.h"
276
 
277
#ifdef NEWDIAGS
278
#include "dg_globs.h"
279
#endif
280
 
281
#ifdef NEWDWARF
282
#include "dw2_config.h"
283
#include "dw2_basic.h"
284
#include "dw2_extra.h"
285
#endif
286
 
287
 
288
/* MACROS */
289
 
290
#define PREFETCH_COUNT 1000
291
 
292
/* VARIABLES */
293
/* All variables initialised */
294
 
295
static where SPILLREG;	/* no init needed */
296
static int SPILLMASK;	/* no init needed */
297
 
298
int cmp_64hilab = -1;	/* >=0 iff label required by cmp */
299
 
300
where cond1, cond2a, cond2b;	/* no init needed */
301
int cond1_set = 0;		/* init by cproc */
302
int cond2_set = 0;		/* init by cproc */
303
int fstack_pos;			/* init by cproc */
304
int  top_regsinuse;		/* no init needed */
305
exp overflow_e = nilexp;	/* no init needed */
306
int ferrsize;			/* init by cproc */
307
int fpucon;			/* init by cproc */
308
 
309
		/* initialised by initzeros */
310
exp zeroe;			/* constant exps and wheres */
311
exp fzeroe;
312
exp fonee;
313
exp flongmaxe;
314
exp dlongmaxe;
315
exp dllmaxe;
316
exp dzeroe;
317
exp donee;
318
where zero;
319
where fzero;
320
where fone;
321
where dzero;
322
where done;
323
exp smaxe;
324
exp sllmaxe;
325
 
326
exp dummys;
327
exp dummyu;
328
exp reg0id;
329
exp reg0charid;
330
exp reg0uid;
331
exp reg1id;
332
exp reg2id;
333
exp reg3id;
334
exp reg4id;
335
exp reg5id;
336
exp reg6id;
337
exp spid;
338
exp bpid;
339
exp pushid;
340
exp flstackid;
341
exp stack0ref;
342
where reg0;
343
where reg0char;
344
where reg0u;
345
where reg1;
346
where reg2;
347
where reg3;
348
where reg4;
349
where reg5;
350
where reg6;
351
where sp;
352
where bp;
353
where ind_sp;
354
where ind_reg0;
355
where ind_reg1;
356
where ind_reg2;
357
where ind_reg4;
358
where pushdest;
359
where flstack;
360
where stack0;
361
 
362
static exp firstlocalid;
363
static where firstlocal;
364
 
365
exp ferrmemid;
366
exp ferrmem;
367
 
368
where reg_wheres[7];
369
		/* end of values inited by initzeros */
370
 
371
static int   contop_level = 0;	/* initial value for pushing must be 0 */
372
static int reg0_in_use = 0;	/* initial value for pushing must be 0 */
373
int contop_dopop = 0;		/* initial value for pushing must be 0 */
374
 
375
static exp name_memmove = nilexp;	/* initialised if and when needed */
376
static exp cont_stacklimit = nilexp;	/* initialised if and when needed */
377
static exp lib64_s_mult = nilexp;
378
static exp lib64_u_mult = nilexp;
379
static exp lib64_div[4];
380
static exp lib64_rem[4];
381
static exp lib64_error = nilexp;
382
static int lib64_set = 0;
383
 
384
 
385
/* IDENTITIES */
386
 
387
int first_fl_reg = 8;
388
 
389
char  maxdigs[] = "4294967296";
390
char  smaxdigs[] = "2147483648";
391
int  lsmask[33] = {
392
  0,
393
  0x1, 0x3, 0x7, 0xf,
394
  0x1f, 0x3f, 0x7f, 0xff,
395
  0x1ff, 0x3ff, 0x7ff, 0xfff,
396
  0x1fff, 0x3fff, 0x7fff, 0xffff,
397
  0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
398
  0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
399
  0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
400
  0x1fffffff, 0x3fffffff, 0x7fffffff, (int)0xffffffff
401
};
402
 
403
int  msmask[33] = {
404
  0,
405
  (int)0x80000000, (int)0xc0000000, (int)0xe0000000, (int)0xf0000000,
406
  (int)0xf8000000, (int)0xfc000000, (int)0xfe000000, (int)0xff000000,
407
  (int)0xff800000, (int)0xffc00000, (int)0xffe00000, (int)0xfff00000,
408
  (int)0xfff80000, (int)0xfffc0000, (int)0xfffe0000, (int)0xffff0000,
409
  (int)0xffff8000, (int)0xffffc000, (int)0xffffe000, (int)0xfffff000,
410
  (int)0xfffff800, (int)0xfffffc00, (int)0xfffffe00, (int)0xffffff00,
411
  (int)0xffffff80, (int)0xffffffc0, (int)0xffffffe0, (int)0xfffffff0,
412
  (int)0xfffffff8, (int)0xfffffffc, (int)0xfffffffe, (int)0xffffffff
413
};
414
 
415
static int flpt_test_no[] = {0, 0x45, 0x5, 0x5, 0x41, 0x44, 0x44,
416
			     0x41, 0x5, 0x5, 0x45, 0x40, 0x40, 0x4, 0x4};
417
 
418
 
419
/* PROCEDURES */
420
 
421
static void try_overflow
422
    PROTO_N ( (sha, inv) )
423
    PROTO_T ( shape sha X int inv )
424
{
425
  if (overflow_e != nilexp) {
426
    exp oe = overflow_e;
427
    if (isov(overflow_e)) {
428
      exp jd = pt(son(pt(overflow_e)));
429
      overflow_e = nilexp;
430
      jmp_overflow (jd, is_signed(sha), inv);
431
    }
432
    else
433
    if (istrap(overflow_e)) {
434
      overflow_e = nilexp;
435
      trap_overflow (is_signed(sha), inv);
436
    }
437
    overflow_e = oe;
438
  }
439
  return;
440
}
441
 
442
static void test_exception
443
    PROTO_N ( (test_no, sha) )
444
    PROTO_T ( int test_no X shape sha )
445
{
446
  if (overflow_e != nilexp) {
447
    exp oe = overflow_e;
448
    if (isov(overflow_e)) {
449
      exp jd = pt(son(pt(overflow_e)));
450
      overflow_e = nilexp;
451
      branch (test_no, jd, is_signed(sha), name(sha));
452
    }
453
    else
454
    if (istrap(overflow_e)) {
455
      overflow_e = nilexp;
456
      test_trap (test_no, is_signed(sha), name(sha));
457
    }
458
    overflow_e = oe;
459
  }
460
  return;
461
}
462
 
463
static void do_exception
464
    PROTO_Z ()
465
{
466
  if (overflow_e != nilexp) {
467
    exp oe = overflow_e;
468
    if (isov(overflow_e)) {
469
      exp jd = pt(son(pt(overflow_e)));
470
      overflow_e = nilexp;
471
      jump (jd, 0);
472
    }
473
    else
474
    if (istrap(overflow_e)) {
475
      overflow_e = nilexp;
476
      trap_ins(f_overflow);
477
    }
478
    overflow_e = oe;
479
  }
480
  return;
481
}
482
 
483
 
484
 
485
static int use_pop_ass
486
    PROTO_N ( (n, ln) )
487
    PROTO_T ( exp n X exp ln )
488
{
489
  exp id;
490
  if (name (ln) == cont_tag)
491
    ln = son (ln);
492
  if (name (ln) != name_tag)
493
    return (0);
494
  id = son (ln);
495
  while (n != id && last (n) &&
496
	 (is_a(name(n)) || name(n) == ident_tag ||
497
		name(n) == ass_tag))
498
    n = bro (n);
499
  if (n == id)
500
    return (get_reg_no (no (id)) - fstack_pos + 2);
501
  return (0);
502
}
503
 
504
 
505
static int   use_pop
506
    PROTO_N ( (n, ln) )
507
    PROTO_T ( exp n X exp ln )
508
{
509
  exp id;
510
  if (name (ln) == cont_tag)
511
    ln = son (ln);
512
  if (name (ln) != name_tag)
513
    return (0);
514
  id = son (ln);
515
  while (n != id && last (n))
516
    n = bro (n);
517
  if (n == id)
518
    return (get_reg_no (no (id)) - fstack_pos + 2);
519
  return (0);
520
}
521
 
522
int  count_regs
523
    PROTO_N ( (mask) )
524
    PROTO_T ( int mask )
525
{
526
  return (bits_in[mask & 0xf] + bits_in[(mask >> 4) & 0x3]);
527
}
528
 
529
static void cmp64_contop
530
    PROTO_N ( (d) )
531
    PROTO_T ( int d )
532
{
533
  if (d && contop_dopop) {
534
    int lolab = next_lab();
535
    simple_branch (je, lolab);
536
    if (contop_dopop == 1)
537
     {
538
      ins1 (popl, size32, SPILLREG);
539
#ifdef NEWDWARF
540
      if (diagnose && dwarf2 && no_frame)
541
	dw2_track_pop();
542
#endif
543
     }
544
    else
545
     {
546
	exp ap = getexp (f_bottom, nilexp, 0, sp.where_exp,
547
                          nilexp, 0, 4, reff_tag);
548
        ins2 (leal, size32, size32, mw (ap, 0), sp);
549
     };
550
    simple_branch (jmp, cmp_64hilab);
551
    simplest_set_lab (lolab);
552
  }
553
  else
554
    simple_branch (jne, cmp_64hilab);
555
  return;
556
}
557
 
558
 
559
void end_contop
560
    PROTO_Z ()
561
{
562
  if (contop_level == 0)
563
    reg0_in_use = 0;
564
  if (contop_dopop) {
565
    if (contop_dopop == 1)
566
     {
567
      ins1 (popl, size32, SPILLREG);
568
#ifdef NEWDWARF
569
      if (diagnose && dwarf2 && no_frame)
570
	dw2_track_pop();
571
#endif
572
     }
573
    else
574
     {
575
	exp ap = getexp (f_bottom, nilexp, 0, sp.where_exp,
576
                          nilexp, 0, 4, reff_tag);
577
        ins2 (leal, size32, size32, mw (ap, 0), sp);
578
     };
579
    invalidate_dest (SPILLREG);
580
    contop_dopop = 0;
581
    extra_stack -= 32;
582
    min_rfree |= SPILLMASK;
583
  };
584
  return;
585
}
586
 
587
 
588
/* if a in cont or ass of an identified object, load the address */
589
void contop
590
    PROTO_N ( (a, r0inuse, dest) )
591
    PROTO_T ( exp a X int r0inuse X where dest )
592
{
593
  unsigned char  n = name (a);
594
  int  offset = 0;
595
 
596
  contop_level++;
597
 
598
  if (PIC_code) {
599
    SPILLREG = reg4;
600
    SPILLMASK = 0x10;
601
  }
602
  else {
603
    SPILLREG = reg3;
604
    SPILLMASK = 0x8;
605
  };
606
 
607
  if ((n == cont_tag || n == ass_tag || n == reff_tag)
608
      && name (son (a)) == ident_tag) {
609
		/* IF 1 */
610
    ash st;				/* dummy stack for use by coder */
611
    exp fin = bro (son (son (a)));	/* fin holds body of final
612
					   identity */
613
    unsigned char  oldn = name (fin);		/* oldn hold name of final
614
					   identity */
615
    exp id1 = son (a);			/* outer identity */
616
    int  inreg1 = ptno (son (son (id1))) == reg_pl;
617
					/* true if def of outer identity
618
					   is already in a register */
619
    int  reg_mask = (~regsinuse) & 0x3e;
620
    int  regs_free = count_regs (reg_mask);
621
					/* number of free integer
622
					   registers */
623
    exp old_overflow_e;
624
    st.ashsize = 0;
625
    st.ashalign = 0;
626
 
627
    if (r0inuse && contop_level == 1)
628
      reg0_in_use |= 1;			/* cannot use reg0 */
629
 
630
    if (oldn == ident_tag) {
631
		/* IF 2 */
632
	/* body of id1 is an identity, so TWO identities, so
633
	   addptr ivolved */
634
      exp id2 = bro (son (id1));	/* inner identity */
635
      int  inreg2 = ptno (son (son (id2))) == reg_pl;
636
					/* true if def of inner identity
637
					   is already in a register */
638
      int  regs_good = regs_free + inreg1 + inreg2;
639
					/* we want two registers but the
640
					   definitions of id1 and id2 will
641
					   do */
642
      fin = bro (son (fin));
643
      oldn = name (fin);		/* correct fin and oldn */
644
 
645
      if (regs_good < 2) {
646
		/* IF 3 */
647
	/* we have two declarations and need some registers */
648
 
649
	if ((inreg1 + inreg2) == 1 && !reg0_in_use) {
650
		/* with reg0 we have enough registers */
651
	  if (inreg2) {
652
	    ptno (id1) = reg_pl;
653
	    no (id1) = 1;		/* id1 uses reg0 */
654
	    ptno (id2) = reg_pl;
655
	    no (id2) = no (son (son (id2)));
656
	  }
657
	  else {
658
	    ptno (id2) = reg_pl;
659
	    no (id2) = 1;		/* id2 uses reg0 */
660
	    ptno (id1) = reg_pl;
661
	    no (id1) = no (son (son (id1)));
662
	  };
663
 
664
	  coder (mw (id1, 0), st, son (id1));
665
	  coder (mw (id2, 0), st, son (id2)); /* work out defs */
666
	  contop_level--;
667
	  son (a) = fin;		/* code body in caller */
668
	  return;
669
	};
670
 
671
 
672
	if (regs_free == 1 || !reg0_in_use) {
673
					/* there is one free register,
674
					   no need to spill */
675
	  where use_reg;		/* holds free register */
676
 
677
	  if (regs_free == 1) {
678
	    frr f;
679
	    f = first_reg (reg_mask);
680
	    use_reg = reg_wheres[f.fr_no];	/* free register from
681
						   mask */
682
	    min_rfree |= reg_mask;	/* mark as used */
683
	  }
684
	  else
685
	    use_reg = reg0;		/* reg0 is free */
686
 
687
	  if (name (fin) == reff_tag) {	/* remove reff */
688
	    offset = no (fin);
689
	    fin = son (fin);
690
	  };
691
          old_overflow_e = overflow_e;
692
          overflow_e = nilexp;
693
			/* this must be an addptr, note that the
694
			   calculations cannot involve the free reg */
695
	  if (name (bro (son (fin))) == name_tag) {
696
			/* the offset is named, so add the pointer to the
697
			   offset and put in the free register */
698
	    add (slongsh, mw (son (id2), 0), mw (son (id1), 0), use_reg);
699
	  }
700
	  else {
701
			/* this is an offset_mult so do the arithmetic of
702
			   address calculation and put the address in
703
			   the free register */
704
	    exp m = bro (son (fin));
705
            move(slongsh, mw (son (id1), 0), use_reg);
706
            mult (slongsh, use_reg, mw (bro (son (m)), 0),
707
		use_reg);
708
	    add (slongsh, mw (son (id2), 0), use_reg, use_reg);
709
	  };
710
          overflow_e = old_overflow_e;
711
 
712
	  if (offset != 0) {
713
			/* put back the reff if there was one */
714
	    exp r = getexp (sh (son (a)), nilexp, 0, use_reg.where_exp,
715
		nilexp, 0, offset, reff_tag);
716
	    son (a) = r;
717
	  }
718
	  else
719
	    son (a) = use_reg.where_exp;
720
		/* the address is in the free register, code the rest
721
		   in caller */
722
	  contop_level--;
723
	  return;
724
	};
725
 
726
		/* we are a register short so spill SPILLREG */
727
	ins1 (pushl, size32, SPILLREG);
728
#ifdef NEWDWARF
729
	if (diagnose && dwarf2 && no_frame)
730
	  dw2_track_push();
731
#endif
732
	extra_stack += 32;
733
	check_stack_max;
734
 
735
	if (name (fin) == reff_tag) {	/* remove reff */
736
	  offset = no (fin);
737
	  fin = son (fin);
738
	};
739
 
740
        old_overflow_e = overflow_e;
741
        overflow_e = nilexp;
742
		/* it must be an addptr */
743
	if (name (bro (son (fin))) == name_tag) {
744
		/* the offset is named */
745
	  move (slongsh, mw (son (id1), 0), SPILLREG);
746
			/* put the offset in SPILLREG */
747
 
748
	  if (eq_where (SPILLREG, mw (son (id2), 0)))
749
			/* id2 is the SPILLREG, so add the pushed value */
750
	    add (slongsh, stack0, SPILLREG, SPILLREG);
751
	  else
752
			/* otherwise add def of id2 to SPILLREG */
753
	    add (slongsh, mw (son (id2), 0), SPILLREG, SPILLREG);
754
	}
755
	else {
756
		/* the offset is an offset_mult */
757
	  exp m = bro (son (fin));
758
	  move (slongsh, mw (son (id1), 0), SPILLREG);
759
			/* number to SPILLREG */
760
	  mult (slongsh, SPILLREG, mw (bro (son (m)), 0), SPILLREG);
761
			/* multiply by size */
762
	  if (eq_where (SPILLREG, mw (son (id2), 0)))
763
			/* id2 is the SPILLREG, so add the pushed value */
764
	    add (slongsh, stack0, SPILLREG, SPILLREG);
765
	  else
766
			/* otherwise add def of id2 to SPILLREG */
767
	    add (slongsh, mw (son (id2), 0), SPILLREG, SPILLREG);
768
	};
769
        overflow_e = old_overflow_e;
770
 
771
	if (offset != 0) {	/* put back the reff if needed */
772
	  exp r = getexp (sh (son (a)), nilexp, 0, SPILLREG.where_exp,
773
	      nilexp, 0, offset, reff_tag);
774
	  son (a) = r;
775
	}
776
	else
777
	  son (a) = SPILLREG.where_exp;
778
			/* code the rest in the caller */
779
 
780
	contop_level--;
781
 
782
	if (!eq_where (dest, SPILLREG))
783
	  contop_dopop = 1;	/* arrange to pop SPILLREG if not equal
784
				   to dest */
785
	else
786
	  contop_dopop = 2;	/* do not pop SPILREG */
787
	return;
788
      };
789
 
790
		/* regs_goo >= 2 so we have enough registers */
791
      setname (fin, top_tag);	/* nullify fin */
792
      coder (reg0, st, son (a));	/* code the declarations */
793
      /* we are coding the identity declaration */
794
      contop_level--;
795
      setname (fin, oldn);	/* restore fin */
796
      son (a) = fin;		/* code the rest in caller */
797
      return;
798
    };
799
		/* end of IF 2 */
800
 
801
		/* one declaration, so simple indirection */
802
    if (!inreg1 && regs_free == 0) {
803
		/* we need another register */
804
      if (reg0_in_use) {
805
		/* we shall have to spill one */
806
	ins1 (pushl, size32, SPILLREG);	/* spill SPILLREG */
807
#ifdef NEWDWARF
808
	if (diagnose && dwarf2 && no_frame)
809
	  dw2_track_push();
810
#endif
811
	extra_stack += 32;
812
	check_stack_max;
813
 
814
	move (slongsh, mw (son (id1), 0), SPILLREG);
815
		/* put the pointer into SPILLREG */
816
 
817
        ptno(id1) = reg_pl;
818
        no(id1) = SPILLMASK;	/* set place for identity to SPILLREG */
819
 
820
        son(a) = fin;	/* code the rest in caller */
821
	contop_level--;
822
	if (!eq_where (dest, SPILLREG))
823
	  contop_dopop = 1;	/* arrange to pop SPILLREG */
824
	else
825
	  contop_dopop = 2;	/* do not pop SPILLREG */
826
	return;
827
      };
828
 
829
		/* reg0 is available */
830
      move (slongsh, mw (son (id1), 0), reg0);
831
		/* put the pointer into reg0 */
832
 
833
      ptno(id1) = reg_pl;
834
      no(id1) = 1;	/* set place for identity to reg0 */
835
 
836
      contop_level--;
837
      son(a) = fin;	/* code the rest in caller */
838
      return;
839
    };
840
 
841
 
842
    setname (fin, top_tag);	/* nullify fin */
843
    coder (reg0, st, son (a));	/* we are coding the identity declaration
844
				*/
845
    contop_level--;
846
    setname (fin, oldn);	/* restore fin */
847
    son (a) = fin;		/* code the rest in caller */
848
    return;
849
  };
850
  contop_level--;
851
  top_regsinuse = regsinuse;
852
  return;
853
}
854
 
855
 
856
 
857
 
858
void initzeros
859
    PROTO_Z ()
860
{
861
				/* set up the constants */
862
  int  flongmax = new_flpt ();
863
  int  fllmax = new_flpt ();
864
  int  fslongmax = new_flpt ();
865
  int  fsllmax = new_flpt ();
866
  int  i;
867
  flt * flongmaxr = &flptnos[flongmax];
868
  flt * fllmaxr = &flptnos[fllmax];
869
  flt * fslongmaxr = &flptnos[fslongmax];
870
  flt * fsllmaxr = &flptnos[fsllmax];
871
 
872
  flongmaxr -> sign = 1;
873
  flongmaxr -> exp = 2;
874
  fllmaxr -> sign = 1;
875
  fllmaxr -> exp = 4;
876
  fslongmaxr -> sign = 1;
877
  fslongmaxr -> exp = 1;
878
  fsllmaxr -> sign = 1;
879
  fsllmaxr -> exp = 3;
880
  for (i = 0; i < MANT_SIZE; i++) {
881
    (flongmaxr -> mant)[i] = (unsigned short)((i == 0) ? 1 : 0);
882
    (fllmaxr -> mant)[i] = (unsigned short)((i == 0) ? 1 : 0);
883
    (fslongmaxr -> mant)[i] = (unsigned short)((i == 0) ? 32768 : 0);
884
    (fsllmaxr -> mant)[i] = (unsigned short)((i == 0) ? 32768 : 0);
885
  };
886
 
887
  zeroe = getexp (f_bottom, nilexp, 0, nilexp, nilexp, 0, 0, val_tag);
888
  fzeroe = getexp (shrealsh, nilexp, 0, nilexp, nilexp, 0, fzero_no, real_tag);
889
  fonee = getexp (shrealsh, nilexp, 0, nilexp, nilexp, 0, fone_no, real_tag);
890
  flongmaxe = getexp (shrealsh, nilexp, 0, nilexp, nilexp, 0,
891
      flongmax, real_tag);
892
  smaxe = getexp (realsh, nilexp, 0, nilexp, nilexp, 0,
893
      fslongmax, real_tag);
894
  sllmaxe = getexp (doublesh, nilexp, 0, nilexp, nilexp, 0,
895
      fsllmax, real_tag);
896
  dzeroe = getexp (realsh, nilexp, 0, nilexp, nilexp, 0, fzero_no, real_tag);
897
  donee = getexp (realsh, nilexp, 0, nilexp, nilexp, 0, fone_no, real_tag);
898
  dlongmaxe = getexp (realsh, nilexp, 0, nilexp, nilexp, 0,
899
      flongmax, real_tag);
900
  dllmaxe = getexp (doublesh, nilexp, 0, nilexp, nilexp, 0,
901
      fllmax, real_tag);
902
  pushid = getexp (f_bottom, nilexp, 0, nilexp, nilexp, 0, 0, apply_tag);
903
  pushdest.where_exp = pushid;
904
  pushdest.where_off = 0;
905
  zero.where_exp = zeroe;
906
  fzero.where_exp = fzeroe;
907
  fone.where_exp = fonee;
908
  dzero.where_exp = dzeroe;
909
  done.where_exp = donee;
910
  zero.where_off = 0;
911
  fzero.where_off = 0;
912
  fone.where_off = 0;
913
  dzero.where_off = 0;
914
  done.where_off = 0;
915
 
916
  dummys = getexp (slongsh, nilexp, 0, nilexp, nilexp, 0, 0, val_tag);
917
  dummyu = getexp (ulongsh, nilexp, 0, nilexp, nilexp, 0, 0, val_tag);
918
 
919
  reg0id = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
920
      0x1, ident_tag);
921
  ptno(reg0id) = reg_pl;
922
  reg0 = mw (getexp (slongsh, nilexp, 0, reg0id, nilexp, 0, 0, name_tag),
923
      0);
924
 
925
  reg0charid = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
926
      0x1, ident_tag);
927
  ptno(reg0charid) = reg_pl;
928
  reg0char = mw (getexp (scharsh, nilexp, 0, reg0id,
929
	nilexp, 0, 0, name_tag),
930
      0);
931
 
932
  reg1id = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
933
      0x2, ident_tag);
934
  ptno(reg1id) = reg_pl;
935
  reg1 = mw (getexp (slongsh, nilexp, 0, reg1id, nilexp, 0, 0, name_tag),
936
      0);
937
 
938
  reg2id = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
939
      0x4, ident_tag);
940
  ptno(reg2id) = reg_pl;
941
  reg2 = mw (getexp (slongsh, nilexp, 0, reg2id, nilexp, 0, 0, name_tag),
942
      0);
943
 
944
  reg3id = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
945
      0x8, ident_tag);
946
  ptno(reg3id) = reg_pl;
947
  reg3 = mw (getexp (slongsh, nilexp, 0, reg3id, nilexp, 0, 0, name_tag),
948
      0);
949
 
950
 
951
  reg4id = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
952
      0x10, ident_tag);
953
  ptno(reg4id) = reg_pl;
954
  reg4 = mw (getexp (slongsh, nilexp, 0, reg4id, nilexp, 0, 0, name_tag),
955
      0);
956
 
957
  reg5id = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
958
      0x20, ident_tag);
959
  ptno(reg5id) = reg_pl;
960
  reg5 = mw (getexp (slongsh, nilexp, 0, reg5id, nilexp, 0, 0, name_tag),
961
      0);
962
 
963
  reg6id = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
964
      0x40, ident_tag);
965
  ptno(reg6id) = reg_pl;
966
  reg6 = mw (getexp (slongsh, nilexp, 0, reg6id, nilexp, 0, 0, name_tag),
967
      0);
968
 
969
  flstackid = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
970
      0x10000, ident_tag);
971
  ptno(flstackid) = reg_pl;
972
  flstack = mw (getexp (realsh, nilexp, 0, flstackid, nilexp,
973
	0, 0, name_tag),
974
      0);
975
 
976
  reg0uid = getexp (f_bottom, nilexp, 0, dummyu, nilexp, 0,
977
      0x1, ident_tag);
978
  ptno(reg0uid) = reg_pl;
979
  reg0u = mw (getexp (ulongsh, nilexp, 0, reg0uid, nilexp, 0, 0, name_tag),
980
      0);
981
 
982
  spid = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
983
      128, ident_tag);
984
  ptno(spid) = reg_pl;
985
  sp = mw (getexp (slongsh, nilexp, 0, spid, nilexp, 0, 0, name_tag), 0);
986
 
987
  bpid = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0,
988
      64, ident_tag);
989
  ptno(bpid) = reg_pl;
990
  bp = mw (getexp (slongsh, nilexp, 0, bpid, nilexp, 0, 0, name_tag), 0);
991
 
992
 
993
  stack0ref = getexp (f_top, nilexp, 0, sp.where_exp, nilexp, 0, -32,
994
      reff_tag);
995
  stack0 = mw (getexp (f_pointer (f_alignment(slongsh)), nilexp, 0,
996
	stack0ref, nilexp, 0, 0, cont_tag), 0);
997
 
998
  ind_reg0 = mw (getexp (f_pointer (f_alignment(slongsh)), nilexp, 0,
999
	reg0.where_exp, nilexp, 0, 0, cont_tag), 0);
1000
  ind_reg1 = mw (getexp (f_pointer (f_alignment(slongsh)), nilexp, 0,
1001
	reg1.where_exp, nilexp, 0, 0, cont_tag), 0);
1002
  ind_reg2 = mw (getexp (f_pointer (f_alignment(slongsh)), nilexp, 0,
1003
	reg2.where_exp, nilexp, 0, 0, cont_tag), 0);
1004
  ind_reg4 = mw (getexp (f_pointer (f_alignment(slongsh)), nilexp, 0,
1005
	reg4.where_exp, nilexp, 0, 0, cont_tag), 0);
1006
  ind_sp = mw (getexp (f_pointer (f_alignment(slongsh)), nilexp, 0, sp.where_exp,
1007
	nilexp, 0, 0, cont_tag), 0);
1008
 
1009
  firstlocalid = getexp (f_bottom, nilexp, 0, dummys, nilexp, 0, 0, ident_tag);
1010
  ptno(firstlocalid) = local_pl;
1011
  firstlocal = mw (getexp (slongsh, nilexp, 0, firstlocalid, nilexp, 0, 0, name_tag), 0);
1012
 
1013
  reg_wheres[0] = reg0;
1014
  reg_wheres[1] = reg1;
1015
  reg_wheres[2] = reg2;
1016
  reg_wheres[3] = reg3;
1017
  reg_wheres[4] = reg4;
1018
  reg_wheres[5] = reg5;
1019
  reg_wheres[6] = bp;
1020
 
1021
  ferrmemid = getexp (f_bottom, nilexp, 0, nilexp, nilexp, 0, 0, ident_tag);
1022
  ptno(ferrmemid) = ferr_pl;
1023
  ferrmem = getexp (realsh, nilexp, 0, ferrmemid, nilexp, 0, 0, name_tag);
1024
 
1025
}
1026
 
1027
 
1028
 
1029
 /* 80386 output routines */
1030
 
1031
 
1032
/* is w in memory and not a constant */
1033
int flinmem
1034
    PROTO_N ( (w) )
1035
    PROTO_T ( where w )
1036
{
1037
  exp e = w.where_exp;
1038
  unsigned char  n = name (e);
1039
  exp id;
1040
  int recog = 0;
1041
 
1042
  if (n == ident_tag || n == labst_tag) {
1043
    id = e;
1044
    recog = 1;
1045
  }
1046
  else {
1047
    if (n == name_tag) {
1048
      id = son (e);
1049
      recog = 1;
1050
    }
1051
    else {
1052
      if ((n == cont_tag || n == ass_tag) &&
1053
	  name (son (e)) == name_tag && isvar (son (son (e)))) {
1054
	id = son (son (e));
1055
	recog = 1;
1056
      }
1057
    };
1058
  };
1059
 
1060
#ifndef NEWDIAGS
1061
  if (n == diagnose_tag)
1062
    return flinmem(mw(son(e), w.where_off));
1063
#endif
1064
 
1065
  if (!recog)
1066
    return (1);
1067
  else {
1068
    SET(id);
1069
  };
1070
 
1071
  if (ptno (id) == reg_pl &&
1072
      (name (sh (son (id))) > ucharhd || no (id) < 0x10))/* 0x10 is edi */
1073
    return (0);  /* there are no char versions of edi, esi */
1074
 
1075
  return (1);
1076
}
1077
 
1078
 
1079
/* is w in memory or an integer or null
1080
   pointer constant */
1081
int inmem
1082
    PROTO_N ( (w) )
1083
    PROTO_T ( where w )
1084
{
1085
  unsigned char  n = name (w.where_exp);
1086
  if (n == val_tag ||
1087
	n == null_tag || n == current_env_tag)
1088
    return (0);
1089
  return (flinmem (w));
1090
}
1091
 
1092
int w_islastuse
1093
    PROTO_N ( (w) )
1094
    PROTO_T ( where w )
1095
{
1096
  exp e = w.where_exp;
1097
  if (name(e) == name_tag && !isvar(son(e)))
1098
    return islastuse(e);
1099
  if (name(e) == cont_tag && name(son(e)) == name_tag &&
1100
       isvar(son(son(e))))
1101
    return islastuse(son(e));
1102
  return 0;
1103
}
1104
 
1105
/* abs value a1 of shape sha and put
1106
   it in dest */
1107
void absop
1108
    PROTO_N ( (sha, a1, dest) )
1109
    PROTO_T ( shape sha X where a1 X where dest )
1110
{
1111
  int labno = next_lab();
1112
  where q;
1113
  int sz = shape_size(sha);
1114
  char * op, * ng;
1115
 
1116
  q = dest;
1117
 
1118
  switch (sz) {
1119
    case 8:
1120
      op = testb;
1121
      ng = negb;
1122
      break;
1123
    case 16:
1124
      op = testw;
1125
      ng = negw;
1126
      break;
1127
    case 32:
1128
    case 64:
1129
      op = testl;
1130
      ng = negl;
1131
      break;
1132
    default:
1133
      failer("unexpected size");
1134
  };
1135
 
1136
  cond1_set = 0;
1137
  cond2_set = 0;
1138
 
1139
  if (inmem(dest)) {
1140
    move(sha, a1, reg0);
1141
    q = reg0;
1142
  }
1143
  else
1144
    move(sha, a1, dest);
1145
 
1146
  if (sz == 64) {
1147
	/* must be in reg0/reg1 */
1148
    ins2(testl, 32, 32, reg1, reg1);
1149
    simple_branch(jge, labno);
1150
    move (slongsh, reg1, reg2);
1151
    move (slongsh, zero, reg1);
1152
    ins1(negl, 32, reg0);
1153
    ins2(sbbl, 32, 32, reg2, reg1);
1154
    try_overflow (sha, 0);
1155
    invalidate_dest(reg1);
1156
    invalidate_dest(reg2);
1157
  }
1158
  else {
1159
    ins2(op, sz, sz, q, q);
1160
    simple_branch(jg, labno);
1161
    ins1(ng, sz, q);
1162
    try_overflow (sha, 0);
1163
  }
1164
  invalidate_dest(q);
1165
  simple_set_label(labno);
1166
  move(sha, q, dest);
1167
  return;
1168
}
1169
 
1170
 
1171
static void maxmin
1172
    PROTO_N ( (sha, a1, a2, dest, ismax) )
1173
    PROTO_T ( shape sha X where a1 X where a2 X where dest X int ismax )
1174
{
1175
  where tempw;
1176
  int labno = next_lab();
1177
  int lab64;
1178
  int mem1;
1179
  int mem2;
1180
  char *in;
1181
  int sz = shape_size(sha);
1182
  char * op12;
1183
  char * op21;
1184
  int late_contop = 0;
1185
 
1186
  if (is_signed(sha)) {
1187
    op12 = (ismax)  ? jl : jg;
1188
    op21 = (ismax) ? jg : jl;
1189
  }
1190
  else {
1191
    op12 = (ismax)  ? jb : ja;
1192
    op21 = (ismax) ? ja : jb;
1193
  };
1194
 
1195
  cond1_set = 0;
1196
  cond2_set = 0;
1197
 
1198
  switch (sz) {
1199
    case 8:
1200
      in = cmpb;
1201
      break;
1202
    case 16:
1203
      in = cmpw;
1204
      break;
1205
    case 32:
1206
      in = cmpl;
1207
      break;
1208
    case 64:
1209
      lab64 = next_lab();
1210
      break;	/* use cmpl instead of in */
1211
    default:
1212
      failer("unexpected size");
1213
  };
1214
 
1215
  if (eq_where(a2, dest)) {
1216
    tempw = a1;
1217
    a1 = a2;
1218
    a2 = tempw;
1219
  };
1220
 
1221
  mem1 = inmem(a1);
1222
  mem2 = inmem(a2);
1223
 
1224
  if (eq_where(a1, a2)) {
1225
    move (sha, a1, dest);
1226
    return;
1227
  }
1228
  if (eq_where(a1, dest)) {
1229
    exp hold1 = son(a1.where_exp);
1230
    exp hold2 = son(a2.where_exp);
1231
    int riu = regsinuse;
1232
    if (mem1 && mem2) {
1233
      move(sha, a2, reg0);
1234
      maxmin(sha, a1, reg0, dest, ismax);
1235
      return;
1236
    };
1237
    if (name(a2.where_exp) != val_tag) {
1238
      if (mem1) {
1239
	if (sz == 64) {
1240
		/* a2 must be reg0/1 */
1241
	  regsinuse |= 0x2;
1242
	  contop (a1.where_exp, 1, dest);
1243
	  ins2 (cmpl, 32, 32, mw(a1.where_exp, a1.where_off + 32), reg1);
1244
	  simple_branch (op12, labno);
1245
	  simple_branch (jne, lab64);
1246
	  ins2 (cmpl, 32, 32, a1, reg0);
1247
	  simple_branch ((ismax ? jb : ja), labno);
1248
	  late_contop = contop_dopop;
1249
	  contop_dopop = 0;
1250
	}
1251
	else {
1252
	  contop(a1.where_exp, eq_where(a2, reg0), dest);
1253
          ins2(in, sz, sz, a1, a2);
1254
	  end_contop();
1255
          simple_branch(op12, labno);
1256
	};
1257
      }
1258
      else {
1259
	if (mem2) {
1260
	  if (sz == 64) {
1261
		/* a1 and dest must be reg0/1 */
1262
	    regsinuse |= 0x2;
1263
	    contop(a2.where_exp, 1, dest);
1264
	    ins2 (cmpl, 32, 32, reg1, mw(a2.where_exp, a2.where_off + 32));
1265
	    simple_branch (op12, labno);
1266
	    simple_branch (jne, lab64);
1267
	    ins2 (cmpl, 32, 32, reg0, a2);
1268
	    simple_branch ((ismax ? jb : ja), labno);
1269
	  }
1270
	  else {
1271
	    contop(a2.where_exp, eq_where(a1, reg0), dest);
1272
            ins2(in, sz, sz, a1, a2);
1273
            simple_branch(op12, labno);
1274
	  };
1275
	  late_contop = contop_dopop;
1276
	  contop_dopop = 0;
1277
	}
1278
	else  {		/* cannot be (sz == 64) */
1279
	  ins2(in, sz, sz, a1, a2);
1280
          simple_branch(op12, labno);
1281
        };
1282
      };
1283
    }
1284
    else {
1285
      if (sz == 64) {
1286
	int c, c1;
1287
	if (!isbigval(a2.where_exp)) {
1288
	  c = no (a2.where_exp) + a2.where_off;
1289
	  c1 = (is_signed(sha) && c < 0) ? -1 : 0;
1290
	}
1291
	else {
1292
	  flt64 x;
1293
	  int ov;
1294
	  x = flt_to_f64(no(a2.where_exp), is_signed(sha), &ov);
1295
	  c = x.small;
1296
	  c1 = x.big;
1297
	};
1298
	if (mem1) {
1299
	  contop (a1.where_exp, 0, dest);
1300
	  ins2 (cmpl, 32, 32, mw(zeroe, c1), mw(a1.where_exp, a1.where_off + 32));
1301
	  simple_branch (op21, labno);
1302
	  simple_branch (jne, lab64);
1303
	  ins2 (cmpl, 32, 32, mw(zeroe, c), a1);
1304
	  simple_branch ((ismax ? ja : jb), labno);
1305
	  late_contop = contop_dopop;
1306
	  contop_dopop = 0;
1307
	}
1308
	else {
1309
		/* a1 and dest must be reg0/1 */
1310
	  ins2 (cmpl, 32, 32, mw(zeroe, c1), reg1);
1311
	  simple_branch (op21, labno);
1312
	  simple_branch (jne, lab64);
1313
	  ins2 (cmpl, 32, 32, mw(zeroe, c), reg0);
1314
	  simple_branch ((ismax ? ja : jb), labno);
1315
	};
1316
      }
1317
      else {
1318
	if (mem1) {
1319
	  contop(a1.where_exp, 0, dest);
1320
          ins2(in, sz, sz, a2, a1);
1321
	  end_contop();
1322
	}
1323
	else
1324
          ins2(in, sz, sz, a2, a1);
1325
	simple_branch(op21, labno);
1326
      };
1327
    };
1328
    if (sz == 64)
1329
      simplest_set_lab (lab64);
1330
    move(sha, a2, dest);
1331
    simple_set_label(labno);
1332
    if (late_contop) {
1333
      contop_dopop = late_contop;
1334
      end_contop();
1335
    };
1336
    regsinuse = riu;
1337
    invalidate_dest(dest);
1338
    invalidate_dest(a1);
1339
    invalidate_dest(a2);
1340
    son(a1.where_exp) = hold1;
1341
    son(a2.where_exp) = hold2;
1342
    return;
1343
  };
1344
 
1345
  if (eq_where(a1, reg0)) {
1346
    reg0_in_use = 1;
1347
    maxmin(sha, reg0, a2, reg0, ismax);
1348
    move(sha, reg0, dest);
1349
    return;
1350
  };
1351
 
1352
  if (eq_where(a2, reg0)) {
1353
    reg0_in_use = 1;
1354
    maxmin(sha, a1, reg0, reg0, ismax);
1355
    move(sha, reg0, dest);
1356
    return;
1357
  };
1358
 
1359
  move(sha, a1, reg0);
1360
  maxmin(sha, reg0, a2, dest, ismax);
1361
  return;
1362
}
1363
 
1364
 
1365
/* max values a1, a2 of shape sha and put them in dest */
1366
void maxop
1367
    PROTO_N ( (sha, a1, a2, dest) )
1368
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
1369
{
1370
  maxmin(sha, a1, a2, dest, 1);
1371
  return;
1372
}
1373
 
1374
/* min values a1, a2 of shape sha and put them in dest */
1375
void minop
1376
    PROTO_N ( (sha, a1, a2, dest) )
1377
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
1378
{
1379
  maxmin(sha, a1, a2, dest, 0);
1380
  return;
1381
}
1382
 
1383
/* add values a1, a2 of shape sha and put them in dest  */
1384
void add_plus
1385
    PROTO_N ( (sha, a1, a2, dest, plus1) )
1386
    PROTO_T ( shape sha X where a1 X where a2 X where dest X int plus1 )
1387
{
1388
  int  sz;
1389
  exp a = a1.where_exp;
1390
  int  aoff = a1.where_off;
1391
  exp b = a2.where_exp;
1392
  int  boff = a2.where_off;
1393
  sz = shape_size(sha);
1394
 
1395
  if (name(a) == val_tag && name(sh(a)) == offsethd && al2(sh(a)) != 1) {
1396
    if (name(sha) == offsethd && al2(sha) != 1)
1397
      no(a) = no(a) / 8;
1398
    sh(a) = slongsh;
1399
  };
1400
  if (name(b) == val_tag && name(sh(b)) == offsethd && al2(sh(b)) != 1) {
1401
    if (name(sha) == offsethd && al2(sha) != 1)
1402
      no(b) = no(b) / 8;
1403
    sh(b) = slongsh;
1404
  };
1405
 
1406
  cond1_set = 1;
1407
  cond2_set = 0;
1408
  cond1 = dest;			/* we know the conditions are set
1409
				   according to the which will be in dest
1410
				*/
1411
 
1412
  if (eq_where (a1, dest) &&
1413
	(!keep_short || !flinmem(dest))) {	/* altering dest */
1414
    if (name (b) == val_tag && !plus1 && !isbigval(b) && (no (b) + boff == 0 ||
1415
	  ((no (b) + boff == 1 || no (b) + boff == -1) && sz <= 32 &&
1416
	    (overflow_e == nilexp || is_signed(sha) )))) {
1417
      exp hold = son(a);
1418
      if (no (b) + boff == 0) {	/* adding zero */
1419
	cond1_set = 0;		/* we didn't know conditions after all */
1420
	return;
1421
      };
1422
      contop (a, 0, a1);	/* get the address of a if necessary */
1423
      if (no (b) + boff == 1) {	/* use inc */
1424
	if (sz == 8) {
1425
	  ins1 (incb, sz, a1);
1426
	};
1427
	if (sz == 16) {
1428
	  ins1 (incw, sz, a1);
1429
	};
1430
	if (sz == 32) {
1431
	  ins1 (incl, sz, a1);
1432
	};
1433
      }
1434
      else {			/* use dec */
1435
	if (sz == 8) {
1436
	  ins1 (decb, sz, a1);
1437
	};
1438
	if (sz == 16) {
1439
	  ins1 (decw, sz, a1);
1440
	};
1441
	if (sz == 32) {
1442
	  ins1 (decl, sz, a1);
1443
	};
1444
      };
1445
      invalidate_dest (dest);
1446
      end_contop ();
1447
      try_overflow (sha, plus1);
1448
      son(a) = hold;
1449
      return;
1450
    };
1451
 
1452
    if (!inmem (a1) || !inmem (a2)) {
1453
      /* either a1 or a2 is not in memory */
1454
      int riu = regsinuse;
1455
      exp holda = son(a);
1456
      exp holdb = son(b);
1457
      if (sz == 64)
1458
	regsinuse |= 0x2;
1459
      if (inmem (a1))
1460
	contop (a, eq_where (reg0, a2), a1);
1461
      else
1462
	contop (b,
1463
	     (eq_where (reg0, a2) || eq_where (reg0, a1)), a1);
1464
      if (plus1)
1465
	ins0 (stc);
1466
      if (sz == 8) {
1467
	ins2 ((plus1 ? adcb : addb), sz, sz, a2, a1);
1468
      };
1469
      if (sz == 16) {
1470
	ins2 ((plus1 ? adcw : addw), sz, sz, a2, a1);
1471
      };
1472
      if (sz == 32) {
1473
	ins2 ((plus1 ? adcl : addl), sz, sz, a2, a1);
1474
      };
1475
      if (sz == 64) {
1476
	where hi1, lo1, hi2, lo2;
1477
	lo1 = a1;
1478
	hi1 = (inmem(a1) ? mw (a, aoff + 32) : reg1);
1479
	if (name (b) == val_tag) {
1480
	  int c, c1;
1481
	  if (!isbigval(b)) {
1482
	    c = no (b) + boff;
1483
	    c1 = (is_signed(sha) && c < 0) ? -1 : 0;
1484
	  }
1485
	  else {
1486
	    flt64 x;
1487
	    int ov;
1488
	    x = flt_to_f64(no(b), is_signed(sha), &ov);
1489
	    c = x.small;
1490
	    c1 = x.big;
1491
	  };
1492
	  lo2 = mw (zeroe, c);
1493
	  hi2 = mw (zeroe, c1);
1494
	}
1495
	else {
1496
	  lo2 = a2;
1497
	  hi2 = (inmem(a2) ? mw (b, boff + 32) : reg1);
1498
	}
1499
	ins2 ((plus1 ? adcl : addl), 32, 32, lo2, lo1);
1500
	ins2 (adcl, 32, 32, hi2, hi1);
1501
      };
1502
      invalidate_dest (dest);
1503
      end_contop ();
1504
      regsinuse = riu;
1505
      try_overflow (sha, plus1);
1506
      son(a) = holda;
1507
      son(b) = holdb;
1508
      return;
1509
    };
1510
 
1511
    move (sha, a2, reg0);
1512
    add_plus (sha, reg0, a1, a1, plus1);
1513
    invalidate_dest (dest);
1514
    return;
1515
  };
1516
 
1517
  if (eq_where (a2, dest) &&
1518
	(!keep_short || !flinmem(dest))) {	/* altering dest */
1519
    if (name (a) == val_tag && !plus1 && !isbigval(a) && (no (a) + aoff == 0 ||
1520
	  ((no (a) + aoff == 1 || no (a) + aoff == -1) && sz <= 32 &&
1521
	    (overflow_e == nilexp || is_signed(sha) )))) {
1522
      exp hold = son(a);
1523
      if (no (a) + aoff == 0) {	/* adding zero */
1524
	cond1_set = 0;		/* we didn't know conditions after all */
1525
	return;
1526
      };
1527
      contop (b, 0, a2);
1528
      if (no (a) + aoff == 1) {	/* use inc */
1529
	if (sz == 8) {
1530
	  ins1 (incb, sz, a2);
1531
	};
1532
	if (sz == 16) {
1533
	  ins1 (incw, sz, a2);
1534
	};
1535
	if (sz == 32) {
1536
	  ins1 (incl, sz, a2);
1537
	};
1538
      }
1539
      else {			/* use dec */
1540
	if (sz == 8) {
1541
	  ins1 (decb, sz, a2);
1542
	};
1543
	if (sz == 16) {
1544
	  ins1 (decw, sz, a2);
1545
	};
1546
	if (sz == 32) {
1547
	  ins1 (decl, sz, a2);
1548
	};
1549
      };
1550
      invalidate_dest (dest);
1551
      end_contop ();
1552
      try_overflow (sha, plus1);
1553
      son(a) = hold;
1554
      return;
1555
    };
1556
 
1557
    if (!inmem (a1) || !inmem (a2)) {
1558
      /* either a1 or a2 is not in memory */
1559
      int riu = regsinuse;
1560
      exp holda = son(a);
1561
      exp holdb = son(b);
1562
      if (sz == 64)
1563
	regsinuse |= 0x2;
1564
      if (inmem (a1))
1565
	contop (a, eq_where (reg0, a2), a2);
1566
      else
1567
	contop (b,
1568
	     (eq_where (reg0, a2) || eq_where (reg0, a1)), a2);
1569
      if (plus1)
1570
	ins0 (stc);
1571
      if (sz == 8) {
1572
	ins2 ((plus1 ? adcb : addb), sz, sz, a1, a2);
1573
      };
1574
      if (sz == 16) {
1575
	ins2 ((plus1 ? adcw : addw), sz, sz, a1, a2);
1576
      };
1577
      if (sz == 32) {
1578
	ins2 ((plus1 ? adcl : addl), sz, sz, a1, a2);
1579
      };
1580
      if (sz == 64) {
1581
	where hi1, lo1, hi2, lo2;
1582
	lo2 = a2;
1583
	hi2 = (inmem(a2) ? mw (b, a2.where_off + 32) : reg1);
1584
	if (name (a) == val_tag) {
1585
	  int c, c1;
1586
	  if (!isbigval(a)) {
1587
	    c = no (a) + aoff;
1588
	    c1 = (is_signed(sha) && c < 0) ? -1 : 0;
1589
	  }
1590
	  else {
1591
	    flt64 x;
1592
	    int ov;
1593
	    x = flt_to_f64(no(a), is_signed(sha), &ov);
1594
	    c = x.small;
1595
	    c1 = x.big;
1596
	  };
1597
	  lo1 = mw (zeroe, c);
1598
	  hi1 = mw (zeroe, c1);
1599
	}
1600
	else {
1601
	  lo1 = a1;
1602
	  hi1 = (inmem(a1) ? mw (a, aoff + 32) : reg1);
1603
	}
1604
	ins2 ((plus1 ? adcl : addl), 32, 32, lo1, lo2);
1605
 	ins2 (adcl, 32, 32, hi1, hi2);
1606
      };
1607
      invalidate_dest (dest);
1608
      try_overflow (sha, plus1);
1609
      end_contop ();
1610
      regsinuse = riu;
1611
      son(a) = holda;
1612
      son(b) = holdb;
1613
      return;
1614
    };
1615
 
1616
    move (sha, a1, reg0);
1617
    add_plus (sha, reg0, a2, a2, plus1);
1618
    invalidate_dest (dest);
1619
    return;
1620
  };
1621
 
1622
  if (name (a) == val_tag && !plus1 && !isbigval(a) && no (a) + aoff == 0) {
1623
    /* adding zero and moving */
1624
    cond1_set = 0;
1625
    move (sha, a2, dest);
1626
    return;
1627
  };
1628
 
1629
  if (name (b) == val_tag && !plus1 && !isbigval(b) && no (b) + boff == 0) {
1630
    /* adding zero and moving */
1631
    cond1_set = 0;
1632
    move (sha, a1, dest);
1633
    return;
1634
  };
1635
 
1636
  /* switch on memory position of a1, a2, dest */
1637
  switch ((inmem (a1) << 2) + (inmem (a2) << 1) + inmem (dest)) {
1638
    case 0:
1639
      {				/* none in memory */
1640
	exp ap;
1641
        int n;
1642
        if (overflow_e != nilexp || sz > 32)
1643
          {
1644
            move (sha, a2, dest);
1645
            add_plus (sha, a1, dest, dest, plus1);
1646
            return;
1647
          };
1648
	/* otherwise cannot be plus1 */
1649
	if (name (a) == val_tag) {
1650
	  if (name (b) == val_tag) {/* we know the answer */
1651
	    cond1_set = 0;
1652
	    move (sha, mw (zeroe,
1653
		    no (a) + no (b) + a1.where_off + a2.where_off),
1654
		    dest);
1655
	    return;
1656
	  };
1657
          if (name(sh(a)) == offsethd)
1658
            n = 1;
1659
          else
1660
            n = 8;
1661
          if (n == 8 && (no(a) & (int)0xf0000000) == 0)  {
1662
	    ap = getexp (f_bottom, nilexp, 0, b, nilexp, 0,
1663
	        (no (a) + a1.where_off) * n,
1664
	        reff_tag);
1665
	    cond1_set = 0;
1666
	    ins2 (leal, 32, 32, mw (ap, 0), dest);
1667
	    retcell (ap);
1668
	    invalidate_dest (dest);
1669
	    return;
1670
          }
1671
          else  {
1672
            move(sha, a2, dest);
1673
            add(sha, a1, dest, dest);
1674
            return;
1675
          };
1676
	};
1677
	if (name (b) == val_tag) {
1678
          if (name(sh(b)) == offsethd)
1679
            n = 1;
1680
          else
1681
            n = 8;
1682
          if (n == 8 && (no(b) & (int)0xf0000000) == 0)  {
1683
	    ap = getexp (f_bottom, nilexp, 0, a, nilexp, 0,
1684
	        (no (b) + a2.where_off) * n,
1685
	        reff_tag);
1686
	    cond1_set = 0;
1687
	    ins2 (leal, 32, 32, mw (ap, 0), dest);
1688
	    retcell (ap);
1689
	    invalidate_dest (dest);
1690
	    return;
1691
          }
1692
          else  {
1693
            move(sha, a1, dest);
1694
            add(sha, a2, dest, dest);
1695
            return;
1696
          };
1697
	};
1698
	ap = getexp (f_bottom, nilexp, 0, a, nilexp, 0, 0,
1699
	      addptr_tag);
1700
	{
1701
	  exp temp = bro(a);
1702
	  bro (a) = b;
1703
	  cond1_set = 0;
1704
	  ins2 (leal, 32, 32, mw (ap, 0), dest);
1705
	  retcell (ap);
1706
          invalidate_dest (dest);
1707
	  bro(a) = temp;
1708
          return;
1709
	}
1710
      };
1711
    case 1:
1712
    case 3:
1713
    case 5:
1714
    case 7:
1715
      /* dest is in memory */
1716
      add_plus (sha, a1, a2, reg0, plus1);
1717
      move (sha, reg0, dest);
1718
      return;
1719
    case 2: 			/* a2 in memory others not */
1720
      if (eq_where (a1, reg0))
1721
	reg0_in_use = 1;
1722
      move (sha, a2, dest);
1723
      add_plus (sha, a1, dest, dest, plus1);
1724
      invalidate_dest (dest);
1725
      return;
1726
    case 4: 			/* a1 in memory others not */
1727
      if (eq_where (a2, reg0))
1728
	reg0_in_use = 1;
1729
      move (sha, a1, dest);
1730
      add_plus (sha, a2, dest, dest, plus1);
1731
      invalidate_dest (dest);
1732
      return;
1733
    default: 			/* case 6 a1 and a2 in memory, dest not */
1734
      move (sha, a2, reg0);
1735
      add_plus (sha, a1, reg0, reg0, plus1);
1736
      move (sha, reg0, dest);
1737
      return;
1738
  };
1739
}
1740
 
1741
 
1742
/* add values a1, a2 of shape sha and put them in dest */
1743
void add
1744
    PROTO_N ( (sha, a1, a2, dest) )
1745
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
1746
{
1747
  add_plus (sha, a1, a2, dest, 0);
1748
  return;
1749
}
1750
 
1751
 
1752
/* negate a1 in sup_dest then add a2 and put in dest */
1753
void inverted_sub
1754
    PROTO_N ( (sha, a1, a2, sup_dest, dest) )
1755
    PROTO_T ( shape sha X where a1 X where a2 X where sup_dest X where dest )
1756
{
1757
  if (overflow_e == nilexp) {
1758
    negate (sha, a1, sup_dest);
1759
    add_plus (sha, a2, sup_dest, dest, 0);
1760
  }
1761
  else {
1762
    exp old_overflow_e = overflow_e;
1763
    overflow_e = nilexp;
1764
    not (sha, a1, sup_dest);
1765
    overflow_e = old_overflow_e;
1766
    add_plus (sha, a2, sup_dest, dest, 1);
1767
  }
1768
  return;
1769
}
1770
 
1771
 
1772
/* subtract a1 from a2 and put in dest,
1773
   shape sha, structure similar to add qv.
1774
   for comments */
1775
void sub
1776
    PROTO_N ( (sha, a1, a2, dest) )
1777
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
1778
{
1779
  int  sz;
1780
  exp a = a1.where_exp;
1781
  int  aoff = a1.where_off;
1782
  exp b = a2.where_exp;
1783
  sz = shape_size(sha);
1784
 
1785
  if (name(a) == val_tag && name(sh(a)) == offsethd && al2(sh(a)) != 1) {
1786
    if (name(sha) == offsethd && al2(sha) != 1)
1787
      no(a) = no(a) / 8;
1788
    sh(a) = slongsh;
1789
  };
1790
  if (name(b) == val_tag && name(sh(b)) == offsethd && al2(sh(b)) != 1) {
1791
    if (name(sha) == offsethd && al2(sha) != 1)
1792
      no(b) = no(b) / 8;
1793
    sh(b) = slongsh;
1794
  };
1795
 
1796
  if (name (sha) & 1) {
1797
    cond1_set = 1;
1798
    cond2_set = 0;
1799
    cond1 = dest;
1800
  }
1801
  else {			/* the conditions are not set correctly if
1802
				   unsigned */
1803
    cond1_set = 0;
1804
    cond2_set = 0;
1805
  };
1806
 
1807
 
1808
  if (eq_where (a2, dest) &&
1809
	(!keep_short || !flinmem(dest))) {
1810
    if (name (a) == val_tag && !isbigval(a) && (no (a) + aoff == 0 ||
1811
	  ((no (a) + aoff == 1 || no (a) + aoff == -1) && sz <= 32 &&
1812
	    (overflow_e == nilexp || is_signed(sha) )))) {
1813
      exp hold = son(b);
1814
      if (no (a) + aoff == 0) {	/* we didn't know the conditions */
1815
	cond1_set = 0;
1816
	return;
1817
      };
1818
      contop (b, 0, a2);
1819
      if (no (a) + aoff == 1) {	/* use dec */
1820
	if (sz == 8) {
1821
	  ins1 (decb, sz, a2);
1822
	};
1823
	if (sz == 16) {
1824
	  ins1 (decw, sz, a2);
1825
	};
1826
	if (sz == 32) {
1827
	  ins1 (decl, sz, a2);
1828
	};
1829
      }
1830
      else {			/* use inc */
1831
	if (sz == 8) {
1832
	  ins1 (incb, sz, a2);
1833
	};
1834
	if (sz == 16) {
1835
	  ins1 (incw, sz, a2);
1836
	};
1837
	if (sz == 32) {
1838
	  ins1 (incl, sz, a2);
1839
	};
1840
      };
1841
      invalidate_dest (dest);
1842
      end_contop ();
1843
      try_overflow (sha, 0);
1844
      son(b) = hold;
1845
      return;
1846
    };
1847
 
1848
    if (!inmem (a1) || !inmem (a2)) {
1849
      int riu = regsinuse;
1850
      exp holda = son(a);
1851
      exp holdb = son(b);
1852
      if (sz == 64)
1853
	regsinuse |= 0x2;
1854
      if (inmem (a1))
1855
	contop (a, eq_where (reg0, a2), a2);
1856
      else
1857
	contop (b,
1858
	     (eq_where (reg0, a2) || eq_where (reg0, a1)), a2);
1859
      if (sz == 8) {
1860
	ins2 (subb, sz, sz, a1, a2);
1861
      };
1862
      if (sz == 16) {
1863
	ins2 (subw, sz, sz, a1, a2);
1864
      };
1865
      if (sz == 32) {
1866
	ins2 (subl, sz, sz, a1, a2);
1867
      };
1868
      if (sz == 64) {
1869
	where hi1, lo1, hi2, lo2;
1870
	lo2 = a2;
1871
	hi2 = (inmem(a2) ? mw (b, a2.where_off + 32) : reg1);
1872
	if (name (a) == val_tag) {
1873
	  int c, c1;
1874
	  if (!isbigval(a)) {
1875
	    c = no (a) + aoff;
1876
	    c1 = (is_signed(sha) && c < 0) ? -1 : 0;
1877
	  }
1878
	  else {
1879
	    flt64 x;
1880
	    int ov;
1881
	    x = flt_to_f64(no(a), is_signed(sha), &ov);
1882
	    c = x.small;
1883
	    c1 = x.big;
1884
	  };
1885
	  lo1 = mw (zeroe, c);
1886
	  hi1 = mw (zeroe, c1);
1887
	}
1888
	else {
1889
	  lo1 = a1;
1890
	  hi1 = (inmem(a1) ? mw (a, aoff + 32) : reg1);
1891
	}
1892
 	ins2 (subl, 32, 32, lo1, lo2);
1893
 	ins2 (sbbl, 32, 32, hi1, hi2);
1894
      };
1895
      invalidate_dest (dest);
1896
      end_contop ();
1897
      regsinuse = riu;
1898
      try_overflow (sha, 0);
1899
      son(a) = holda;
1900
      son(b) = holdb;
1901
      return;
1902
    };
1903
 
1904
    move (sha, a1, reg0);
1905
    sub (sha, reg0, dest, dest);
1906
    invalidate_dest (dest);
1907
    return;
1908
  };
1909
 
1910
  if (name (a) == val_tag && !isbigval(a) && no (a) + aoff == 0) {
1911
    cond1_set = 0;
1912
    move (sha, a2, dest);
1913
    return;
1914
  };
1915
 
1916
  switch ((inmem (a1) << 2) + (inmem (a2) << 1) + inmem (dest)) {
1917
    case 0:
1918
    case 2: 			/* a2 may be in mem, others not */
1919
      if (!eq_where (a1, dest)) {
1920
	if (eq_where (a1, reg0))
1921
	  reg0_in_use = 1;
1922
	move (sha, a2, dest);
1923
	sub (sha, a1, dest, dest);
1924
	invalidate_dest (dest);
1925
	return;
1926
      };
1927
      if (eq_where (a1, reg0) || eq_where (a2, reg0)) {
1928
	if (eq_where (a2, reg0))
1929
	  reg0_in_use = 1;
1930
	inverted_sub (sha, a1, a2, dest, dest);
1931
	return;
1932
      };
1933
      inverted_sub (sha, a1, a2, reg0, dest);
1934
      return;
1935
    case 4:  			/* a1 in memory others not */
1936
      if (eq_where (dest, reg0)) {
1937
	move (sha, a2, reg0);
1938
	sub (sha, a1, reg0, reg0);
1939
	invalidate_dest (dest);
1940
	return;
1941
      };		/* else drop through */
1942
    case 1:
1943
    case 3:
1944
    case 5:
1945
    case 7: 			/* dest is in memory */
1946
      sub (sha, a1, a2, reg0);
1947
      move (sha, reg0, dest);
1948
      return;
1949
    default: 			/* case 6 a1 and a2 in memory, dest not */
1950
      /* we ought to look to see if dest affects the addressing of a1 or
1951
         a2, and use it if not */
1952
      inverted_sub (sha, a1, a2, reg0, dest);
1953
      return;
1954
  };
1955
}
1956
 
1957
 
1958
/* put a negated into dest, shape sha */
1959
void negate
1960
    PROTO_N ( (sha, a, dest) )
1961
    PROTO_T ( shape sha X where a X where dest )
1962
{
1963
  int  sz;
1964
  sz = shape_size(sha);
1965
 
1966
  cond1_set = 1;
1967
  cond2_set = 0;
1968
  cond1 = dest;
1969
 
1970
  if (!inmem (a) && eq_where (a, dest)) {/* negating in situ */
1971
    if (sz == 8) {
1972
      ins1 (negb, sz, dest);
1973
      invalidate_dest (dest);
1974
    };
1975
    if (sz == 16) {
1976
      ins1 (negw, sz, dest);
1977
      invalidate_dest (dest);
1978
    };
1979
    if (sz == 32) {
1980
      ins1 (negl, sz, dest);
1981
      invalidate_dest (dest);
1982
    };
1983
    if (sz == 64) {	/* must be reg0/1 */
1984
      move (slongsh, reg1, reg2);
1985
      move (slongsh, zero, reg1);
1986
      ins1(negl, 32, reg0);
1987
      ins2(sbbl, 32, 32, reg2, reg1);
1988
      try_overflow (sha, 0);
1989
      invalidate_dest (reg0);
1990
      invalidate_dest (reg1);
1991
      invalidate_dest (reg2);
1992
      return;
1993
    };
1994
    try_overflow (sha, 0);
1995
    return;
1996
  };
1997
 
1998
  if (!inmem (a) && name (a.where_exp) != val_tag &&
1999
      (w_islastuse (a) || eq_where (a, reg0))) {
2000
    /* a is a register and no longer needed */
2001
    negate (sha, a, a);
2002
    move (sha, a, dest);
2003
    return;
2004
  };
2005
 
2006
  if (!inmem (dest)) {		/* dest is a register */
2007
    move (sha, a, dest);
2008
    negate (sha, dest, dest);
2009
    invalidate_dest (dest);
2010
    return;
2011
  };
2012
 
2013
  /* dest is in memory, a is either in memory or needed, it won't be reg0
2014
  */
2015
  move (sha, a, reg0);
2016
  negate (sha, reg0, reg0);
2017
  move (sha, reg0, dest);
2018
  return;
2019
}
2020
 
2021
/* put not(a) into dest, shape sha */
2022
void not
2023
    PROTO_N ( (sha, a, dest) )
2024
    PROTO_T ( shape sha X where a X where dest )
2025
{
2026
  int  sz;
2027
  sz = shape_size(sha);
2028
 
2029
  cond1_set = 0;
2030
  cond2_set = 0;
2031
 
2032
  if (!inmem (a) && eq_where (a, dest)) {/* inverting in situ */
2033
    if (sz == 8) {
2034
      ins1 (notb, sz, dest);
2035
      invalidate_dest (dest);
2036
      return;
2037
    };
2038
    if (sz == 16) {
2039
      ins1 (notw, sz, dest);
2040
      invalidate_dest (dest);
2041
      return;
2042
    };
2043
    if (sz == 32) {
2044
      ins1 (notl, sz, dest);
2045
      invalidate_dest (dest);
2046
      return;
2047
    };
2048
    if (sz == 64) {	/* must be reg0/1 */
2049
      ins1 (notl, 32, reg0);
2050
      ins1 (notl, 32, reg1);
2051
      invalidate_dest (reg0);
2052
      invalidate_dest (reg1);
2053
      return;
2054
    };
2055
  };
2056
 
2057
  if (!inmem (a) && name (a.where_exp) != val_tag &&
2058
      (w_islastuse (a) || eq_where (a, reg0))) {
2059
    not (sha, a, a);
2060
    move (sha, a, dest);
2061
    return;
2062
  };
2063
 
2064
  if (!inmem (dest)) {		/* dest is a register */
2065
    move (sha, a, dest);
2066
    not (sha, dest, dest);
2067
    invalidate_dest (dest);
2068
    return;
2069
  };
2070
 
2071
  /* dest is in memory, a is either in memory or needed, it won't be reg0
2072
  */
2073
  move (sha, a, reg0);
2074
  not (sha, reg0, reg0);
2075
  move (sha, reg0, dest);
2076
  return;
2077
}
2078
 
2079
 
2080
 
2081
 
2082
/* floating register for e */
2083
int  in_fl_reg
2084
    PROTO_N ( (e) )
2085
    PROTO_T ( exp e )
2086
{
2087
  unsigned char  ne = name (e);
2088
  if (ne == name_tag && ptno (son (e)) == reg_pl) {
2089
    int  n = no (son (e));
2090
    return ((n > 0x80) ? n : 0);
2091
  };
2092
  if (ne == cont_tag && name (son (e)) == name_tag &&
2093
      isvar (son (son (e))) &&
2094
      ptno (son (son (e))) == reg_pl) {
2095
    int  n = no (son (son (e)));
2096
    return ((n > 0x80) ? n : 0);
2097
  };
2098
  if (ne == ass_tag && name (son (e)) == name_tag &&
2099
      isvar (son (son (e))) &&
2100
      ptno (son (son (e))) == reg_pl) {
2101
    int  n = no (son (son (e)));
2102
    return ((n > 0x80) ? n : 0);
2103
  };
2104
  if (ne == ident_tag && ptno (e) == reg_pl) {
2105
    int  n = no (e);
2106
    return ((n > 0x80) ? n : 0);
2107
  };
2108
  return (0);
2109
}
2110
 
2111
 
2112
/* is e in the floating point stack top ? */
2113
int in_fstack
2114
    PROTO_N ( (e) )
2115
    PROTO_T ( exp e )
2116
{
2117
  int  f = in_fl_reg (e);
2118
  int  fpos = (f) ? get_reg_no (f) : 0;
2119
  return (fpos == fstack_pos);
2120
}
2121
 
2122
 
2123
 
2124
/* is e in a register */
2125
int  in_reg
2126
    PROTO_N ( (e) )
2127
    PROTO_T ( exp e )
2128
{
2129
  unsigned char  ne = name (e);
2130
  if (ne == name_tag && ptno (son (e)) == reg_pl) {
2131
    int  n = no (son (e));
2132
    if (!iscaonly (son (e)) && isvar (son (e)))
2133
      n = (n | (int)0x80000000);
2134
    return (n);
2135
  };
2136
  if (ne == cont_tag && name (son (e)) == name_tag &&
2137
      isvar (son (son (e))) &&
2138
      ptno (son (son (e))) == reg_pl) {
2139
    int  n = no (son (son (e)));
2140
    if (!iscaonly (son (son (e))) && isvar (son (son (e))))
2141
      n = (n | (int)0x80000000);
2142
    return (n);
2143
  };
2144
  if (ne == ass_tag && name (son (e)) == name_tag &&
2145
      isvar (son (son (e))) &&
2146
      ptno (son (son (e))) == reg_pl) {
2147
    int  n = no (son (son (e)));
2148
    if (!iscaonly (son (son (e))) && isvar (son (son (e))))
2149
      n = (n | (int)0x80000000);
2150
    return (n);
2151
  };
2152
  if (ne == ident_tag && ptno (e) == reg_pl) {
2153
    int  n = no (e);
2154
    if (!iscaonly (e) && isvar (e))
2155
      n = (n | (int)0x80000000);
2156
    return (n);
2157
  };
2158
  if (ne == current_env_tag)
2159
    return (0x40);
2160
  return (0);
2161
}
2162
 
2163
static int all_in_regs
2164
    PROTO_N ( (e) )
2165
    PROTO_T ( exp e )
2166
{
2167
  exp id1, id2;
2168
  unsigned char  n = name (e);
2169
 
2170
  if ((n == cont_tag || n == ass_tag || n == reff_tag)
2171
      && name (son (e)) == ident_tag) {
2172
    id1 = son (e);
2173
    if (ptno (son (son (id1))) != reg_pl)
2174
      return (0);
2175
    id2 = bro (son (id1));
2176
    if (name (id2) != ident_tag)
2177
      return (1);
2178
    return (ptno (son (son (id2))) == reg_pl);
2179
  };
2180
 
2181
  return (1);
2182
}
2183
 
2184
int two_contops
2185
    PROTO_N ( (fe, te) )
2186
    PROTO_T ( exp fe X exp te )
2187
{
2188
  int   nr = count_regs ((~regsinuse) & 0x3e);
2189
  if (nr >= 2)
2190
    return (1);
2191
  if (nr == 1)
2192
    return (all_in_regs (fe) || all_in_regs (te));
2193
  return (all_in_regs (fe) && all_in_regs (te));
2194
}
2195
 
2196
 
2197
/* move value of shape sha from "from" to "to" */
2198
void move
2199
    PROTO_N ( (sha, from, to) )
2200
    PROTO_T ( shape sha X where from X where to )
2201
{
2202
  int  sz;
2203
  int  c, c1;
2204
  int isco = 0;
2205
  exp fe = from.where_exp;
2206
  exp te = to.where_exp;
2207
  exp holdfe = son(fe);
2208
  exp holdte = son(te);
2209
  where reg_w;
2210
  sz = rounder (shape_size(sha), 8);
2211
 
2212
 
2213
 
2214
  if (sz == 0 || eq_where (from, to))
2215
    return;
2216
 
2217
  /* move does not set conditions. Only clear if to spoils cond record */
2218
 
2219
  if ((cond1_set && (eq_where (to, cond1) ||
2220
	  invalidates (to.where_exp, cond1.where_exp))) ||
2221
      (cond2_set &&
2222
	(eq_where (to, cond2a) || eq_where (to, cond2b) ||
2223
	  invalidates (to.where_exp, cond2a.where_exp) ||
2224
	  invalidates (to.where_exp, cond2b.where_exp)))) {
2225
    cond1_set = 0;
2226
    cond2_set = 0;
2227
  };
2228
 
2229
  if (name(fe) == reff_tag ||
2230
	(PIC_code && name(fe) == name_tag &&
2231
	  isglob(son (fe)) &&
2232
	  (name (sha) == offsethd) &&
2233
	  !brog(son(fe)) ->  dec_u.dec_val.extnamed))
2234
    {
2235
      mova(from, to);
2236
      return;
2237
    };
2238
 
2239
  if (name (sha) >= shrealhd && name (sha) <= doublehd) {
2240
    /* moving a float or double */
2241
    int  f1 = in_fl_reg (from.where_exp);
2242
    int  f2 = in_fl_reg (to.where_exp);
2243
    int  f1pos = (f1) ? get_reg_no (f1) : 0;
2244
    int  f2pos = (f2) ? get_reg_no (f2) : 0;
2245
    if (f1pos && f1pos == f2pos && f2 != 0x10000)
2246
      return;			/* from and to are the same */
2247
    if (f1pos && f1pos > f2pos && f2 != 0x10000) {
2248
      if (f1pos == fstack_pos &&
2249
	  from.where_exp != flstack.where_exp &&
2250
	/*  name (sha) != doublehd && */
2251
	  use_pop_ass (to.where_exp, from.where_exp) != 2) {
2252
	if (flinmem (to)) {	/* are going to pop the floating point
2253
				   stack */
2254
	  contop (te, 0, reg0);	/* compute address of to if necessary */
2255
	  if (name (sha) == shrealhd)
2256
	    ins1 (fsts, 32, to);
2257
	  else
2258
	  if (name (sha) == realhd)
2259
	    ins1 (fstl, 64, to);
2260
	  else {
2261
	    ins1 (fstpt, 96, to);
2262
	    ins1 (fldt, 96, to);
2263
	  };
2264
	  end_contop ();
2265
	  son(fe) = holdfe;
2266
	  son(te) = holdte;
2267
	  return;
2268
	};
2269
	ins1 (fst, 0, to);	/* store fstack0 into to (a reg) */
2270
	son(fe) = holdfe;
2271
	son(te) = holdte;
2272
	return;
2273
      };
2274
      if (f1pos != fstack_pos)
2275
	move (sha, from, flstack);
2276
      /* push from into floating point stack */
2277
      if (flinmem (to)) {	/* store from fstack0 into memory and pop
2278
				*/
2279
	contop (te, 0, reg0);
2280
	if (name (sha) == shrealhd)
2281
	  ins1 (fstps, 32, to);
2282
	else
2283
	if (name (sha) == realhd)
2284
	  ins1 (fstpl, 64, to);
2285
	else
2286
	  ins1 (fstpt, 96, to);
2287
	pop_fl;
2288
	end_contop ();
2289
	son(fe) = holdfe;
2290
	son(te) = holdte;
2291
	return;
2292
      };
2293
      ins1 (fstp, 0, to);	/* pop from fstack0 into floating point
2294
				   register */
2295
      pop_fl;
2296
      son(fe) = holdfe;
2297
      son(te) = holdte;
2298
      return;
2299
    };
2300
    if (in_fl_reg (to.where_exp)) {
2301
      int fz;
2302
      if (name (from.where_exp) == real_tag &&
2303
	  ((fz = cmpflpt (no (from.where_exp),
2304
                           no (fzeroe), 5), fz) ||
2305
	    cmpflpt (no (from.where_exp), no (fonee), 5))) {
2306
	if (fz)
2307
	  ins0 (fldz);		/* push zero into fstack0 */
2308
	else
2309
	  ins0 (fld1);		/* push one into fstack0 */
2310
      }
2311
      else {
2312
	if (flinmem (from)) {	/* push from into fstack0 from memory */
2313
	  contop (fe, 0, reg0);	/* put address of from into reg0 if
2314
				   necessary */
2315
	  if (name (sha) == shrealhd)
2316
	    ins1 (flds, 32, from);
2317
	  else
2318
	  if (name (sha) == realhd)
2319
	    ins1 (fldl, 64, from);
2320
	  else
2321
	    ins1 (fldt, 96, from);
2322
	  end_contop ();
2323
	}
2324
	else {
2325
	  if (f1pos == fstack_pos) {/* push fstack0 */
2326
	    load_stack0 ();
2327
	  }
2328
	  else
2329
	    ins1 (fld, 0, from);/* push floating point register */
2330
	};
2331
      };
2332
      push_fl;			/* we necessarily did a push */
2333
      if (flinmem (to)) {	/* pop fstack0 to to (in memory ) */
2334
	contop (te, 0, reg0);
2335
	if (name (sha) == shrealhd)
2336
	  ins1 (fstps, 32, to);
2337
	else
2338
	if (name (sha) == realhd)
2339
	  ins1 (fstpl, 64, to);
2340
	else
2341
	  ins1 (fstpt, 96, to);
2342
	pop_fl;
2343
	end_contop ();
2344
	son(fe) = holdfe;
2345
	son(te) = holdte;
2346
	return;
2347
      };
2348
 
2349
      f2 = in_fl_reg (to.where_exp);
2350
      f2pos = get_reg_no (f2);
2351
      if (f2pos == fstack_pos) {
2352
	son(fe) = holdfe;
2353
	son(te) = holdte;
2354
	return;
2355
      }
2356
 
2357
      ins1 (fstp, 0, to);	/* store fstack0 in to (a reg) and pop
2358
				   floating point stack */
2359
      pop_fl;
2360
      son(fe) = holdfe;
2361
      son(te) = holdte;
2362
      return;
2363
    };
2364
    /* fall through for floating point number not in coprocessor */
2365
  };
2366
 
2367
 
2368
  if (name (to.where_exp) == apply_tag) {	/* pushing */
2369
    where reg_w;
2370
    if (name(fe) == real_tag) {
2371
      int fv = name(sh(fe)) - shrealhd;
2372
      r2l fint;
2373
      fint = real2longs_IEEE(&flptnos[no(fe)], fv);
2374
      if (sz >= 96)
2375
        move(slongsh, mw(zeroe, fint.i3), to);
2376
      if (sz >= 64)
2377
        move(slongsh, mw(zeroe, fint.i2), to);
2378
      move(slongsh, mw(zeroe, fint.i1), to);
2379
      son(fe) = holdfe;
2380
      son(te) = holdte;
2381
      return;
2382
    };
2383
    /* we are pushing on parameter stack */
2384
    if (sz == 32) {
2385
      reg_w = equiv_reg (from, sz);
2386
      if (reg_w.where_exp != nilexp) {
2387
	ins1(pushl, 32, reg_w);
2388
#ifdef NEWDWARF
2389
	if (diagnose && dwarf2 && no_frame)
2390
	  dw2_track_push();
2391
#endif
2392
	son(fe) = holdfe;
2393
	son(te) = holdte;
2394
	return;
2395
      };
2396
    };
2397
    if (sz == 64) {	/* must be s64 or u64 */
2398
      if (name (fe) == val_tag) {	/* moving a constant integer */
2399
	if (!isbigval(fe)) {
2400
	  c = no (fe) + from.where_off;
2401
	  c1 = (name(sha) == s64hd && c < 0) ? -1 : 0;
2402
	}
2403
	else {
2404
	  flt64 x;
2405
	  int ov;
2406
	  x = flt_to_f64(no(fe), is_signed(sh(fe)), &ov);
2407
	  c = x.small;
2408
	  c1 = x.big;
2409
	}
2410
	ins1 (pushl, 32, mw(zeroe, c1));
2411
#ifdef NEWDWARF
2412
	if (diagnose && dwarf2 && no_frame)
2413
	  dw2_track_push();
2414
#endif
2415
 
2416
	ins1 (pushl, 32, mw(zeroe, c));
2417
#ifdef NEWDWARF
2418
	if (diagnose && dwarf2 && no_frame)
2419
	  dw2_track_push();
2420
#endif
2421
 
2422
	son(fe) = holdfe;
2423
	son(te) = holdte;
2424
	return;
2425
      }
2426
      move (sha, from, reg0);
2427
      ins0 (pushedx);
2428
#ifdef NEWDWARF
2429
      if (diagnose && dwarf2 && no_frame)
2430
	dw2_track_push();
2431
#endif
2432
 
2433
      ins0 (pusheax);
2434
#ifdef NEWDWARF
2435
      if (diagnose && dwarf2 && no_frame)
2436
	dw2_track_push();
2437
#endif
2438
 
2439
      son(fe) = holdfe;
2440
      son(te) = holdte;
2441
      return;
2442
    };
2443
    if (sz < 32 ||
2444
         (is80486 && inmem(from))) {
2445
      move (sha, from, reg0);
2446
      ins1 (pushl, 32, reg0);
2447
#ifdef NEWDWARF
2448
      if (diagnose && dwarf2 && no_frame)
2449
	dw2_track_push();
2450
#endif
2451
 
2452
      son(fe) = holdfe;
2453
      son(te) = holdte;
2454
      return;
2455
    };
2456
    contop (from.where_exp, 0, reg0);
2457
    ins1 (pushl, sz, from);
2458
#ifdef NEWDWARF
2459
    if (diagnose && dwarf2 && no_frame)
2460
      dw2_track_push();
2461
#endif
2462
 
2463
    end_contop ();
2464
    son(fe) = holdfe;
2465
    son(te) = holdte;
2466
    return;
2467
  };
2468
 
2469
 
2470
  if (inmem (from) && inmem (to) && ((sz <= 32 && sz != 24)
2471
				|| name(sha) == u64hd || name(sha) == s64hd)) {
2472
    /* from and to are both in memory */
2473
    move (sha, from, reg0);
2474
    move (sha, reg0, to);
2475
    son(fe) = holdfe;
2476
    son(te) = holdte;
2477
    return;
2478
  };
2479
 
2480
  if (name(fe) == real_tag) {
2481
    int fv = name(sh(fe)) - shrealhd;
2482
    r2l fint;
2483
    fint = real2longs_IEEE(&flptnos[no(fe)], fv);
2484
    move(slongsh, mw(zeroe, fint.i1), to);
2485
    if (sz >= 64)
2486
      move(slongsh, mw(zeroe, fint.i2), mw(te, to.where_off + 32));
2487
    if (sz >= 96)
2488
      move(slongsh, mw(zeroe, fint.i3), mw(te, to.where_off + 64));
2489
    son(fe) = holdfe;
2490
    son(te) = holdte;
2491
    return;
2492
  };
2493
 
2494
  if (name (fe) == val_tag) {	/* moving a constant integer */
2495
    isco = 1;
2496
    if (!isbigval(fe)) {
2497
      c = no (fe) + from.where_off;
2498
      if (sz == 64)
2499
	c1 = (name(sha) == s64hd && c < 0) ? -1 : 0;
2500
    }
2501
    else {
2502
      flt64 x;
2503
      int ov;
2504
      x = flt_to_f64(no(fe), is_signed(sh(fe)), &ov);
2505
      c = x.small;
2506
      c1 = x.big;
2507
    }
2508
  };
2509
  if (name (fe) == null_tag) {	/* moving a constant null */
2510
    isco = 1;
2511
    c = no(fe);
2512
  };
2513
 
2514
 
2515
  if (isco) {			/* moving a constant */
2516
 
2517
    contop (te, 0, to);
2518
    SET(c);
2519
 
2520
    if (c == 0 && !inmem (to) && sz <= 32) {/* constant is zero, so clear */
2521
      cond1_set = 0;
2522
      cond2_set = 0;
2523
      ins2 (xorl, 32, 32, to, to);
2524
      invalidate_dest (to);
2525
      end_contop ();
2526
      son(fe) = holdfe;
2527
      son(te) = holdte;
2528
      return;
2529
    };
2530
 
2531
    /* use fastest operation for each size of constant */
2532
 
2533
    if (sz == 8 && !eq_where (to, reg5) && !eq_where (to, reg4)) {
2534
      ins2 (movb, sz, sz, mw (zeroe, (c & 0xff)), to);
2535
      invalidate_dest (to);
2536
      end_contop ();
2537
      son(fe) = holdfe;
2538
      son(te) = holdte;
2539
      return;
2540
    };
2541
 
2542
    if (sz == 16) {
2543
      ins2 (movw, sz, sz, mw (zeroe, (c & 0xffff)), to);
2544
      invalidate_dest (to);
2545
      end_contop ();
2546
      son(fe) = holdfe;
2547
      son(te) = holdte;
2548
      return;
2549
    };
2550
 
2551
    if (sz == 64) {
2552
      if (eq_where (to, reg0)) {
2553
	if (c == 0)
2554
	  ins2 (xorl, 32, 32, reg0, reg0);
2555
	else
2556
	  ins2 (movl, 32, 32, mw (zeroe, c), reg0);
2557
	if (c1 == 0)
2558
	  ins2 (xorl, 32, 32, reg1, reg1);
2559
	else
2560
	  ins2 (movl, 32, 32, mw (zeroe, c1), reg1);
2561
	invalidate_dest (reg0);
2562
	invalidate_dest (reg1);
2563
      }
2564
      else {
2565
        ins2 (movl, 32, 32, mw (zeroe, c), to);
2566
        ins2 (movl, 32, 32, mw (zeroe, c1), mw (te, to.where_off + 32));
2567
	invalidate_dest (to);
2568
      }
2569
      end_contop ();
2570
      son(fe) = holdfe;
2571
      son(te) = holdte;
2572
      return;
2573
    }
2574
 
2575
    if (inmem(to) && (c == 0 &&
2576
	 ((name(te) == ass_tag && name(son(te)) == name_tag &&
2577
		isvar(son(son(te)))) ||
2578
		(name(te) == ident_tag)))) {
2579
      reg_w = equiv_reg (from, sz);
2580
      if (reg_w.where_exp != nilexp)
2581
	move (sha, reg_w, to);
2582
      else {
2583
        move(slongsh, from, reg0);
2584
        move(slongsh, reg0, to);
2585
        move_reg(from, reg0, sha);
2586
      };
2587
    }
2588
    else {
2589
      ins2 (movl, 32, 32, from, to);
2590
    }
2591
 
2592
    invalidate_dest (to);
2593
    end_contop ();
2594
    son(fe) = holdfe;
2595
    son(te) = holdte;
2596
    return;
2597
  };
2598
 
2599
  /* moving a non-constant value */
2600
 
2601
 
2602
 
2603
  if (sz == 8) {		/* moving a byte */
2604
    if (!inmem (from) &&
2605
	(in_reg (from.where_exp) & 0x70)) {
2606
      if (!inmem (to)) {
2607
	move (slongsh, from, to);
2608
	son(fe) = holdfe;
2609
	son(te) = holdte;
2610
	return;
2611
      };
2612
      move (slongsh, from, reg0);
2613
      move (sha, reg0, to);
2614
      son(fe) = holdfe;
2615
      son(te) = holdte;
2616
      return;
2617
    };
2618
 
2619
    if (!inmem (to) && name (to.where_exp) != val_tag &&
2620
	(in_reg (to.where_exp) & 0x70)) {
2621
      if (!inmem (from)) {
2622
	move (slongsh, from, to);
2623
	son(fe) = holdfe;
2624
	son(te) = holdte;
2625
	return;
2626
      };
2627
      move (sha, from, reg0);
2628
      move (slongsh, reg0, to);
2629
      son(fe) = holdfe;
2630
      son(te) = holdte;
2631
      return;
2632
    };
2633
 
2634
    if (in_reg (from.where_exp)) {
2635
      contop (te, eq_where (reg0, from), to);
2636
      ins2 (movb, sz, sz, from, to);
2637
      invalidate_dest (to);
2638
      move_reg (from, to, sha);
2639
      end_contop ();
2640
    }
2641
    else {
2642
      reg_w = equiv_reg (from, sz);
2643
      if (reg_w.where_exp != nilexp) {
2644
	move (sha, reg_w, to);
2645
	move_reg (from, to, sha);
2646
      }
2647
      else {
2648
	contop (fe, 0, to);
2649
	ins2 (movb, sz, sz, from, to);
2650
	invalidate_dest (to);
2651
	move_reg (from, to, sha);
2652
	end_contop ();
2653
      };
2654
    };
2655
    son(fe) = holdfe;
2656
    son(te) = holdte;
2657
    return;
2658
  };
2659
  if (sz == 16) {		/* moving 16 bits */
2660
    if (in_reg (from.where_exp)) {
2661
      contop (te, eq_where (reg0, from), to);
2662
      ins2 (movw, sz, sz, from, to);
2663
      invalidate_dest (to);
2664
      move_reg (from, to, sha);
2665
      end_contop ();
2666
    }
2667
    else {
2668
      reg_w = equiv_reg (from, sz);
2669
      if (reg_w.where_exp != nilexp) {
2670
	move (sha, reg_w, to);
2671
	move_reg (from, to, sha);
2672
      }
2673
      else {
2674
	contop (fe, 0, to);
2675
	ins2 (movw, sz, sz, from, to);
2676
	invalidate_dest (to);
2677
	move_reg (from, to, sha);
2678
	end_contop ();
2679
      };
2680
    };
2681
    son(fe) = holdfe;
2682
    son(te) = holdte;
2683
    return;
2684
  };
2685
  if (sz == 32) {		/* moving 32 bits */
2686
 
2687
    if (in_reg (from.where_exp)) {
2688
      contop (te, eq_where (reg0, from), to);
2689
      ins2 (movl, sz, sz, from, to);
2690
      invalidate_dest (to);
2691
      move_reg (from, to, sha);
2692
      end_contop ();
2693
    }
2694
    else {
2695
      reg_w = equiv_reg (from, sz);
2696
      if (reg_w.where_exp != nilexp) {
2697
	move (sha, reg_w, to);
2698
	move_reg (from, to, sha);
2699
      }
2700
      else {
2701
	contop (fe, 0, to);
2702
	ins2 (movl, sz, sz, from, to);
2703
	invalidate_dest (to);
2704
	move_reg (from, to, sha);
2705
	end_contop ();
2706
      };
2707
    };
2708
    son(fe) = holdfe;
2709
    son(te) = holdte;
2710
    return;
2711
  };
2712
 
2713
  if (sz == 64 && (eq_where (to, reg0) || eq_where (from, reg0))) {
2714
				/* moving reg0 & reg1 to or from memory */
2715
    where w1;
2716
    int riu = regsinuse;
2717
    if (!eq_where (from, reg0)) {
2718
      regsinuse |= 0x2;
2719
      contop (fe, 0, reg0);
2720
      w1 = mw (fe, from.where_off + 32);
2721
      ins2 (movl, sz, sz, w1, reg1);
2722
      ins2 (movl, sz, sz, from, reg0);
2723
      invalidate_dest (reg0);
2724
      invalidate_dest (reg1);
2725
      end_contop ();
2726
    }
2727
    else
2728
    if (!eq_where (to, reg0)) {
2729
      regsinuse |= 0x2;
2730
      contop (te, 1, to);
2731
      w1 = mw (te, to.where_off + 32);
2732
      ins2 (movl, sz, sz, reg0, to);
2733
      ins2 (movl, sz, sz, reg1, w1);
2734
      invalidate_dest (to);
2735
      end_contop ();
2736
    };
2737
    regsinuse = riu;
2738
    son(fe) = holdfe;
2739
    son(te) = holdte;
2740
    return;
2741
  }
2742
 
2743
  if (name(sha) == realhd && might_overlap(sha, from, to)) {
2744
     if ((regsinuse & 0x7e) != 0x7e) {
2745
        int  foff = from.where_off;
2746
        int  toff = to.where_off;
2747
        int  old_regsinuse = regsinuse;
2748
        where extra_reg;
2749
 
2750
        contop (fe, 1, to);
2751
        regsinuse = top_regsinuse;
2752
        contop_level++;
2753
        reg0_in_use = 1;
2754
        contop (te, 1, to);
2755
        regsinuse = old_regsinuse;
2756
 
2757
        if ((regsinuse & 0x2) == 0)
2758
	  extra_reg = reg1;
2759
	else
2760
        if ((regsinuse & 0x4) == 0)
2761
	  extra_reg = reg2;
2762
	else
2763
        if ((regsinuse & 0x8) == 0) {
2764
	  extra_reg = reg3;
2765
	  min_rfree |= 0x8;
2766
        }
2767
	else
2768
        if ((regsinuse & 0x10) == 0) {
2769
	  extra_reg = reg4;
2770
	  min_rfree |= 0x10;
2771
        }
2772
	else
2773
        if ((regsinuse & 0x20) == 0) {
2774
	  extra_reg = reg5;
2775
	  min_rfree |= 0x20;
2776
        }
2777
	else
2778
        if ((regsinuse & 0x40) == 0) {
2779
	  extra_reg = reg6;
2780
	  min_rfree |= 0x40;
2781
        }
2782
	else {
2783
	  SET(extra_reg);
2784
	};
2785
        ins2 (movl, size32, size32, mw (fe, foff), reg0);
2786
        ins2 (movl, size32, size32, mw (fe, foff + 32), extra_reg);
2787
        ins2 (movl, size32, size32, reg0, mw (te, toff));
2788
        ins2 (movl, size32, size32, extra_reg, mw (te, toff + 32));
2789
	invalidate_dest(reg0);
2790
	invalidate_dest(extra_reg);
2791
	invalidate_dest(to);
2792
        end_contop ();
2793
        contop_level--;
2794
        end_contop ();
2795
	son(fe) = holdfe;
2796
	son(te) = holdte;
2797
	return;
2798
      };
2799
    move(sha, from, flstack);
2800
    move(sha, flstack, to);
2801
    son(fe) = holdfe;
2802
    son(te) = holdte;
2803
    return;
2804
  };
2805
 
2806
  if (sz <= (40 * 8) && two_contops (fe, te)) {
2807
    int  i;
2808
    int  foff = from.where_off;
2809
    int  toff = to.where_off;
2810
    int  old_regsinuse = regsinuse;
2811
 
2812
 
2813
    contop (fe, 1, to);
2814
    regsinuse = top_regsinuse;
2815
    contop_level++;
2816
    reg0_in_use = 1;
2817
    contop (te, 1, to);
2818
    regsinuse = old_regsinuse;
2819
 
2820
    /* use movl as far as possible */
2821
    for (i = 0; i <= (sz - 32); i = i + 32) {
2822
      ins2 (movl, size32, size32, mw (fe, foff + i), reg0);
2823
      ins2 (movl, size32, size32, reg0, mw (te, toff + i));
2824
      invalidate_dest (mw (te, toff + i));
2825
    };
2826
    if (i == sz) {
2827
      invalidate_dest (reg0);
2828
      end_contop ();
2829
      contop_level--;
2830
      end_contop ();
2831
      son(fe) = holdfe;
2832
      son(te) = holdte;
2833
      return;
2834
    };
2835
    /* move final word and byte if necessary */
2836
    if ((sz - i) >= 16) {
2837
      ins2 (movw, size16, size16, mw (fe, foff + i), reg0);
2838
      ins2 (movw, size16, size16, reg0, mw (te, toff + i));
2839
      invalidate_dest (mw (te, toff + i));
2840
      i += 16;
2841
    };
2842
    if ((sz - i) >= 8) {
2843
      ins2 (movb, size8, size8, mw (fe, foff + i), reg0);
2844
      ins2 (movb, size8, size8, reg0, mw (te, toff + i));
2845
      invalidate_dest (mw (te, toff + i));
2846
    };
2847
    invalidate_dest (reg0);
2848
    end_contop ();
2849
    contop_level--;
2850
    end_contop ();
2851
    son(fe) = holdfe;
2852
    son(te) = holdte;
2853
    return;
2854
  };
2855
 
2856
  if (name(sha) == realhd) {
2857
    move(sha, from, flstack);
2858
    move(sha, flstack, to);
2859
    son(fe) = holdfe;
2860
    son(te) = holdte;
2861
    return;
2862
  };
2863
 
2864
  {				/* use rep movsl to do the move */
2865
    int  old_extra_stack = extra_stack;
2866
    int  old_regsinuse;
2867
    if (regsinuse & 0x20) {
2868
      extra_stack += 32;
2869
      ins0 (pushesi);
2870
#ifdef NEWDWARF
2871
      if (diagnose && dwarf2 && no_frame)
2872
	dw2_track_push();
2873
#endif
2874
    };
2875
    if (regsinuse & 0x10) {
2876
      extra_stack += 32;
2877
      ins0 (pushedi);
2878
#ifdef NEWDWARF
2879
      if (diagnose && dwarf2 && no_frame)
2880
	dw2_track_push();
2881
#endif
2882
    };
2883
    if (regsinuse & 0x4) {
2884
      extra_stack += 32;
2885
      ins0 (pushecx);
2886
#ifdef NEWDWARF
2887
      if (diagnose && dwarf2 && no_frame)
2888
	dw2_track_push();
2889
#endif
2890
    };
2891
    old_regsinuse = regsinuse;
2892
    if (regsinuse & 0x20) {
2893
      mova (from, pushdest);
2894
      extra_stack += 32;
2895
    }
2896
    else {
2897
      mova (from, reg5);
2898
      regsinuse |= 0x20;
2899
    };
2900
 
2901
    mova (to, reg4);
2902
    regsinuse = old_regsinuse;
2903
 
2904
    move (slongsh, mw (zeroe, (sz / 32)), reg2);
2905
 
2906
    if (regsinuse & 0x20) {
2907
      ins0 (popesi);
2908
#ifdef NEWDWARF
2909
      if (diagnose && dwarf2 && no_frame)
2910
	dw2_track_pop();
2911
#endif
2912
    }
2913
    ins0 (rep);
2914
    ins0 (movsl);
2915
 
2916
    /* and move the last word and byte if necessary */
2917
    sz = sz % 32;
2918
    if (sz >= 16) {
2919
      ins0 (movsw);
2920
      sz -= 16;
2921
    };
2922
    if (sz == 8)
2923
      ins0 (movsb);
2924
 
2925
 
2926
    invalidate_dest (reg2);
2927
    invalidate_dest (reg4);
2928
    invalidate_dest (reg5);
2929
    if (regsinuse & 0x4) {
2930
      ins0 (popecx);
2931
#ifdef NEWDWARF
2932
      if (diagnose && dwarf2 && no_frame)
2933
	dw2_track_pop();
2934
#endif
2935
    };
2936
    if (regsinuse & 0x10) {
2937
      ins0 (popedi);
2938
#ifdef NEWDWARF
2939
      if (diagnose && dwarf2 && no_frame)
2940
	dw2_track_pop();
2941
#endif
2942
    };
2943
    if (regsinuse & 0x20) {
2944
      ins0 (popesi);
2945
#ifdef NEWDWARF
2946
      if (diagnose && dwarf2 && no_frame)
2947
	dw2_track_pop();
2948
#endif
2949
    };
2950
    check_stack_max;
2951
    extra_stack = old_extra_stack;
2952
    min_rfree |= 0x30;
2953
    invalidate_dest (to);
2954
    son(fe) = holdfe;
2955
    son(te) = holdte;
2956
    return;
2957
  };
2958
}
2959
 
2960
/* use rep movsb */
2961
void movecont
2962
    PROTO_N ( (from, to, length, nooverlap) )
2963
    PROTO_T ( where from X where to X where length X int nooverlap )
2964
{
2965
  if (nooverlap) {
2966
    int  old_extra_stack = extra_stack;
2967
    if (regsinuse & 0x20) {
2968
      extra_stack += 32;
2969
      ins0 (pushesi);
2970
#ifdef NEWDWARF
2971
      if (diagnose && dwarf2 && no_frame)
2972
	dw2_track_push();
2973
#endif
2974
    }
2975
    if (regsinuse & 0x10) {
2976
      extra_stack += 32;
2977
      ins0 (pushedi);
2978
#ifdef NEWDWARF
2979
      if (diagnose && dwarf2 && no_frame)
2980
	dw2_track_push();
2981
#endif
2982
    }
2983
    ins0 (pushecx);
2984
#ifdef NEWDWARF
2985
    if (diagnose && dwarf2 && no_frame)
2986
      dw2_track_push();
2987
#endif
2988
    extra_stack += 32;
2989
    move (sh(from.where_exp), from, pushdest);
2990
    extra_stack += 32;
2991
    move (sh(to.where_exp), to, pushdest);
2992
    extra_stack += 32;
2993
    move (sh(length.where_exp), length, pushdest);
2994
    ins0 (popecx);
2995
#ifdef NEWDWARF
2996
    if (diagnose && dwarf2 && no_frame)
2997
      dw2_track_pop();
2998
#endif
2999
    ins0 (popedi);
3000
#ifdef NEWDWARF
3001
    if (diagnose && dwarf2 && no_frame)
3002
      dw2_track_pop();
3003
#endif
3004
    ins0 (popesi);
3005
#ifdef NEWDWARF
3006
    if (diagnose && dwarf2 && no_frame)
3007
      dw2_track_pop();
3008
#endif
3009
    move (slongsh, reg2, reg0);
3010
    ins2 (sarl, size8, size32, mw (zeroe, 2), reg2);
3011
    ins0 (rep);
3012
    ins0 (movsl);
3013
    move (slongsh, reg0, reg2);
3014
    ins2 (andl, size32, size32, mw (zeroe, 3), reg2);
3015
    ins0 (rep);
3016
    ins0 (movsb);
3017
    ins0 (popecx);
3018
#ifdef NEWDWARF
3019
    if (diagnose && dwarf2 && no_frame)
3020
      dw2_track_pop();
3021
#endif
3022
    if (regsinuse & 0x10) {
3023
      ins0 (popedi);
3024
#ifdef NEWDWARF
3025
      if (diagnose && dwarf2 && no_frame)
3026
	dw2_track_pop();
3027
#endif
3028
    }
3029
    if (regsinuse & 0x20) {
3030
      ins0 (popesi);
3031
#ifdef NEWDWARF
3032
      if (diagnose && dwarf2 && no_frame)
3033
	dw2_track_pop();
3034
#endif
3035
    }
3036
    check_stack_max;
3037
    extra_stack = old_extra_stack;
3038
    min_rfree |= 0x30;
3039
    invalidate_dest (reg0);
3040
    invalidate_dest (reg2);
3041
    invalidate_dest (to);
3042
  }
3043
  else {
3044
    move(sh(length.where_exp), length, pushdest);
3045
    extra_stack += 32;
3046
    move(sh(from.where_exp), from, pushdest);
3047
    extra_stack += 32;
3048
    move(sh(to.where_exp), to, pushdest);
3049
    if (name_memmove == nilexp)
3050
      name_memmove = make_extn ("memmove", f_proc, 0);
3051
    callins (0, name_memmove, stack_dec);	/* call_libfn("memmove"); */
3052
    extra_stack -= 64;
3053
    add(slongsh, mw(zeroe, 12), sp, sp);
3054
    invalidate_dest(reg0);
3055
    invalidate_dest(reg1);
3056
    invalidate_dest(reg2);
3057
  };
3058
 
3059
  return;
3060
}
3061
 
3062
 
3063
 
3064
 
3065
void retins
3066
    PROTO_Z ()
3067
{
3068
		/* leave proc, discarding any callee parameters */
3069
		/* can overwrite %ecx */
3070
  int n = (remove_struct_ref && has_struct_res(crt_proc_exp)) ? 32 : 0;
3071
  if (callee_size >= 0) {
3072
    if ((n += callee_size) == 0)
3073
      ins0 (ret);
3074
    else
3075
      ins1(ret, 32, mw(zeroe, n/8));
3076
  }
3077
  else {	/* variable sized callees to be discarded */
3078
    ins0 (popecx);	/* return address */
3079
    ins0 ("pop %esp");	/* discard callees */
3080
    if (n != 0)
3081
      add (slongsh, mw (zeroe, n/8), sp, sp);
3082
    ins0 ("jmp *%ecx");
3083
  }
3084
  return;
3085
}
3086
 
3087
void stack_return
3088
    PROTO_N ( (longs) )
3089
    PROTO_T ( int longs )
3090
{
3091
  if (longs == 32 && (regsinuse & 0x2) == 0)
3092
   {
3093
     ins0(popedx);
3094
#ifdef NEWDWARF
3095
      if (diagnose && dwarf2 && no_frame)
3096
	dw2_track_pop();
3097
#endif
3098
     invalidate_dest(reg1);
3099
     stack_dec += longs;
3100
     return;
3101
   };
3102
  if (longs == 32 && (regsinuse & 0x4) == 0)
3103
   {
3104
     ins0(popecx);
3105
#ifdef NEWDWARF
3106
      if (diagnose && dwarf2 && no_frame)
3107
	dw2_track_pop();
3108
#endif
3109
     invalidate_dest(reg2);
3110
     stack_dec += longs;
3111
     return;
3112
   };
3113
  if (is80586 && longs == 64 && (regsinuse & 0x2) == 0)
3114
   {
3115
     ins0(popedx);
3116
#ifdef NEWDWARF
3117
      if (diagnose && dwarf2 && no_frame)
3118
	dw2_track_pop();
3119
#endif
3120
     ins0(popedx);
3121
#ifdef NEWDWARF
3122
      if (diagnose && dwarf2 && no_frame)
3123
	dw2_track_pop();
3124
#endif
3125
     invalidate_dest(reg1);
3126
     stack_dec += longs;
3127
     return;
3128
   };
3129
  if (is80586 && longs == 64 && (regsinuse & 0x4) == 0)
3130
   {
3131
     ins0(popecx);
3132
#ifdef NEWDWARF
3133
      if (diagnose && dwarf2 && no_frame)
3134
	dw2_track_pop();
3135
#endif
3136
     ins0(popecx);
3137
#ifdef NEWDWARF
3138
      if (diagnose && dwarf2 && no_frame)
3139
	dw2_track_pop();
3140
#endif
3141
     invalidate_dest(reg2);
3142
     stack_dec += longs;
3143
     return;
3144
   };
3145
  add (slongsh, mw (zeroe, (longs / 8)), sp, sp);
3146
  stack_dec += longs;
3147
#ifdef NEWDWARF
3148
  if (diagnose && dwarf2 && no_frame)
3149
    dw2_track_sp();
3150
#endif
3151
  return;
3152
}
3153
 
3154
/* call instruction */
3155
void callins
3156
    PROTO_N ( (longs, fn, ret_stack_dec) )
3157
    PROTO_T ( int longs X exp fn X int ret_stack_dec )
3158
{
3159
  cond1_set = 0;
3160
  cond2_set = 0;
3161
  if (name (fn) == name_tag && !isvar (son (fn)) && isglob (son (fn))) {
3162
    exp ind = getexp (f_proc, nilexp, 0, fn, nilexp, 0,
3163
	0, cont_tag);
3164
#ifdef NEWDWARF
3165
    if (current_dg_info) {
3166
      current_dg_info->data.i_call.brk = set_dw_text_label ();
3167
      current_dg_info->data.i_call.p.k = WH_STR;
3168
      current_dg_info->data.i_call.p.u.s = (brog(son(fn)))->dec_u.dec_val.dec_id;
3169
      current_dg_info->data.i_call.p.o = no(fn)/8;
3170
    }
3171
#endif
3172
    ins1 (call, 32, mw (ind, 0));
3173
    retcell (ind);
3174
  }
3175
  else {
3176
    if (inmem (mw (fn, 0))) {
3177
      move (slongsh, mw (fn, 0), reg0);
3178
      fn = reg0.where_exp;
3179
    };
3180
#ifdef NEWDWARF
3181
    if (current_dg_info) {
3182
      int rn;
3183
      if (name(fn)==name_tag && !isvar(son(fn)))
3184
	rn = no(son(fn));
3185
      else
3186
      if (name(fn)==cont_tag && name(son(fn))==name_tag && 
3187
		isvar(son(son(fn))))
3188
	rn = no(son(son(fn)));
3189
      else {
3190
	failer ("where?");
3191
	rn = 1;
3192
      }
3193
      current_dg_info->data.i_call.brk = set_dw_text_label ();
3194
      current_dg_info->data.i_call.p.k = WH_REG;
3195
      current_dg_info->data.i_call.p.u.l = get_reg_no (rn);
3196
    }
3197
#endif
3198
    ins1ind (call, 32, mw (fn, 0));
3199
  };
3200
  stack_dec = ret_stack_dec;
3201
#ifdef NEWDWARF
3202
  START_BB ();
3203
#endif
3204
  if (longs == 32 || (longs == 64 && is80586) ||
3205
	!no_frame || !not_in_params || !not_in_postlude)
3206
    stack_return(longs);
3207
  else
3208
    keep_short = 1;
3209
  return;
3210
}
3211
 
3212
void jumpins
3213
    PROTO_N ( (lab) )
3214
    PROTO_T ( exp lab )
3215
{
3216
    if (inmem (mw (lab, 0))) {
3217
      move (slongsh, mw (lab, 0), reg0);
3218
      lab = reg0.where_exp;
3219
    };
3220
    ins1ind (jmp, 32, mw (lab, 0));
3221
    return;
3222
}
3223
 
3224
 
3225
 
3226
/* compare from with min (from - min)
3227
   values have shape sha. The testno for
3228
   which it is being used is supplied so
3229
   that we can optimise cmp(0,x)
3230
 
3231
   Result true (1) if optimised compare with 0
3232
   in which case we need to ignore overflow */
3233
int cmp
3234
    PROTO_N ( (sha, from, min, nt, e) )
3235
    PROTO_T ( shape sha X where from X where min X int nt X exp e )
3236
{
3237
  int  sz;
3238
  exp cc = cond1.where_exp;
3239
  exp cc2a = cond2a.where_exp;
3240
  exp me;
3241
  int contop_done = 0;
3242
  where has_equiv_from;
3243
  where has_equiv_min;
3244
  exp hold_from = son(from.where_exp);
3245
  exp hold_min = son(min.where_exp);
3246
  sz = shape_size(sha);
3247
 
3248
  if (cond1_set &&
3249
      (eq_where (min, zero) || (name(min.where_exp) == null_tag && no(min.where_exp) == 0)) &&
3250
      (is_signed (sha) || nt >= 5) &&
3251
      ((name (cc) == ident_tag && eq_shape (sh (son (cc)), sha)) ||
3252
	(name (cc) == ass_tag && eq_shape (sh (bro (son (cc))), sha)) ||
3253
	eq_shape (sh (cc), sha)) &&
3254
      eq_where (cond1, from) && sz <= 32)
3255
    return 1;			/* we are comparing the value from which
3256
				   the conditions are set with zero */
3257
 
3258
  if (cond2_set &&
3259
	((name (cc2a) == ident_tag && eq_shape (sh (son (cc2a)), sha)) ||
3260
	  eq_shape (sh (cc2a), sha)) &&
3261
	eq_where (cond2a, from) &&
3262
	eq_where (cond2b, min))
3263
    return 0;			/* we are repeating the previous
3264
				   comparison */
3265
 
3266
 
3267
  if (!is_floating (name (sha))) {
3268
    where orig_min;
3269
    orig_min = min;
3270
    has_equiv_from = equiv_reg (from, sz);
3271
    if (has_equiv_from.where_exp != nilexp) {
3272
      from = has_equiv_from;
3273
      hold_from = son(from.where_exp);
3274
    }
3275
    has_equiv_min = equiv_reg(min, sz);
3276
    if (has_equiv_min.where_exp != nilexp) {
3277
      min = has_equiv_min;
3278
      hold_min = son(min.where_exp);
3279
    }
3280
 
3281
    if (cond1_set &&
3282
        (eq_where (min, zero) || (name(min.where_exp) == null_tag && no(min.where_exp) == 0)) &&
3283
        (is_signed (sha) || nt >= 5) &&
3284
        ((name (cc) == ident_tag && eq_shape (sh (son (cc)), sha)) ||
3285
	  (name (cc) == ass_tag && eq_shape (sh (bro (son (cc))), sha)) ||
3286
	  eq_shape (sh (cc), sha)) &&
3287
        eq_where (cond1, from) && sz <= 32)
3288
      return 1;			/* we are comparing the value from which
3289
				   the conditions are set with zero */
3290
 
3291
    if (cond2_set &&
3292
	  ((name (cc2a) == ident_tag && eq_shape (sh (son (cc2a)), sha)) ||
3293
	    eq_shape (sh (cc2a), sha)) &&
3294
	  eq_where (cond2a, from) &&
3295
	  eq_where (cond2b, min))
3296
      return 0;			/* we are repeating the previous
3297
				   comparison */
3298
 
3299
    if (((name(min.where_exp) == null_tag && no(min.where_exp) == 0)
3300
	 || eq_where (min, zero)) &&
3301
	!inmem (from)) {
3302
				/* min is zero */
3303
 
3304
      cond1_set = 1;
3305
      cond2_set = 0;
3306
      cond1 = from;
3307
 
3308
 
3309
      if (sz == 8) {
3310
	ins2 (testb, sz, sz, from, from);
3311
	return 0;
3312
      };
3313
      if (sz == 16) {
3314
	ins2 (testw, sz, sz, from, from);
3315
	return 0;
3316
      };
3317
      if (sz == 32) {
3318
	ins2 (testl, sz, sz, from, from);
3319
	return 0;
3320
      };
3321
      if (sz == 64) {	/* !inmem, so from must be reg0/reg1 */
3322
	if (nt >= 5) {
3323
	  ins2 (orl, 32, 32, reg1, reg0);
3324
	  invalidate_dest (reg0);
3325
	  cond1_set = 0;
3326
	  return 0;
3327
	}
3328
	else
3329
	if (nt == f_less_than || nt == f_greater_than_or_equal) {
3330
	  ins2 (testl, 32, 32, reg1, reg1);
3331
	  cond1_set = 0;
3332
	  return 0;
3333
	}
3334
      }
3335
    };
3336
 
3337
 
3338
    cond1_set = 0;
3339
    cond2_set = 1;
3340
    cond2a = from;
3341
    cond2b = min;
3342
 
3343
 
3344
    if (nt >= 5 &&
3345
        ((name(from.where_exp) == null_tag && no(from.where_exp) == 0) ||
3346
		 eq_where (from, zero)) &&
3347
        !inmem (min)) {
3348
      /* from is zero and the test is == or != so we don't have to reverse
3349
         its sense */
3350
 
3351
      if (sz == 8) {
3352
	ins2 (testb, sz, sz, min, min);
3353
	return 0;
3354
      };
3355
      if (sz == 16) {
3356
	ins2 (testw, sz, sz, min, min);
3357
	return 0;
3358
      };
3359
      if (sz == 32) {
3360
	ins2 (testl, sz, sz, min, min);
3361
	return 0;
3362
      };
3363
      if (sz == 64) {	/* !inmem, so min must be reg0/reg1 */
3364
	ins2 (orl, 32, 32, reg1, reg0);
3365
	invalidate_dest (reg0);
3366
	cond2_set = 0;
3367
	return 0;
3368
      }
3369
    };
3370
 
3371
    if (sz != 16 && sz <= 32 && ((name(min.where_exp) == null_tag ||
3372
		 name(min.where_exp) == val_tag) &&
3373
			 no(min.where_exp) == 0) &&
3374
        inmem (from) && has_equiv_from.where_exp == nilexp) {
3375
      {
3376
        move(sha, from, reg0);
3377
	cond1_set = 0;
3378
	cond2_set = 0;
3379
        IGNORE cmp(sha, reg0, min, nt, e);
3380
      };
3381
      return 0;
3382
    };
3383
 
3384
    {
3385
      char *in;
3386
      int riu = regsinuse;
3387
      switch (sz) {
3388
	case 8:
3389
	  in = cmpb;
3390
	  break;
3391
	case 16:
3392
	  in = cmpw;
3393
	  break;
3394
	case 32:
3395
	case 64:
3396
	  in = cmpl;
3397
	  break;
3398
	default:
3399
	  failer("unexpected size");
3400
      };
3401
 
3402
      if ((inmem (from) && inmem (min)) ||
3403
	  (name (sha) == prokhd && !PIC_code && !eq_where(min, reg0)) ||
3404
	  (name (from.where_exp) == name_tag &&
3405
	    isvar (son (from.where_exp))) ||
3406
	   (name(from.where_exp) == reff_tag &&
3407
	    name(son(from.where_exp)) == name_tag &&
3408
	    !isvar(son(son(from.where_exp))))) {
3409
	if ((name (from.where_exp) == name_tag &&
3410
	    ((isvar (son (from.where_exp)) &&
3411
	      ptno (son (from.where_exp)) <= par_pl) ||
3412
            ( PIC_code &&
3413
              isglob(son (from.where_exp)) &&
3414
	      (name (sha) == prokhd || name(sha) == ptrhd) &&
3415
              !brog(son(from.where_exp)) ->  dec_u.dec_val.extnamed))) ||
3416
	      name(from.where_exp) == reff_tag)
3417
	  mova (from, reg0);
3418
	else
3419
	  move (sha, from, reg0);
3420
	son(from.where_exp) = hold_from;
3421
	from = reg0;
3422
	hold_from = son(from.where_exp);
3423
      }
3424
      else {
3425
	if (inmem (from)) {
3426
	  if (sz == 64)
3427
	    regsinuse |= 0x2;
3428
	  contop (from.where_exp, eq_where (reg0, min), reg0);
3429
	  contop_done = 1;
3430
	};
3431
      };
3432
 
3433
      if ((name(min.where_exp) == val_tag || name(min.where_exp) == env_offset_tag) &&
3434
            ((name(from.where_exp) == val_tag || name(from.where_exp) == env_offset_tag) ||
3435
		(keep_short && inmem(from))))  {
3436
        move (sha, from, reg0);
3437
	son(from.where_exp) = hold_from;
3438
        from = reg0;
3439
	hold_from = son(from.where_exp);
3440
      };
3441
 
3442
      if (eq_where (from, reg0) && eq_where (min, reg0)
3443
				&& !eq_where (orig_min, reg0)) {
3444
	son(min.where_exp) = hold_min;
3445
	min = orig_min;		/* equiv_reg lost due to evaluation of from */
3446
	hold_min = son(min.where_exp);
3447
      }
3448
 
3449
      me = min.where_exp;
3450
      if ((name (me) == name_tag && isvar (son (me)) &&
3451
	     ptno (son (me)) <= par_pl) ||
3452
          (PIC_code && name (me) == name_tag && isglob(son(me)) &&
3453
            (name(sha) == prokhd || name(sha) == ptrhd) &&
3454
             !brog(son(me)) ->  dec_u.dec_val.extnamed) ||
3455
	   (name(me) == reff_tag && name(son(me)) == name_tag &&
3456
	    !isvar(son(son(me))))){
3457
	if (eq_where (from, reg0)) {
3458
          ins0(pusheax);
3459
#ifdef NEWDWARF
3460
	  if (diagnose && dwarf2 && no_frame)
3461
	    dw2_track_push();
3462
#endif
3463
          extra_stack += 32;
3464
	  check_stack_max;
3465
	  mova (min, reg0);
3466
	  ins2 (in, sz, sz, reg0, mw(ind_sp.where_exp, -32));
3467
	  invalidate_dest (ind_sp);
3468
	  invalidate_dest (reg0);
3469
          ins0(popeax);
3470
#ifdef NEWDWARF
3471
	  if (diagnose && dwarf2 && no_frame)
3472
	    dw2_track_pop();
3473
#endif
3474
          extra_stack -= 32;
3475
	  son(from.where_exp) = hold_from;
3476
	  son(min.where_exp) = hold_min;
3477
          return 0;
3478
	};
3479
	mova (min, reg0);
3480
	son(min.where_exp) = hold_min;
3481
	min = reg0;
3482
	hold_min = son(min.where_exp);
3483
     }
3484
      else {
3485
	if (inmem (min)) {
3486
	  if (sz == 64)
3487
	    regsinuse |= 0x2;
3488
	  contop (min.where_exp, eq_where (reg0, from), reg0);
3489
	  contop_done = 1;
3490
	};
3491
      };
3492
 
3493
      if (sz == 8 && (eq_where (min, reg4) || eq_where (min, reg5))) {
3494
	if (!eq_where (from, reg0)) {
3495
	  move (sha, min, reg0);
3496
	  son(min.where_exp) = hold_min;
3497
	  min = reg0;
3498
	  hold_min = son(min.where_exp);
3499
	}
3500
	else {
3501
	  sub (sha, min, reg0, reg0);
3502
	  if (contop_done)
3503
	    end_contop ();
3504
	  son(from.where_exp) = hold_from;
3505
	  son(min.where_exp) = hold_min;
3506
	  return 0;
3507
	}
3508
      };
3509
 
3510
      if (sz != 64) {
3511
	ins2 (in, sz, sz, min, from);/* do the comparison */
3512
	if (contop_done)
3513
	  end_contop ();
3514
	son(from.where_exp) = hold_from;
3515
	son(min.where_exp) = hold_min;
3516
	return 0;
3517
      }
3518
      {		/* compare 64bit */
3519
	where fromlo, fromhi, minlo, minhi;
3520
	cond2_set = 0;
3521
	if (eq_where (from, reg0)) {
3522
	  fromlo = reg0;
3523
	  fromhi = reg1;
3524
	}
3525
	else {
3526
	  fromlo = from;
3527
	  fromhi = mw (from.where_exp, from.where_off + 32);
3528
	}
3529
	if (eq_where (min, reg0)) {
3530
	  minlo = reg0;
3531
	  minhi = reg1;
3532
	}
3533
	else
3534
	if (name(min.where_exp) == val_tag) {
3535
	  int c, c1;
3536
	  if (!isbigval(min.where_exp)) {
3537
	    c = no(min.where_exp);
3538
	    c1 = (is_signed(sha) && c < 0) ? -1 : 0;
3539
	    if (c == 0 && (nt == f_greater_than_or_equal || nt == f_less_than)) {
3540
				/* sign bit says it all, so ignore fromlo */
3541
	      ins2 (cmpl, 32, 32, zero, fromhi);
3542
	      if (contop_done)
3543
		end_contop ();
3544
	      regsinuse = riu;
3545
	      son(from.where_exp) = hold_from;
3546
	      son(min.where_exp) = hold_min;
3547
	      return 0;
3548
	    }
3549
	  }
3550
	  else {
3551
	    flt64 x;
3552
	    int ov;
3553
	    x = flt_to_f64(no(min.where_exp), is_signed(sha), &ov);
3554
	    c = x.small;
3555
	    c1 = x.big;
3556
	  }
3557
	  minlo = mw (zeroe, c);
3558
	  minhi = mw (zeroe, c1);
3559
	}
3560
	else {
3561
	  minlo = min;
3562
	  minhi = mw (min.where_exp, min.where_off + 32);
3563
	}
3564
	if (nt >= 5 || !is_signed(sha)) {
3565
	  int flags_set_lab = next_lab ();
3566
	  ins2 (cmpl, 32, 32, minhi, fromhi);
3567
	  simple_branch (jne, flags_set_lab);
3568
	  ins2 (cmpl, 32, 32, minlo, fromlo);
3569
	  simplest_set_lab (flags_set_lab);
3570
	  if (contop_done)
3571
	    end_contop ();
3572
	  regsinuse = riu;
3573
	  son(from.where_exp) = hold_from;
3574
	  son(min.where_exp) = hold_min;
3575
	  return 0;
3576
	}
3577
	cmp_64hilab = next_lab ();
3578
	ins2 (cmpl, 32, 32, minhi, fromhi);
3579
	cmp64_contop (contop_done);	/* if hi unequal, undo contop and jump to cmp_64hilab */
3580
	ins2 (cmpl, 32, 32, minlo, fromlo);
3581
        if (contop_done)
3582
	  end_contop ();
3583
	regsinuse = riu;
3584
	son(from.where_exp) = hold_from;
3585
	son(min.where_exp) = hold_min;
3586
        return 0;
3587
      }
3588
    };
3589
  }
3590
  else {
3591
    cond1_set = 0;
3592
    cond2_set = 1;
3593
    cond2a = from;
3594
    cond2b = min;
3595
 
3596
    fl_comp (sha, from, min, e);	/* do a floating point comparison */
3597
    son(from.where_exp) = hold_from;
3598
    son(min.where_exp) = hold_min;
3599
    return 0;
3600
  }
3601
}
3602
 
3603
int bad_from_reg
3604
    PROTO_N ( (from) )
3605
    PROTO_T ( where from )
3606
{
3607
    return (!inmem (from) && name (from.where_exp) != val_tag &&
3608
	(in_reg (from.where_exp) & 0x70));
3609
}
3610
 
3611
/* change variety from (which has shape
3612
   fsh) to sha, and put in to */
3613
void change_var_sh
3614
    PROTO_N ( (sha, fsh, from, to) )
3615
    PROTO_T ( shape sha X shape fsh X where from X where to )
3616
{
3617
  exp fe = from.where_exp;
3618
  exp holdfe = son(fe);
3619
  int  szf,			/* size of from */
3620
        szt;			/* size of to */
3621
  int sgf,			/* from is signed */
3622
    sgt;			/* to is signed */
3623
 
3624
  cond1_set = 0;
3625
  cond2_set = 0;		/* see note on move */
3626
 
3627
  szf = shape_size(fsh);
3628
  sgf = is_signed(fsh);
3629
 
3630
  /* set szt and sgt */
3631
  switch (name (sha)) {
3632
    case scharhd:
3633
      szt = 8;
3634
      sgt = 1;
3635
      break;
3636
    case ucharhd:
3637
      szt = 8;
3638
      sgt = 0;
3639
      break;
3640
    case swordhd:
3641
      szt = 16;
3642
      sgt = 1;
3643
      break;
3644
    case uwordhd:
3645
      szt = 16;
3646
      sgt = 0;
3647
      break;
3648
    case slonghd:
3649
      szt = 32;
3650
      sgt = 1;
3651
      break;
3652
    case s64hd:
3653
      szt = 64;
3654
      sgt = 1;
3655
      break;
3656
    case u64hd:
3657
      szt = 64;
3658
      sgt = 0;
3659
      break;
3660
    case bitfhd:
3661
      szt = 32;
3662
      sgt = is_signed(sha);
3663
      sha = (sgt) ? slongsh: ulongsh;
3664
      break;
3665
    default:
3666
      szt = 32;
3667
      sgt = 0;
3668
      break;
3669
  };
3670
 
3671
  if (name (fe) == val_tag) {	/* we know the value */
3672
    int val;
3673
    if (!isbigval(fe)) {
3674
      val = dochvar (no (fe), sha);
3675
      if (overflow_e != nilexp && (dochvar (no (fe), fsh) != val || (val < 0 &&
3676
		((szt == 32 && (sgt != sgf)) || (szt == 64 && !sgt && sgf)))))
3677
	do_exception ();
3678
      no (fe) = val;
3679
    }
3680
    else {
3681
      flt64 x;
3682
      int ov;
3683
      x = flt_to_f64(no(fe), sgf, &ov);
3684
      val = dochvar ((int)(x.small), sha);
3685
      if (overflow_e != nilexp && (
3686
		(szt == 64 && x.big < 0 && (sgt != sgf)) ||
3687
		(szt == 32 && ((!(x.small & (1<<31)) && x.big != 0) ||
3688
			((x.small & (1<<31)) && x.big != -sgt))) ||
3689
		(szt < 32)))
3690
	do_exception ();
3691
      if (szt != 64) {
3692
	no (fe) = val;
3693
	clearbigval (fe);
3694
      }
3695
    };
3696
    sh (fe) = sha;
3697
    move (sha, from, to);
3698
    return;
3699
  };
3700
 
3701
 
3702
  if (name(fsh) == bitfhd) {
3703
    if (szf < 8) {
3704
      if (sgf && !sgt) {
3705
	and (scharsh, from, mw (zeroe, (1 << szf) - 1), reg0);
3706
	from = reg0;
3707
      }
3708
      szf = 8;
3709
      fsh = (sgf) ? scharsh : ucharsh;
3710
    }
3711
    else
3712
    if (szf < 16) {
3713
      if (sgf && !sgt) {
3714
	and (swordsh, from, mw (zeroe, (1 << szf) - 1), reg0);
3715
	from = reg0;
3716
      }
3717
      szf = 16;
3718
      fsh = (sgf) ? swordsh : uwordsh;
3719
    }
3720
    else
3721
    if (szf < 32) {
3722
      if (sgf && !sgt) {
3723
	and (slongsh, from, mw (zeroe, (1 << szf) - 1), reg0);
3724
	from = reg0;
3725
      }
3726
      szf = 32;
3727
      fsh = (sgf) ? slongsh : ulongsh;
3728
    }
3729
  }
3730
 
3731
  if (overflow_e != nilexp && (sgt < sgf || (szt - sgt) < (szf - sgf))) {
3732
    int smax = (szt == 64) ? 0x7fffffff : (1 << (szt-1)) - 1;
3733
    int min = (sgt) ? (-smax)-1 : 0;
3734
    int max = (sgt) ? smax : smax+smax+1;
3735
    if (inmem(from)) {
3736
      move (fsh, from, reg0);
3737
      from = reg0;
3738
    };
3739
    if (szf == 64) {
3740
      if (szt == 64) {
3741
	IGNORE cmp (slongsh, reg1, zero, f_greater_than_or_equal, nilexp);
3742
	test_exception (f_greater_than_or_equal, slongsh);
3743
      }
3744
      else {
3745
	int lab1;
3746
	IGNORE cmp (slongsh, reg1, zero, f_equal, nilexp);
3747
	if (sgf && sgt) {
3748
	  int lab2 = next_lab ();
3749
	  lab1 = next_lab ();
3750
	  simple_branch (je, lab2);
3751
	  IGNORE cmp (slongsh, reg1, mw(zeroe,-1), f_equal, nilexp);
3752
	  test_exception (f_equal, slongsh);
3753
	  IGNORE cmp (ulongsh, from, mw(zeroe,min), f_greater_than_or_equal, nilexp);
3754
	  test_exception (f_greater_than_or_equal, ulongsh);
3755
	  simple_branch (jmp, lab1);
3756
	  simplest_set_lab (lab2);
3757
	}
3758
	else
3759
	  test_exception (f_equal, slongsh);
3760
	if (szt != 32 || sgt) {
3761
	  IGNORE cmp (ulongsh, reg0, mw(zeroe,max), f_less_than_or_equal, nilexp);
3762
	  test_exception (f_less_than_or_equal, ulongsh);
3763
	};
3764
	if (sgf && sgt)
3765
	  simplest_set_lab (lab1);
3766
      };
3767
    }
3768
    else {
3769
      if (sgf && (!sgt || szt < szf)) {
3770
	IGNORE cmp (fsh, from, mw(zeroe,min), f_greater_than_or_equal, nilexp);
3771
	test_exception (f_greater_than_or_equal, fsh);
3772
      };
3773
      if ((szt - sgt) < (szf - sgf)) {
3774
	IGNORE cmp (fsh, from, mw(zeroe,max), f_less_than_or_equal, nilexp);
3775
	test_exception (f_less_than_or_equal, fsh);
3776
      };
3777
    };
3778
  }
3779
 
3780
  if (szf == 8) {
3781
    if (bad_from_reg(from)) {
3782
      move (slongsh, from, reg0);
3783
      from = reg0;
3784
    };
3785
 
3786
    if (szt == 8) {
3787
      move (sha, from, to);
3788
      return;
3789
    };
3790
 
3791
    if (szt == 16) {
3792
      if (sgf) {
3793
	if (inmem (to)) {
3794
	  contop (fe, eq_where (reg0, from), reg0);
3795
	  ins2 (movsbw, szf, szt, from, reg0);
3796
	  invalidate_dest (reg0);
3797
	  end_contop ();
3798
	  move (sha, reg0, to);
3799
	}
3800
	else {
3801
	  contop (fe, eq_where (reg0, from), to);
3802
	  ins2 (movsbw, szf, szt, from, to);
3803
	  invalidate_dest (to);
3804
	  end_contop ();
3805
	};
3806
	son(fe) = holdfe;
3807
	return;
3808
      }
3809
      else {
3810
	if (inmem (to)) {
3811
	  contop (fe, eq_where (reg0, from), reg0);
3812
	  ins2 (movzbw, szf, szt, from, reg0);
3813
	  invalidate_dest (reg0);
3814
	  end_contop ();
3815
	  move (sha, reg0, to);
3816
	}
3817
	else {
3818
	  contop (fe, eq_where (reg0, from), to);
3819
	  ins2 (movzbw, szf, szt, from, to);
3820
	  invalidate_dest (to);
3821
	  end_contop ();
3822
	};
3823
	son(fe) = holdfe;
3824
	return;
3825
      };
3826
    };
3827
    if (szt >= 32) {
3828
      if (sgf) {
3829
	if (inmem (to) || szt == 64) {
3830
	  contop (fe, eq_where (reg0, from), reg0);
3831
	  ins2 (movsbl, szf, 32, from, reg0);
3832
	  invalidate_dest (reg0);
3833
	  end_contop ();
3834
	  if (szt == 64) {
3835
	    if (sgt) {
3836
	      move (slongsh, reg0, reg1);
3837
	      ins2 (sarl, 8, 32, mw(zeroe,31), reg1);
3838
	    }
3839
	    else
3840
	      move (ulongsh, zero, reg1);
3841
	  };
3842
	  move (sha, reg0, to);
3843
	}
3844
	else {
3845
	  contop (fe, eq_where (reg0, from), to);
3846
	  ins2 (movsbl, szf, szt, from, to);
3847
	  invalidate_dest (to);
3848
	  end_contop ();
3849
	};
3850
	son(fe) = holdfe;
3851
	return;
3852
      };
3853
      if (inmem (to) || szt == 64) {
3854
	move(scharsh, from, reg0);
3855
	and(slongsh, reg0, mw(zeroe, 0xff), reg0);
3856
	if (szt == 64)
3857
	  move (ulongsh, zero, reg1);
3858
	move (sha, reg0, to);
3859
	}
3860
      else {
3861
	if (eq_where(to, reg4)|| eq_where(to, reg5)||
3862
		 eq_where(to, reg6)) {
3863
	  contop (fe, eq_where (reg0, from), to);
3864
	  ins2 (movzbl, szf, szt, from, to);
3865
	  invalidate_dest (to);
3866
	  end_contop ();
3867
	}
3868
	else {
3869
	  move(scharsh, from, to);
3870
	  and(slongsh, to, mw(zeroe, 0xff), to);
3871
	};
3872
      };
3873
      son(fe) = holdfe;
3874
      return;
3875
    };
3876
  };
3877
 
3878
  if (szf == 16) {
3879
    if (szt == 8) {
3880
      if (bad_from_reg(from)) {
3881
        move (slongsh, from, reg0);
3882
        from = reg0;
3883
      };
3884
 
3885
      if (sgt) {
3886
	if (inmem (to)) {
3887
	  move (sh (fe), from, reg0);
3888
	  move (sha, reg0, to);
3889
	}
3890
	else
3891
	  move (sha, from, to);
3892
	son(fe) = holdfe;
3893
	return;
3894
      };
3895
      move (sha, from, to);
3896
      son(fe) = holdfe;
3897
      return;
3898
    };
3899
    if (szt == 16) {
3900
      move (sha, from, to);
3901
      son(fe) = holdfe;
3902
      return;
3903
    };
3904
    if (sgf) {
3905
      if (inmem (to) || szt == 64) {
3906
	contop (fe, eq_where (reg0, from), reg0);
3907
	ins2 (movswl, szf, 32, from, reg0);
3908
	invalidate_dest (reg0);
3909
	end_contop ();
3910
	if (szt == 64) {
3911
	  if (sgt) {
3912
	    move (slongsh, reg0, reg1);
3913
	    ins2 (sarl, 8, 32, mw(zeroe,31), reg1);
3914
	  }
3915
	  else
3916
	    move (ulongsh, zero, reg1);
3917
	};
3918
	move (sha, reg0, to);
3919
      }
3920
      else {
3921
	contop (fe, eq_where (reg0, from), to);
3922
	ins2 (movswl, szf, szt, from, to);
3923
	invalidate_dest (to);
3924
	end_contop ();
3925
      };
3926
      son(fe) = holdfe;
3927
      return;
3928
    };
3929
    if (inmem (to) || szt == 64) {
3930
      move(swordsh, from, reg0);
3931
      and(slongsh, reg0, mw(zeroe, 0xffff), reg0);
3932
      if (szt == 64)
3933
	move (ulongsh, zero, reg1);
3934
      move (sha, reg0, to);
3935
    }
3936
    else {
3937
      move(swordsh, from, to);
3938
      and(slongsh, to, mw(zeroe, 0xffff), to);
3939
    };
3940
    son(fe) = holdfe;
3941
    return;
3942
  };
3943
 
3944
  if (szf >= 32) {
3945
    if (szt == 8) {
3946
      if (bad_from_reg(from)) {
3947
        move (slongsh, from, reg0);
3948
        from = reg0;
3949
      };
3950
      if (sgt) {
3951
        if (inmem (from) && inmem (to)) {
3952
	  move (sh (fe), from, reg0);
3953
	  move (sha, reg0, to);
3954
        }
3955
        else
3956
	  move (sha, from, to);
3957
	son(fe) = holdfe;
3958
        return;
3959
      };
3960
      move (sha, from, to);
3961
      son(fe) = holdfe;
3962
      return;
3963
    };
3964
 
3965
    if (szt == 16) {
3966
      if (sgt) {
3967
        if (inmem (to)) {
3968
	  move (sha, from, reg0);
3969
  	  move (sha, reg0, to);
3970
        }
3971
        else
3972
  	  move (sha, from, to);
3973
	son(fe) = holdfe;
3974
        return;
3975
      };
3976
      move (sha, from, to);
3977
      son(fe) = holdfe;
3978
      return;
3979
    };
3980
    if (szt > szf) {
3981
      move (slongsh, from, reg0);
3982
      if (sgf && sgt) {
3983
	move (slongsh, reg0, reg1);
3984
	ins2 (sarl, 8, 32, mw(zeroe,31), reg1);
3985
      }
3986
      else
3987
	move (ulongsh, zero, reg1);
3988
      invalidate_dest (reg0);
3989
      from = reg0;
3990
    }
3991
    move (sha, from, to);
3992
    son(fe) = holdfe;
3993
    return;
3994
  };
3995
 
3996
  if (!sgf)  {
3997
    move (sha, from, to);
3998
    son(fe) = holdfe;
3999
    return;
4000
  };
4001
 
4002
  move(sha, from, to);
4003
  son(fe) = holdfe;
4004
  return;
4005
}
4006
 
4007
/* change variety from to sha, and put in to */
4008
void change_var
4009
    PROTO_N ( (sha, from, to) )
4010
    PROTO_T ( shape sha X where from X where to )
4011
{
4012
  exp fe = from.where_exp;
4013
  shape fsh = sh (fe);
4014
  exp old_overflow_e = overflow_e;
4015
  overflow_e = nilexp;
4016
  change_var_sh (sha, fsh, from, to);
4017
  overflow_e = old_overflow_e;
4018
  return;
4019
}
4020
 
4021
/* change variety from to sha, and put in to */
4022
void change_var_check
4023
    PROTO_N ( (sha, from, to) )
4024
    PROTO_T ( shape sha X where from X where to )
4025
{
4026
  exp fe = from.where_exp;
4027
  shape fsh = sh (fe);
4028
  change_var_sh (sha, fsh, from, to);
4029
  return;
4030
}
4031
 
4032
/* op values a1, a2 of shape sha and put
4033
   them in dest. opb, opw and opl are the
4034
   byte, short and long versions of the
4035
   operator. one is the unit for the
4036
   operator. Similar to plus qv. for
4037
   comments.  */
4038
void andetc
4039
    PROTO_N ( (opb, opw, opl, one, sha, a1, a2, dest) )
4040
    PROTO_T ( char *opb X char *opw X char *opl X int one X shape sha X where a1 X where a2 X where dest )
4041
{
4042
  int  sz;
4043
  exp a = a1.where_exp;
4044
  int  aoff = a1.where_off;
4045
  exp b = a2.where_exp;
4046
  int  boff = a2.where_off;
4047
  exp holda = son(a);
4048
  exp holdb = son(b);
4049
  sz = shape_size(sha);
4050
 
4051
  if (name (a) == val_tag && !isbigval(a) && no (a) + aoff == one) {
4052
    move (sha, a2, dest);
4053
    return;
4054
  };
4055
 
4056
  if (name (b) == val_tag && !isbigval(b) && no (b) + boff == one) {
4057
    move (sha, a1, dest);
4058
    return;
4059
  };
4060
 
4061
  cond1_set = 1;
4062
  cond2_set = 0;
4063
  cond1 = dest;			/* conditions will be set from dest */
4064
 
4065
  if (eq_where (a1, dest) &&
4066
	(!keep_short || !flinmem(dest))) {
4067
    if (!inmem (a1) || !inmem (a2)) {
4068
      /* use 2 address */
4069
      int riu = regsinuse;
4070
      if (sz == 64)
4071
	regsinuse |= 0x2;
4072
      if (inmem (a1))
4073
	contop (a, eq_where (reg0, a2), a1);
4074
      else
4075
	contop (b,
4076
	     (eq_where (reg0, a2) || eq_where (reg0, a1)), a1);
4077
      if (sz == 8) {
4078
	ins2 (opb, sz, sz, a2, a1);
4079
      }
4080
      else
4081
      if (sz == 16) {
4082
	ins2 (opw, sz, sz, a2, a1);
4083
      }
4084
      else
4085
      if (sz == 32) {
4086
	ins2 (opl, sz, sz, a2, a1);
4087
      }
4088
      else
4089
      if (sz == 64) {
4090
	where dhi, dlo, shi, slo;
4091
	if (inmem(a1)) {
4092
	  dlo = a1;
4093
	  dhi = mw (a, aoff+32);
4094
	}
4095
	else {
4096
	  dlo = reg0;
4097
	  dhi = reg1;
4098
	};
4099
	if (name(b) == val_tag) {
4100
	  int c, c1;
4101
	  if (!isbigval(b)) {
4102
	    c = no(b) + boff;
4103
	    c1 = (name(sha) == s64hd && c < 0) ? -1 : 0;
4104
	  }
4105
	  else {
4106
	    flt64 x;
4107
	    int ov;
4108
	    x = flt_to_f64(no(b), is_signed(sha), &ov);
4109
	    c = x.small;
4110
	    c1 = x.big;
4111
	  }
4112
	  if (c != one)
4113
	    ins2 (opl, 32, 32, mw(zeroe, c), dlo);
4114
	  if (c1 != one)
4115
	    ins2 (opl, 32, 32, mw(zeroe, c1), dhi);
4116
	}
4117
	else {
4118
	  if (inmem(a2)) {
4119
	    slo = a2;
4120
	    shi = mw (b, boff+32);
4121
	  }
4122
	  else {
4123
	    slo = reg0;
4124
	    shi = reg1;
4125
	  };
4126
	  ins2 (opl, 32, 32, slo, dlo);
4127
	  ins2 (opl, 32, 32, shi, dhi);
4128
	};
4129
      };
4130
      invalidate_dest (dest);
4131
      end_contop ();
4132
      regsinuse = riu;
4133
      son(a) = holda;
4134
      son(b) = holdb;
4135
      return;
4136
    };
4137
 
4138
    move (sha, a2, reg0);
4139
    andetc (opb, opw, opl, one, sha, reg0, dest, dest);
4140
    return;
4141
  };
4142
 
4143
  if (eq_where (a2, dest) &&
4144
	(!keep_short || !flinmem(dest))) {	/* use 2 address */
4145
    if (!inmem (a1) || !inmem (a2)) {
4146
      int riu = regsinuse;
4147
      if (sz == 64)
4148
	regsinuse |= 0x2;
4149
      if (inmem (a1))
4150
	contop (a, eq_where (reg0, a2), a2);
4151
      else
4152
	contop (b,
4153
	     (eq_where (reg0, a1) || eq_where (reg0, a2)), a2);
4154
      if (sz == 8) {
4155
	ins2 (opb, sz, sz, a1, a2);
4156
      }
4157
      else
4158
      if (sz == 16) {
4159
	ins2 (opw, sz, sz, a1, a2);
4160
      }
4161
      if (sz == 32) {
4162
	ins2 (opl, sz, sz, a1, a2);
4163
      }
4164
      else
4165
      if (sz == 64) {
4166
	where dhi, dlo, shi, slo;
4167
	if (inmem(a2)) {
4168
	  dlo = a2;
4169
	  dhi = mw (b, boff+32);
4170
	}
4171
	else {
4172
	  dlo = reg0;
4173
	  dhi = reg1;
4174
	};
4175
	if (name(a) == val_tag) {
4176
	  int c, c1;
4177
	  if (!isbigval(a)) {
4178
	    c = no(a) + aoff;
4179
	    c1 = (name(sha) == s64hd && c < 0) ? -1 : 0;
4180
	  }
4181
	  else {
4182
	    flt64 x;
4183
	    int ov;
4184
	    x = flt_to_f64(no(a), is_signed(sha), &ov);
4185
	    c = x.small;
4186
	    c1 = x.big;
4187
	  }
4188
	  if (c != one)
4189
	    ins2 (opl, 32, 32, mw(zeroe, c), dlo);
4190
	  if (c1 != one)
4191
	    ins2 (opl, 32, 32, mw(zeroe, c1), dhi);
4192
	}
4193
	else {
4194
	  if (inmem(a1)) {
4195
	    slo = a1;
4196
	    shi = mw (a, aoff+32);
4197
	  }
4198
	  else {
4199
	    slo = reg0;
4200
	    shi = reg1;
4201
	  };
4202
	  ins2 (opl, 32, 32, slo, dlo);
4203
	  ins2 (opl, 32, 32, shi, dhi);
4204
	};
4205
      };
4206
      invalidate_dest (dest);
4207
      end_contop ();
4208
      regsinuse = riu;
4209
      son(a) = holda;
4210
      son(b) = holdb;
4211
      return;
4212
    };
4213
 
4214
    move (sha, a1, reg0);
4215
    andetc (opb, opw, opl, one, sha, reg0, dest, dest);
4216
    return;
4217
  };
4218
 
4219
  switch ((inmem (a1) << 2) + (inmem (a2) << 1) + inmem (dest)) {
4220
    case 0:
4221
      move (sha, a2, dest);
4222
      andetc (opb, opw, opl, one, sha, a1, dest, dest);
4223
      return;
4224
    case 1:
4225
    case 3:
4226
    case 5:
4227
    case 7:
4228
      andetc (opb, opw, opl, one, sha, a1, a2, reg0);
4229
      move (sha, reg0, dest);
4230
      return;
4231
    case 2:
4232
      if (eq_where (a1, reg0))
4233
	reg0_in_use = 1;
4234
      move (sha, a2, dest);
4235
      andetc (opb, opw, opl, one, sha, a1, dest, dest);
4236
      return;
4237
    case 4:
4238
      if (eq_where (a2, reg0))
4239
	reg0_in_use = 1;
4240
      move (sha, a1, dest);
4241
      andetc (opb, opw, opl, one, sha, a2, dest, dest);
4242
      return;
4243
    default: 			/* case 6 */
4244
      move (sha, a2, reg0);
4245
      andetc (opb, opw, opl, one, sha, a1, reg0, reg0);
4246
      move (sha, reg0, dest);
4247
      return;
4248
  };
4249
 
4250
}
4251
 
4252
void and
4253
    PROTO_N ( (sha, a1, a2, dest) )
4254
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
4255
{
4256
  andetc (andb, andw, andl, -1, sha, a1, a2, dest);
4257
  return;
4258
}
4259
 
4260
void or
4261
    PROTO_N ( (sha, a1, a2, dest) )
4262
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
4263
{
4264
  andetc (orb, orw, orl, 0, sha, a1, a2, dest);
4265
  return;
4266
}
4267
 
4268
void xor
4269
    PROTO_N ( (sha, a1, a2, dest) )
4270
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
4271
{
4272
  andetc (xorb, xorw, xorl, 0, sha, a1, a2, dest);
4273
  return;
4274
}
4275
 
4276
 
4277
static void needs_lib64
4278
    PROTO_Z ()
4279
{
4280
  if (!lib64_set) {
4281
    lib64_s_mult = make_extn ("__TDFUs_mult", f_proc, 0);
4282
    lib64_u_mult = make_extn ("__TDFUu_mult", f_proc, 0);
4283
    lib64_div[0] = make_extn ("__TDFUu_div2", f_proc, 0);
4284
    lib64_div[1] = make_extn ("__TDFUs_div2", f_proc, 0);
4285
    lib64_div[2] = make_extn ("__TDFUu_div1", f_proc, 0);
4286
    lib64_div[3] = make_extn ("__TDFUs_div1", f_proc, 0);
4287
    lib64_rem[0] = make_extn ("__TDFUu_rem2", f_proc, 0);
4288
    lib64_rem[1] = make_extn ("__TDFUs_rem2", f_proc, 0);
4289
    lib64_rem[2] = make_extn ("__TDFUu_rem1", f_proc, 0);
4290
    lib64_rem[3] = make_extn ("__TDFUs_rem1", f_proc, 0);
4291
    lib64_error = make_extn ("__TDFerror", slongsh, 1);
4292
    if (!PIC_code)
4293
      lib64_error = getexp (slongsh, nilexp, 1, lib64_error, nilexp, 0, 0, cont_tag);
4294
    lib64_set = 1;
4295
  };
4296
  return;
4297
}
4298
 
4299
 
4300
/* 64-bit multiply a1 by a2, result to reg0/1
4301
   arg shapes sh1, sh2 may be 32 or 64-bit
4302
   proper subset varieties for sha */
4303
static void mult64
4304
    PROTO_N ( (sha, sh1, sh2, a1, a2) )
4305
    PROTO_T ( shape sha X shape sh1 X shape sh2 X where a1 X where a2 )
4306
{
4307
  int riu = regsinuse;	/* we know reg2 not in use */
4308
  exp holda2 = son(a2.where_exp);
4309
 
4310
  if (shape_size(sh1) == 32) {
4311
    if (shape_size(sh2) != 32 || (eq_where (a2, reg0) && !eq_where (a1, reg0))) {
4312
      mult64 (sha, sh2, sh1, a2, a1);
4313
      return;
4314
    };
4315
    if (eq_where (a1, reg0)) {
4316
      int difsg = (is_signed(sh1) != is_signed(sh2));
4317
      int lab1, lab2;
4318
      regsinuse |= 0x2;
4319
      contop (a2.where_exp, 1, a2);
4320
      if (name(a2.where_exp) == val_tag) {
4321
	if ((no(a2.where_exp) = a2.where_off) >= 0) {
4322
	  sh2 = sh1;
4323
	  difsg = 0;
4324
	};
4325
	reg0_in_use = 1;
4326
	move (sh2, a2, reg2);
4327
	a2 = reg2;
4328
      };
4329
      if (difsg && is_signed(sh2)) {
4330
	if (inmem (a2)) {
4331
	  ins2 (movl, 32, 32, a2, reg2);
4332
	  a2 = reg2;
4333
	};
4334
	ins2 (xchg, 32, 32, reg0, reg2);
4335
      };
4336
      if (difsg) {
4337
	lab1 = next_lab();
4338
	lab2 = next_lab();
4339
	ins2 (testl, 32, 32, reg0, reg0);
4340
	simple_branch (jns, lab1);
4341
	ins1 (mull, 32, a2);
4342
	ins2 (decl, 32, 32, a2, reg1);
4343
	simple_branch (jmp, lab2);
4344
	simplest_set_lab (lab1);
4345
	ins1 (mull, 32, a2);
4346
	simplest_set_lab (lab2);
4347
      }
4348
      else
4349
        ins1 ((is_signed(sh1) ? imull : mull), 32, a2);
4350
      end_contop ();
4351
      regsinuse = riu;
4352
      son(a2.where_exp) = holda2;
4353
      return;
4354
    };
4355
	/* neither is in reg0 */
4356
    if (is_signed(sh2) && !is_signed(sh1)) {
4357
      mult64 (sha, sh2, sh1, a2, a1);
4358
      return;
4359
    };
4360
    if (is_signed(sh1)) {
4361
      if (name(a1.where_exp) != val_tag) {
4362
	move (sh1, a1, reg0);
4363
	mult64 (sha, sh1, sh2, reg0, a2);
4364
	return;
4365
      };
4366
      if ((no(a1.where_exp) + a1.where_off) >= 0 || is_signed(sh2)) {
4367
	move (sh2, a2, reg0);
4368
	mult64 (sha, sh2, sh2, reg0, a1);
4369
	return;
4370
      };
4371
	/* otherwise, we are multiplying negative constant by unsigned */
4372
      move (sh1, a1, reg0);
4373
      contop (a2.where_exp, 1, a2);
4374
      if (name(a2.where_exp) == val_tag) {
4375
	reg0_in_use = 1;
4376
	move (sh2, a2, reg2);
4377
	a2 = reg2;
4378
      };
4379
      ins1 (mull, 32, a2);
4380
      ins2 (subl, 32, 32, a2, reg1);
4381
      end_contop ();
4382
      son(a2.where_exp) = holda2;
4383
      return;
4384
    };
4385
	/* both are unsigned */
4386
    if (name(a1.where_exp) == val_tag) {
4387
      move (sh1, a1, reg0);
4388
      mult64 (sha, sh1, sh2, reg0, a2);
4389
      return;
4390
    };
4391
    {
4392
      move (sh2, a2, reg0);
4393
      mult64 (sha, sh2, sh1, reg0, a1);
4394
      return;
4395
    };
4396
  };
4397
 
4398
  if (overflow_e != nilexp && !optop(overflow_e)) {
4399
				/* need library proc to check for overflow */
4400
    needs_lib64();
4401
    if (eq_where (a1, reg0)) {
4402
      a1 = a2;
4403
      a2 = reg0;
4404
    };
4405
    move (sha, a2, pushdest);
4406
    extra_stack += 64;
4407
    move (sha, a1, pushdest);
4408
    extra_stack -= 64;
4409
    callins (0, (is_signed(sha) ? lib64_s_mult : lib64_u_mult), stack_dec);
4410
    add(slongsh, mw(zeroe, 16), sp, sp);
4411
    ins2 (movl, 32, 32, mw(lib64_error, 0), reg2);
4412
    if (PIC_code)
4413
      ins2 (movl, 32, 32, ind_reg2, reg2);
4414
    ins2 (testl, 32, 32, reg2, reg2);
4415
    test_exception (f_greater_than_or_equal, slongsh);
4416
    return;
4417
  };
4418
 
4419
  if (shape_size(sh2) == 32 || (name(a2.where_exp) == val_tag && !isbigval(a2.where_exp))) {
4420
    if (eq_where (a1, reg0)) {
4421
      reg0_in_use = 1;
4422
      regsinuse |= 0x2;
4423
      move (slongsh, a2, reg2);
4424
    }
4425
    else {
4426
      move (slongsh, a2, reg2);
4427
      regsinuse |= 0x4;
4428
      move (sha, a1, reg0);
4429
    }
4430
    ins0 (pushedx);
4431
#ifdef NEWDWARF
4432
    if (diagnose && dwarf2 && no_frame)
4433
      dw2_track_push();
4434
#endif
4435
    if (is_signed(sha) && is_signed(sh2) &&
4436
	  (name(a2.where_exp) != val_tag || (no(a2.where_exp) + a2.where_off) < 0)) {
4437
      ins0 (pusheax);
4438
#ifdef NEWDWARF
4439
      if (diagnose && dwarf2 && no_frame)
4440
	dw2_track_push();
4441
#endif
4442
      ins1 (mull, 32, reg2);
4443
      if (name(a2.where_exp) != val_tag) {
4444
	int lab1 = next_lab();
4445
	ins2 (testl, 32, 32, reg2, reg2);
4446
	simple_branch (jns, lab1);
4447
	ins2 (subl, 32, 32, ind_sp, reg1);
4448
	simplest_set_lab (lab1);
4449
      }
4450
      else
4451
	ins2 (subl, 32, 32, ind_sp, reg1);
4452
      ins2 (addl, 32, 32, mw(zeroe,4), sp);
4453
    }
4454
    else
4455
      ins1 (mull, 32, reg2);
4456
    ins2 (imull, 32, 32, ind_sp, reg2);
4457
    ins2 (addl, 32, 32, reg2, reg1);
4458
    ins0 (popecx);
4459
#ifdef NEWDWARF
4460
    if (diagnose && dwarf2 && no_frame)
4461
      dw2_track_pop();
4462
#endif
4463
    regsinuse = riu;
4464
    return;
4465
  };
4466
 
4467
  if (eq_where (a1, a2)) {
4468
    move (sha, a1, reg0);
4469
    ins0 (pushedx);
4470
#ifdef NEWDWARF
4471
    if (diagnose && dwarf2 && no_frame)
4472
      dw2_track_push();
4473
#endif
4474
    ins2 (movl, 32, 32, reg0, reg2);
4475
    ins1 (mull, 32, reg0);
4476
    ins2 (imull, 32, 32, ind_sp, reg2);
4477
    ins2 (addl, 32, 32, reg2, reg1);
4478
    ins2 (addl, 32, 32, reg2, reg1);
4479
    ins0 (popecx);
4480
#ifdef NEWDWARF
4481
    if (diagnose && dwarf2 && no_frame)
4482
      dw2_track_pop();
4483
#endif
4484
    return;
4485
  };
4486
 
4487
  if (eq_where (a2, reg0)) {
4488
    son(a2.where_exp) = holda2;
4489
    a2 = a1;
4490
    holda2 = son(a2.where_exp);
4491
    a1 = reg0;
4492
  };
4493
  move (sha, a1, reg0);
4494
  reg0_in_use = 1;
4495
  regsinuse |= 0x6;
4496
  contop (a2.where_exp, 1, a2);
4497
  ins0 (pushedx);
4498
#ifdef NEWDWARF
4499
  if (diagnose && dwarf2 && no_frame)
4500
    dw2_track_push();
4501
#endif
4502
  extra_stack += 32;
4503
  ins2 (movl, 32, 32, reg0, reg2);
4504
  ins1 (mull, 32, a2);
4505
  ins2 (imull, 32, 32, mw(a2.where_exp, a2.where_off+32), reg2);
4506
  ins2 (addl, 32, 32, reg2, reg1);
4507
  ins0 (popecx);
4508
#ifdef NEWDWARF
4509
  if (diagnose && dwarf2 && no_frame)
4510
    dw2_track_pop();
4511
#endif
4512
  extra_stack -= 32;
4513
  ins2 (imull, 32, 32, a2, reg2);
4514
  ins2 (addl, 32, 32, reg2, reg1);
4515
  end_contop ();
4516
  regsinuse = riu;
4517
  son(a2.where_exp) = holda2;
4518
  return;
4519
}
4520
 
4521
 
4522
static void clean_multiply
4523
    PROTO_N ( (stored) )
4524
    PROTO_T ( int stored )
4525
{
4526
  if (stored)
4527
   {
4528
      ins0(popedx);
4529
#ifdef NEWDWARF
4530
      if (diagnose && dwarf2 && no_frame)
4531
	dw2_track_pop();
4532
#endif
4533
      extra_stack -= 32;
4534
      invalidate_dest(reg1);
4535
   };
4536
  return;
4537
}
4538
 
4539
/* multiply a1 by a2 add inc and put into
4540
   dest. optimisation have already been
4541
   done. */
4542
void multiply
4543
    PROTO_N ( (sha, a1, a2, dest) )
4544
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
4545
{
4546
  int  sz;
4547
  char *in;
4548
  int stored = 0;
4549
  exp hold_a1 = son(a1.where_exp);
4550
  exp hold_a2 = son(a2.where_exp);
4551
  sz = shape_size(sha);
4552
 
4553
  cond1_set = 0;
4554
  cond2_set = 0;
4555
 
4556
  if (sz == 64) {
4557
    mult64 (sha, sh(a1.where_exp), sh(a2.where_exp), a1, a2);
4558
    move (sha, reg0, dest);
4559
    invalidate_dest (reg0);
4560
    invalidate_dest (reg2);
4561
    return;
4562
  };
4563
 
4564
  if (sz == 8)
4565
    in = imulb;
4566
  else {
4567
    if (sz == 16)
4568
      in = imulw;
4569
    else
4570
      in = imull;
4571
  };
4572
  invalidate_dest (reg0);
4573
  if (name (a2.where_exp) == val_tag && sz != 8 &&
4574
	(is_signed (sha) || overflow_e == nilexp || optop(overflow_e))) {
4575
    	    /* x * const -> y */
4576
    contop (a1.where_exp, eq_where (reg0, a1), dest);
4577
    if (!inmem (dest)) {
4578
        /* x * const -> reg */
4579
      if (name (a1.where_exp) == val_tag) {
4580
	move (sha, a1, dest);
4581
	son(a1.where_exp) = hold_a1;
4582
	a1 = dest;
4583
	hold_a1 = son(a1.where_exp);
4584
      };
4585
      ins3 (in, sz, sz, sz, a2, a1, dest);
4586
      invalidate_dest (dest);
4587
      end_contop ();
4588
      try_overflow (sha, 0);
4589
      son(a1.where_exp) = hold_a1;
4590
      return;
4591
    };
4592
       /* x * const -> notreg   : use reg0 */
4593
    if (name (a1.where_exp) == val_tag) {
4594
      move (sha, a1, reg0);
4595
      son(a1.where_exp) = hold_a1;
4596
      a1 = reg0;
4597
      hold_a1 =  son(a1.where_exp);
4598
    };
4599
    ins3 (in, sz, sz, sz, a2, a1, reg0);
4600
    invalidate_dest (reg0);
4601
    end_contop ();
4602
    try_overflow (sha, 0);
4603
    move (sha, reg0, dest);
4604
    son(a1.where_exp) = hold_a1;
4605
    return;
4606
  };
4607
 
4608
  if (is_signed (sha) && sz != 8) {
4609
      /* signed : we don't have to disturb eax/edx */
4610
    if (!inmem (dest)) {
4611
      if (eq_where (a2, dest)) {
4612
	contop (a1.where_exp,
4613
	     (eq_where (reg0, a1) || eq_where (reg0, a2)),
4614
	    dest);
4615
	ins2 (in, sz, sz, a1, dest);
4616
	invalidate_dest (dest);
4617
	end_contop ();
4618
        try_overflow (sha, 0);
4619
	son(a1.where_exp) = hold_a1;
4620
	return;
4621
      };
4622
      if (eq_where (a1, dest)) {
4623
	contop (a2.where_exp,
4624
	     (eq_where (reg0, a1) || eq_where (reg0, a2)),
4625
	    dest);
4626
	ins2 (in, sz, sz, a2, dest);
4627
	invalidate_dest (dest);
4628
	end_contop ();
4629
        try_overflow (sha, 0);
4630
	son(a2.where_exp) = hold_a2;
4631
	return;
4632
      };
4633
    };
4634
    if (eq_where (reg0, a2)) {
4635
      contop (a1.where_exp, 1, reg0);
4636
      ins2 (in, sz, sz, a1, reg0);
4637
      invalidate_dest (reg0);
4638
      end_contop ();
4639
      try_overflow (sha, 0);
4640
      move (sha, reg0, dest);
4641
      son(a1.where_exp) = hold_a1;
4642
      return;
4643
    };
4644
    move (sha, a1, reg0);
4645
    contop (a2.where_exp, 1, reg0);
4646
    ins2 (in, sz, sz, a2, reg0);
4647
    invalidate_dest (reg0);
4648
    end_contop ();
4649
    try_overflow (sha, 0);
4650
    move (sha, reg0, dest);
4651
    son(a2.where_exp) = hold_a2;
4652
    return;
4653
  }
4654
  else {
4655
       /* unsigned : use mul which only allows eax edx result */
4656
	/* or signed imulb with same constraint */
4657
    if (!is_signed (sha))
4658
      in = &in[1];
4659
    if ((regsinuse & 0x2) && !eq_where (dest, reg1)) {
4660
      stored = 1;
4661
      ins0(pushedx);
4662
#ifdef NEWDWARF
4663
      if (diagnose && dwarf2 && no_frame)
4664
	dw2_track_push();
4665
#endif
4666
      extra_stack += 32;
4667
      check_stack_max;
4668
      invalidate_dest (reg1);
4669
    };
4670
    if (eq_where (reg0, dest)) {
4671
      if (eq_where (a2, reg0)) {
4672
	contop (a1.where_exp, 1, a1);
4673
	if (name (a1.where_exp) == val_tag) {
4674
	  move (sha, a1, reg1);
4675
	  ins1 (in, sz, reg1);
4676
	}
4677
	else {
4678
	  ins1 (in, sz, a1);
4679
	};
4680
        invalidate_dest (reg0);
4681
        invalidate_dest(reg1);
4682
	invalidate_dest (a1);
4683
	end_contop ();
4684
	clean_multiply (stored);
4685
        try_overflow (sha, 0);
4686
	son(a1.where_exp) = hold_a1;
4687
	return;
4688
      };
4689
      if (eq_where (a1, reg0)) {
4690
	contop (a2.where_exp, 1, a2);
4691
	if (name (a2.where_exp) == val_tag) {
4692
	  move (sha, a2, reg1);
4693
	  ins1 (in, sz, reg1);
4694
	}
4695
	else {
4696
	  ins1 (in, sz, a2);
4697
	};
4698
        invalidate_dest (reg0);
4699
        invalidate_dest(reg1);
4700
	invalidate_dest (a2);
4701
	end_contop ();
4702
	clean_multiply (stored);
4703
        try_overflow (sha, 0);
4704
	son(a2.where_exp) = hold_a2;
4705
	return;
4706
      };
4707
    };
4708
    if (eq_where (reg0, a2)) {
4709
      contop (a1.where_exp, 1, a1);
4710
      if (name (a1.where_exp) == val_tag) {
4711
	move (sha, a1, reg1);
4712
	ins1 (in, sz, reg1);
4713
      }
4714
      else {
4715
	ins1 (in, sz, a1);
4716
      };
4717
      invalidate_dest (a1);
4718
      invalidate_dest (reg0);
4719
      invalidate_dest(reg1);
4720
      end_contop ();
4721
      clean_multiply (stored);
4722
      try_overflow (sha, 0);
4723
      move (sha, reg0, dest);
4724
      son(a1.where_exp) = hold_a1;
4725
      return;
4726
    };
4727
    move (sha, a1, reg0);
4728
    contop (a2.where_exp, 1, a2);
4729
    if (name (a2.where_exp) == val_tag) {
4730
      move (sha, a2, reg1);
4731
      ins1 (in, sz, reg1);
4732
    }
4733
    else {
4734
      ins1 (in, sz, a2);
4735
    };
4736
    invalidate_dest (a2);
4737
    invalidate_dest (a1);
4738
    invalidate_dest (reg0);
4739
    invalidate_dest (reg1);
4740
    end_contop ();
4741
    clean_multiply (stored);
4742
    try_overflow (sha, 0);
4743
    move (sha, reg0, dest);
4744
    son(a2.where_exp) = hold_a2;
4745
    return;
4746
  };
4747
}
4748
 
4749
#define short_mults 6
4750
int  mtab[short_mults] = {
4751
  25, 15, 9, 7, 5, 3
4752
};
4753
 
4754
/* do multiplications by small integer constants */
4755
void longc_mult
4756
    PROTO_N ( (a1, a2, dest, inc) )
4757
    PROTO_T ( where a1 X where a2 X where dest X int inc )
4758
{
4759
  int  i,
4760
        j;
4761
  int  n = no (a2.where_exp) + a2.where_off;
4762
  shape sha = slongsh;
4763
  exp holdd = son(dest.where_exp);
4764
 
4765
  if (name(sh(a2.where_exp)) == offsethd && al2(sh(a2.where_exp)) != 1)
4766
     n = n / 8;
4767
 
4768
  cond1_set = 0;
4769
  cond2_set = 0;
4770
 
4771
  if (n == 0) {
4772
    move (sha, zero, dest);
4773
    return;
4774
  };
4775
 
4776
  if (n == 1) {
4777
    move (sha, a1, dest);
4778
    return;
4779
  };
4780
 
4781
 
4782
  switch (n) {
4783
    case 2:
4784
      if (inmem (a1)) {
4785
	where newdest;
4786
	newdest = (inmem (dest)) ? reg0 : dest;
4787
	move (sha, a1, newdest);
4788
	add (sha, newdest, newdest, dest);
4789
	return;
4790
      }
4791
      add(sha, a1, a1, dest);
4792
      return;
4793
    case 3:
4794
      if (inmem (a1)) {
4795
	move (sha, a1, reg0);
4796
	contop (dest.where_exp, 1, dest);
4797
	mult_op (inc, reg0, reg0, 2, dest);
4798
	invalidate_dest (dest);
4799
	son(dest.where_exp) = holdd;
4800
	return;
4801
      };
4802
      contop (dest.where_exp, eq_where (reg0, a1), dest);
4803
      mult_op (inc, a1, a1, 2, dest);
4804
      invalidate_dest (dest);
4805
      son(dest.where_exp) = holdd;
4806
      return;
4807
    case 5:
4808
      if (inmem (a1)) {
4809
	move (sha, a1, reg0);
4810
	contop (dest.where_exp, 1, dest);
4811
	mult_op (inc, reg0, reg0, 4, dest);
4812
	invalidate_dest (dest);
4813
	son(dest.where_exp) = holdd;
4814
	return;
4815
      };
4816
      contop (dest.where_exp, eq_where (reg0, a1), dest);
4817
      mult_op (inc, a1, a1, 4, dest);
4818
      invalidate_dest (dest);
4819
      son(dest.where_exp) = holdd;
4820
      return;
4821
    case 7:
4822
      if (!inmem(a1) && !inmem(dest) && !eq_where(a1, dest)) {
4823
	longc_mult (a1, mw(zeroe, 8), dest, inc);
4824
	sub(sha, a1, dest, dest);
4825
	return;
4826
      };
4827
      if (!inmem(a1) && !inmem(dest)) {
4828
	if (!eq_where(a1, reg0)) {
4829
	  contop (dest.where_exp, 1, dest);
4830
	  mult_op (inc, a1, a1, 2, reg0);
4831
	  mult_op (inc, reg0, a1, 4, dest);
4832
	  invalidate_dest (reg0);
4833
	  invalidate_dest (dest);
4834
	  son(dest.where_exp) = holdd;
4835
	  return;
4836
	}
4837
	else  {
4838
	  ins0(pushedx);
4839
#ifdef NEWDWARF
4840
	  if (diagnose && dwarf2 && no_frame)
4841
	    dw2_track_push();
4842
#endif
4843
	  mult_op (inc, a1, a1, 2, reg1);
4844
	  mult_op (inc, reg1, reg0, 4, dest);
4845
	  invalidate_dest (dest);
4846
	  ins0(popedx);
4847
#ifdef NEWDWARF
4848
	  if (diagnose && dwarf2 && no_frame)
4849
	    dw2_track_pop();
4850
#endif
4851
	  return;
4852
	};
4853
      };
4854
      if (inmem(a1) && !inmem(dest)) {
4855
	move(sha, a1, reg0);
4856
	longc_mult(reg0, a2, dest, inc);
4857
	return;
4858
      };
4859
      multiply (sha, a1, a2, dest);
4860
      return;
4861
    case 9:
4862
      if (inmem (a1)) {
4863
	move (sha, a1, reg0);
4864
	contop (dest.where_exp, 1, dest);
4865
	mult_op (inc, reg0, reg0, 8, dest);
4866
	invalidate_dest (dest);
4867
	son(dest.where_exp) = holdd;
4868
	return;
4869
      };
4870
      contop (dest.where_exp, eq_where (reg0, a1), dest);
4871
      mult_op (inc, a1, a1, 8, dest);
4872
      invalidate_dest (dest);
4873
      son(dest.where_exp) = holdd;
4874
      return;
4875
    case 15: {
4876
        if (!inmem(a1)) {
4877
	  mult_op (inc, a1, a1, 2, reg0);
4878
	}
4879
	else  {
4880
	  move (sha, a1, reg0);
4881
	  mult_op (inc, reg0, reg0, 2, reg0);
4882
	};
4883
	contop (dest.where_exp, 1, dest);
4884
	mult_op (inc, reg0, reg0, 4, dest);
4885
	invalidate_dest (reg0);
4886
	invalidate_dest (dest);
4887
	son(dest.where_exp) = holdd;
4888
	return;
4889
      };
4890
    case 25: {
4891
        if (!inmem(a1)) {
4892
	  mult_op (inc, a1, a1, 4, reg0);
4893
	}
4894
	else  {
4895
	  move (sha, a1, reg0);
4896
	  mult_op (inc, reg0, reg0, 4, reg0);
4897
	};
4898
	contop (dest.where_exp, 1, dest);
4899
	mult_op (inc, reg0, reg0, 4, dest);
4900
	invalidate_dest (reg0);
4901
	invalidate_dest (dest);
4902
	son(dest.where_exp) = holdd;
4903
	return;
4904
      };
4905
    default:
4906
      if ((n & (n - 1)) == 0) {
4907
	int  mask = 1;
4908
	int  c;
4909
	for (c = 0; (mask & n) == 0; ++c)
4910
	  mask += mask;
4911
	shiftl (sha, mw (zeroe, c), a1, dest);
4912
	return;
4913
      };
4914
      if ((-n & (-n - 1)) == 0) {
4915
	int  mask = 1;
4916
	int  c;
4917
	for (c = 0; (mask & -n) == 0; ++c)
4918
	  mask += mask;
4919
	shiftl (sha, mw (zeroe, c), a1, dest);
4920
        negate (sha, dest, dest);
4921
	return;
4922
      };
4923
      for (i = 0; i < short_mults; ++i) {
4924
	if ((n % mtab[i]) == 0) {
4925
	  int  x = n / mtab[i];
4926
	  if ((x & (x - 1)) == 0) {
4927
	    where w;
4928
	    if (inmem (dest))
4929
	      w = reg0;
4930
	    else
4931
	      w = dest;
4932
	    longc_mult (a1, mw (zeroe, mtab[i]), w, 0);
4933
	    longc_mult (w, mw (zeroe, x), dest, inc);
4934
	    return;
4935
	  };
4936
	  for (j = 0; j < short_mults; ++j) {
4937
	    if (x == mtab[j]) {
4938
	      where w;
4939
	      if (inmem (dest))
4940
		w = reg0;
4941
	      else
4942
		w = dest;
4943
	      longc_mult (a1, mw (zeroe, mtab[i]), w, 0);
4944
	      longc_mult (w, mw (zeroe, x), dest, inc);
4945
	      return;
4946
	    };
4947
	  };
4948
	};
4949
      };
4950
      multiply (sha, a1, a2, dest);
4951
      return;
4952
  };
4953
}
4954
 
4955
/* multiply a1 by a2 and put into dest.
4956
   look out for special cases by calling
4957
   longc_mult */
4958
void mult
4959
    PROTO_N ( (sha, a1, a2, dest) )
4960
    PROTO_T ( shape sha X where a1 X where a2 X where dest )
4961
{
4962
  int  inc = 0;
4963
  int sha_size = shape_size(sha);
4964
  cond1_set = 0;
4965
  cond2_set = 0;
4966
 
4967
  if (name (a1.where_exp) == val_tag && sha_size == 32) {
4968
    longc_mult (a2, a1, dest, inc);
4969
    return;
4970
  };
4971
 
4972
  if (name (a2.where_exp) == val_tag && sha_size == 32) {
4973
    longc_mult (a1, a2, dest, inc);
4974
    return;
4975
  };
4976
 
4977
  multiply (sha, a1, a2, dest);
4978
  return;
4979
}
4980
 
4981
 
4982
 
4983
/* shift from wshift places to to. */
4984
void shiftl
4985
    PROTO_N ( (sha, wshift, from, to) )
4986
    PROTO_T ( shape sha X where wshift X where from X where to )
4987
{
4988
  exp p = wshift.where_exp;
4989
  int  places = no (p) + wshift.where_off;
4990
  char *shifter;
4991
  int  sz;
4992
  int sig = is_signed (sha);
4993
  exp holdto = son(to.where_exp);
4994
  sz = shape_size(sha);
4995
 
4996
  cond1_set = 0;
4997
  cond2_set = 0;
4998
 
4999
  if (sz == 64) {
5000
    int riu = regsinuse;
5001
    move (sha, from, reg0);
5002
    if (name(wshift.where_exp) == val_tag)
5003
      rotshift64 (0, sig, wshift);
5004
    else {	/* need count in reg2 */
5005
      if (regsinuse & 0x4) {
5006
        ins0(pushecx);
5007
#ifdef NEWDWARF
5008
	if (diagnose && dwarf2 && no_frame)
5009
	  dw2_track_push();
5010
#endif
5011
        extra_stack += 32;
5012
        check_stack_max;
5013
      };
5014
      reg0_in_use = 1;
5015
      regsinuse |= 0x2;
5016
      move (slongsh, wshift, reg2);
5017
      rotshift64 (0, sig, wshift);
5018
      invalidate_dest (reg2);
5019
      if (regsinuse & 0x4) {
5020
         ins0(popecx);
5021
#ifdef NEWDWARF
5022
	if (diagnose && dwarf2 && no_frame)
5023
	  dw2_track_pop();
5024
#endif
5025
         extra_stack -= 32;
5026
      }
5027
    };
5028
    invalidate_dest (reg0);
5029
    invalidate_dest (reg1);
5030
    move (sha, reg0, to);
5031
    regsinuse = riu;
5032
    return;
5033
  }
5034
 
5035
  switch (sz) {			/* choose shift operation from signedness
5036
				   and length */
5037
    case 8:
5038
      shifter = (sig) ? salb : shlb;
5039
      break;
5040
    case 16:
5041
      shifter = (sig) ? salw : shlw;
5042
      break;
5043
    default:
5044
      shifter = (sig) ? sall : shll;
5045
  };
5046
 
5047
  if (name (p) == val_tag) {	/* no of places is constant */
5048
    if (places >= 32) {
5049
      move (sha, zero, to);
5050
      return;
5051
    };
5052
    if (places == 0)
5053
      {
5054
        move(sha, from, to);
5055
        return;
5056
      };
5057
 
5058
    if (places >=1 && places <= 1)	/* correspond to longc_mult */
5059
     {
5060
       int k = 8;
5061
       if (places == 1)
5062
         k = 2;
5063
       if (places == 2)
5064
         k = 4;
5065
       longc_mult(from, mw(zeroe, k), to, 0);
5066
       return;
5067
     };
5068
 
5069
    if (eq_where (from, to)) {	/* shift in situ */
5070
      contop (to.where_exp, 0, to);
5071
      ins2 (shifter, 8, sz, wshift, to);
5072
      invalidate_dest (to);
5073
      end_contop ();
5074
      son(to.where_exp) = holdto;
5075
      return;
5076
    };
5077
    if (!inmem (to)) {		/* to is a register */
5078
      move (sha, from, to);
5079
      contop (to.where_exp, 0, to);
5080
      ins2 (shifter, 8, sz, wshift, to);
5081
      invalidate_dest (to);
5082
      end_contop ();
5083
      son(to.where_exp) = holdto;
5084
      return;
5085
    };
5086
    /* use reg0 to shift in */
5087
    move (sha, from, reg0);
5088
    ins2 (shifter, 8, sz, wshift, reg0);
5089
    invalidate_dest (reg0);
5090
    move (sha, reg0, to);
5091
    invalidate_dest (to);
5092
    return;
5093
  };
5094
  {				/* we don't know the number of places */
5095
    int   to_reg2,
5096
          wshift_reg2;
5097
    to_reg2 = eq_where (to, reg2);
5098
    wshift_reg2 = eq_where (wshift, reg2);
5099
 
5100
    if (!to_reg2 && (regsinuse & 0x4) && !wshift_reg2) {
5101
      ins0(pushecx);
5102
#ifdef NEWDWARF
5103
      if (diagnose && dwarf2 && no_frame)
5104
	dw2_track_push();
5105
#endif
5106
      extra_stack += 32;
5107
      check_stack_max;
5108
    };
5109
 
5110
    /* scan2 has guaranteed that wshift is not in reg0 */
5111
 
5112
    change_var (slongsh, from, reg0);
5113
    reg0_in_use = 1;
5114
    move (slongsh, wshift, reg2);
5115
 
5116
    ins2 (shifter, 8, sz, reg2, reg0);
5117
    invalidate_dest (reg0);
5118
    invalidate_dest (reg2);
5119
 
5120
    if (!to_reg2 && (regsinuse & 0x4) && !wshift_reg2)
5121
     {
5122
       ins0(popecx);
5123
#ifdef NEWDWARF
5124
      if (diagnose && dwarf2 && no_frame)
5125
	dw2_track_pop();
5126
#endif
5127
       extra_stack -= 32;
5128
     }
5129
 
5130
    /* reg2 might be used in the address of to */
5131
    move (sha, reg0, to);
5132
  };
5133
  return;
5134
 
5135
}
5136
 
5137
/* shift from wshift places to to. */
5138
static void rotshiftr
5139
    PROTO_N ( (shft, sha, wshift, from, to) )
5140
    PROTO_T ( int shft X shape sha X where wshift X where from X where to )
5141
{
5142
  exp p = wshift.where_exp;
5143
  int  places = no (p) + wshift.where_off;
5144
  char *shifter;
5145
  int  sz;
5146
  int sig = is_signed (sha);
5147
  exp holdto = son(to.where_exp);
5148
  sz = shape_size(sha);
5149
 
5150
  cond1_set = 0;
5151
  cond2_set = 0;
5152
 
5153
  if (sz == 64) {
5154
    int riu = regsinuse;
5155
    move (sha, from, reg0);
5156
    if (name(wshift.where_exp) == val_tag)
5157
      rotshift64 (shft+1, sig, wshift);
5158
    else {	/* need count in reg2 */
5159
      if (regsinuse & 0x4) {
5160
        ins0(pushecx);
5161
#ifdef NEWDWARF
5162
	if (diagnose && dwarf2 && no_frame)
5163
	  dw2_track_push();
5164
#endif
5165
        extra_stack += 32;
5166
        check_stack_max;
5167
      };
5168
      reg0_in_use = 1;
5169
      regsinuse |= 0x2;
5170
      move (slongsh, wshift, reg2);
5171
      rotshift64 (shft+1, sig, wshift);
5172
      invalidate_dest (reg2);
5173
      if (regsinuse & 0x4) {
5174
         ins0(popecx);
5175
#ifdef NEWDWARF
5176
	if (diagnose && dwarf2 && no_frame)
5177
	  dw2_track_pop();
5178
#endif
5179
         extra_stack -= 32;
5180
      }
5181
    };
5182
    invalidate_dest (reg0);
5183
    invalidate_dest (reg1);
5184
    move (sha, reg0, to);
5185
    regsinuse = riu;
5186
    return;
5187
  }
5188
 
5189
  if (shft == 0) {
5190
    switch (sz) {
5191
      case 8:
5192
        shifter = (sig) ? sarb : shrb;
5193
        break;
5194
      case 16:
5195
        shifter = (sig) ? sarw : shrw;
5196
        break;
5197
      default:
5198
        shifter = (sig) ? sarl : shrl;
5199
    }
5200
  }
5201
  else {
5202
    switch (sz) {
5203
      case 8:
5204
        shifter = (shft == 1) ? rorb : rolb;
5205
        break;
5206
      case 16:
5207
        shifter = (shft == 1) ? rorw : rolw;
5208
        break;
5209
      default:
5210
        shifter = (shft == 1) ? rorl : roll;
5211
    }
5212
  };
5213
 
5214
  if (name (p) == val_tag) {
5215
    if (places >= 32) {
5216
      if (sig)
5217
	no (p) = 31;
5218
      else {
5219
	move (sha, zero, to);
5220
	return;
5221
      };
5222
    };
5223
    if (eq_where (from, to)) {
5224
      contop (to.where_exp, 0, to);
5225
      ins2 (shifter, 8, sz, wshift, to);
5226
      invalidate_dest (to);
5227
      end_contop ();
5228
      son(to.where_exp) = holdto;
5229
      return;
5230
    };
5231
    if (!inmem (to)) {
5232
      move (sha, from, to);
5233
      contop (to.where_exp, 0, to);
5234
      ins2 (shifter, 8, sz, wshift, to);
5235
      invalidate_dest (to);
5236
      end_contop ();
5237
      son(to.where_exp) = holdto;
5238
      return;
5239
    };
5240
    move (sha, from, reg0);
5241
    ins2 (shifter, 8, sz, wshift, reg0);
5242
    invalidate_dest (reg0);
5243
    move (sha, reg0, to);
5244
    return;
5245
  };
5246
  {
5247
    int   to_reg2,
5248
          wshift_reg2;
5249
    int selfed = 0;
5250
    to_reg2 = eq_where (to, reg2);
5251
    wshift_reg2 = eq_where (wshift, reg2);
5252
 
5253
    if (!to_reg2 && (regsinuse & 0x4) && !wshift_reg2) {
5254
      ins0(pushecx);
5255
#ifdef NEWDWARF
5256
      if (diagnose && dwarf2 && no_frame)
5257
	dw2_track_push();
5258
#endif
5259
      extra_stack += 32;
5260
      check_stack_max;
5261
    };
5262
 
5263
    /* scan2 has guaranteed that wshift is not in reg0 */
5264
 
5265
    if (eq_where(from, to) &&
5266
	 !eq_where(from, reg2) &&
5267
	 ((regsinuse & 0x4) == 0 || wshift_reg2) &&
5268
	 sz == 32) {
5269
      move (slongsh, wshift, reg2);
5270
      ins2 (shifter, 8, sz, reg2, to);
5271
      invalidate_dest (to);
5272
      invalidate_dest (reg2);
5273
      selfed = 1;
5274
    }
5275
    else {
5276
      change_var (slongsh, from, reg0);
5277
      reg0_in_use = 1;
5278
      move (slongsh, wshift, reg2);
5279
 
5280
      ins2 (shifter, 8, sz, reg2, reg0);
5281
      invalidate_dest (reg0);
5282
      invalidate_dest (reg2);
5283
    };
5284
 
5285
    if (!to_reg2 && (regsinuse & 0x4) && !wshift_reg2)
5286
     {
5287
       ins0(popecx);
5288
#ifdef NEWDWARF
5289
      if (diagnose && dwarf2 && no_frame)
5290
	dw2_track_pop();
5291
#endif
5292
       extra_stack -= 32;
5293
     }
5294
 
5295
    /* reg2 might be used in the address of to */
5296
    if (!selfed)
5297
      move (sha, reg0, to);
5298
  };
5299
  return;
5300
 
5301
}
5302
 
5303
/* shift from wshift places to to. */
5304
void shiftr
5305
    PROTO_N ( (sha, wshift, from, to) )
5306
    PROTO_T ( shape sha X where wshift X where from X where to )
5307
{
5308
  rotshiftr (0, sha, wshift, from, to);
5309
  return;
5310
}
5311
 
5312
/* shift from wshift places to to. */
5313
void rotater
5314
    PROTO_N ( (sha, wshift, from, to) )
5315
    PROTO_T ( shape sha X where wshift X where from X where to )
5316
{
5317
  rotshiftr (1, sha, wshift, from, to);
5318
  return;
5319
}
5320
 
5321
/* shift from wshift places to to. */
5322
void rotatel
5323
    PROTO_N ( (sha, wshift, from, to) )
5324
    PROTO_T ( shape sha X where wshift X where from X where to )
5325
{
5326
  rotshiftr (2, sha, wshift, from, to);
5327
  return;
5328
}
5329
 
5330
/* divide top by bottom and put in dest */
5331
static void divit
5332
    PROTO_N ( (sha, bottom, top, dest, whichdiv, use_shift) )
5333
    PROTO_T ( shape sha X where bottom X where top X where dest X int whichdiv X int use_shift )
5334
{
5335
  int sz;
5336
  int v;
5337
  where d;
5338
  int sg = is_signed (sha);
5339
  int r1flag = 0, r2flag = 0;
5340
  int reslab = 0, test_zero = 0, test_ov = 0;
5341
  shape shb = sh(bottom.where_exp);
5342
  d = bottom;
5343
 
5344
  if (name(sh(top.where_exp)) == offsethd)
5345
    sg = 1;  /* fudge because some systems have ptrdiff_t as unsigned
5346
                though ANSI C says it must be signed
5347
             */
5348
 
5349
  if (overflow_e != nilexp && !istrap(overflow_e)) {
5350
    if (name (bottom.where_exp) != val_tag || no(bottom.where_exp) == 0)
5351
      test_zero = 1;
5352
    if (sg && (name (bottom.where_exp) != val_tag || no(bottom.where_exp) == -1))
5353
      test_ov = 1;
5354
  }
5355
 
5356
  sz = shape_size(sha);
5357
 
5358
  cond1_set = 0;
5359
  cond2_set = 0;
5360
 
5361
  if ((use_shift || !sg) &&
5362
      name (bottom.where_exp) == val_tag && !isbigval(bottom.where_exp) &&
5363
      (v = no (bottom.where_exp), v > 0 && (v & (v - 1)) == 0) ) {
5364
    int  c = 0;
5365
    int  m = 1;
5366
    where rw;
5367
    if (name(shb) == offsethd &&
5368
          al2(shb) != 1)
5369
      v = v / 8;
5370
    while (m != v) {
5371
      ++c;
5372
      m = m << 1;
5373
    };
5374
 
5375
    if (c == 0)  {
5376
      move (sha, top, dest);
5377
      return;
5378
    };
5379
 
5380
    if (inmem (dest))
5381
      rw = reg0;
5382
    else
5383
      rw = dest;
5384
    move (sha, top, rw);
5385
    switch (sz) {
5386
      case 8:
5387
	ins2 ((sg) ? sarb : shrb, 8, 8, mw (zeroe, c), rw);
5388
	break;
5389
      case 16:
5390
	ins2 ((sg) ? sarw : shrw, 8, 16, mw (zeroe, c), rw);
5391
	break;
5392
      case 64:
5393
	rotshift64 (1, sg, mw (zeroe, c));	/* shift within reg0/reg1 */
5394
	break;
5395
      default: /* case 32 */
5396
	ins2 ((sg) ? sarl : shrl, 8, 32, mw (zeroe, c), rw);
5397
    }
5398
    invalidate_dest (rw);
5399
    if (inmem (dest))
5400
      move (sha, rw, dest);
5401
    return;
5402
  };
5403
 
5404
  if (sz == 64 && shape_size (shb) == 64 && (
5405
	name (bottom.where_exp) != val_tag || isbigval(bottom.where_exp) ||
5406
 	no (bottom.where_exp) < 0 || sg)) {
5407
    needs_lib64();
5408
    if (eq_where (top, reg0)) {
5409
      ins2 (subl, 32, 32, mw(zeroe, 16), sp);
5410
      extra_stack += 128;
5411
      move (sha, top, mw(ind_sp.where_exp, -128));
5412
      move (sha, bottom, mw(ind_sp.where_exp, -64));
5413
      invalidate_dest (ind_sp);
5414
      extra_stack -= 128;
5415
    }
5416
    else {
5417
      move (sha, bottom, pushdest);
5418
      extra_stack += 64;
5419
      move (sha, top, pushdest);
5420
      extra_stack -= 64;
5421
    }
5422
    callins (0, lib64_div [sg + 2*(whichdiv==1)], stack_dec);
5423
    ins2 (addl, 32, 32, mw(zeroe, 16), sp);
5424
    if (overflow_e != nilexp && !optop(overflow_e)) {
5425
      ins2 (movl, 32, 32, mw(lib64_error, 0), reg2);
5426
      if (PIC_code)
5427
        ins2 (movl, 32, 32, ind_reg2, reg2);
5428
      ins2 (testl, 32, 32, reg2, reg2);
5429
      test_exception (f_greater_than_or_equal, slongsh);
5430
    }
5431
    move (sha, reg0, dest);
5432
    return;
5433
  };
5434
 
5435
  if (sz == 8) {
5436
    if (sg)
5437
      change_var (swordsh, top, reg0);
5438
    else
5439
      change_var (uwordsh, top, reg0);
5440
  }
5441
  else
5442
    move (sha, top, reg0);
5443
 
5444
 
5445
  if (flinmem (bottom) || (eq_where (bottom, reg1) && sz > 8) || (whichdiv==1 && sg) ) {
5446
    d = reg2;
5447
    if (regsinuse & 0x4 && !eq_where (dest, reg2)) {
5448
      /* preserve ecx if necessary */
5449
      r2flag = 1;
5450
      ins0(pushecx);
5451
#ifdef NEWDWARF
5452
      if (diagnose && dwarf2 && no_frame)
5453
	dw2_track_push();
5454
#endif
5455
      stack_dec -= 32;
5456
      check_stack_max;
5457
    };
5458
    reg0_in_use = 1;
5459
    if (sz == 64) {
5460
      int riu = regsinuse;
5461
      regsinuse |= 0x2;
5462
      move (shb, bottom, reg2);
5463
      regsinuse = riu;
5464
    }
5465
    else
5466
      move (shb, bottom, reg2);
5467
  };
5468
 
5469
  if (test_zero) {		/* avoid divide by zero trap */
5470
    IGNORE cmp (shb, d, zero, f_not_equal, nilexp);
5471
    if (isov(overflow_e))
5472
      test_exception (f_not_equal, shb);
5473
    else {
5474
      reslab = next_lab();
5475
      simple_branch (je, reslab);
5476
    }
5477
  }
5478
 
5479
  if (test_ov) {		/* avoid most_neg divide by -1 trap */
5480
    int divlab = next_lab ();
5481
    if (reslab == 0)
5482
      reslab = next_lab();
5483
    IGNORE cmp (shb, d, mw(zeroe,-1), f_equal, nilexp);
5484
    simple_branch (jne, divlab);
5485
    negate (sha, reg0, reg0);
5486
    simple_branch (jmp, reslab);
5487
    simple_set_label(divlab);
5488
  }
5489
 
5490
  if (!eq_where (dest, reg1) && regsinuse & 0x2 && sz > 8) {
5491
    r1flag = 1;
5492
    ins0(pushedx);
5493
#ifdef NEWDWARF
5494
    if (diagnose && dwarf2 && no_frame)
5495
      dw2_track_push();
5496
#endif
5497
    stack_dec -= 32;
5498
    check_stack_max;
5499
    invalidate_dest (reg1);
5500
  };
5501
 
5502
  if (sg) {			/* signed */
5503
    switch (sz) {
5504
      case 8:
5505
	ins1 (idivb, 8, d);
5506
	break;
5507
      case 16:
5508
	move(swordsh, reg0, reg1);
5509
	ins2(sarw, 16, 16, mw(zeroe, 15), reg1);
5510
	ins1 (idivw, 16, d);
5511
	break;
5512
      case 64:
5513
	failer(BADOP);
5514
      default:
5515
	move(slongsh, reg0, reg1);
5516
	ins2(sarl, 32, 32, mw(zeroe, 31), reg1);
5517
	ins1 (idivl, 32, d);
5518
    }
5519
    if (whichdiv == 1) {
5520
      int end = next_lab();
5521
      switch (sz) {
5522
	case 8:
5523
	  ins0("testb %ah,%ah");
5524
	  simple_branch(je, end);
5525
	  ins0("xorb %ah,%cl");
5526
	  simple_branch(jge, end);
5527
	  ins1(decb, 8, reg0);
5528
	  break;
5529
	case 16:
5530
	  ins2(testw, 16, 16, reg1, reg1);
5531
	  simple_branch(je, end);
5532
	  ins2(xorw, 16, 16, reg1, reg2);
5533
	  simple_branch(jge, end);
5534
	  ins1(decw, 16, reg0);
5535
	  break;
5536
	default:
5537
	  ins2(testl, 32, 32, reg1, reg1);
5538
	  simple_branch(je, end);
5539
	  ins2(xorl, 32, 32, reg1, reg2);
5540
	  simple_branch(jge, end);
5541
	  ins1(decl, 32, reg0);
5542
      }
5543
      simplest_set_lab(end);
5544
    };
5545
  }
5546
  else {			/* unsigned */
5547
    switch (sz) {
5548
      case 8:
5549
	ins1 (divb, 8, d);
5550
	break;
5551
      case 16:
5552
	ins2 (xorw, 16, 16, reg1, reg1);
5553
	ins1 (divw, 16, d);
5554
	break;
5555
      case 64:
5556
	ins0 (pusheax);
5557
#ifdef NEWDWARF
5558
	if (diagnose && dwarf2 && no_frame)
5559
	  dw2_track_push();
5560
#endif
5561
	move(slongsh, reg1, reg0);
5562
	ins2 (xorl, 32, 32, reg1, reg1);
5563
	ins1 (divl, 32, d);
5564
	ins2 (xchg, 32, 32, ind_sp, reg0);
5565
	ins1 (divl, 32, d);
5566
	ins0 (popedx);
5567
#ifdef NEWDWARF
5568
	if (diagnose && dwarf2 && no_frame)
5569
	  dw2_track_pop();
5570
#endif
5571
	break;
5572
      default:
5573
	ins2 (xorl, 32, 32, reg1, reg1);
5574
	ins1 (divl, 32, d);
5575
    }
5576
  };
5577
  invalidate_dest (reg0);
5578
  invalidate_dest (reg1);
5579
  invalidate_dest (reg2);
5580
 
5581
  if (r1flag)
5582
   {
5583
     ins0(popedx);
5584
#ifdef NEWDWARF
5585
      if (diagnose && dwarf2 && no_frame)
5586
	dw2_track_pop();
5587
#endif
5588
     stack_dec += 32;
5589
   };
5590
 
5591
  if (reslab != 0)
5592
    simple_set_label (reslab);
5593
 
5594
  if (r2flag)
5595
   {
5596
     ins0(popecx);
5597
#ifdef NEWDWARF
5598
      if (diagnose && dwarf2 && no_frame)
5599
	dw2_track_pop();
5600
#endif
5601
     stack_dec += 32;
5602
   };
5603
 
5604
  move (sha, reg0, dest);
5605
  return;
5606
}
5607
 
5608
 
5609
void div2
5610
    PROTO_N ( (sha, bottom, top, dest) )
5611
    PROTO_T ( shape sha X where bottom X where top X where dest )
5612
{
5613
  divit (sha, bottom, top, dest, 2, 0);
5614
  return;
5615
}
5616
 
5617
void div1
5618
    PROTO_N ( (sha, bottom, top, dest) )
5619
    PROTO_T ( shape sha X where bottom X where top X where dest )
5620
{
5621
  divit (sha, bottom, top, dest, 1, 1);
5622
  return;
5623
}
5624
 
5625
void div0
5626
    PROTO_N ( (sha, bottom, top, dest) )
5627
    PROTO_T ( shape sha X where bottom X where top X where dest )
5628
{
5629
  divit (sha, bottom, top, dest, 0, 1);
5630
  return;
5631
}
5632
 
5633
/* remainder after dividing top by bottom to dest */
5634
static void remit
5635
    PROTO_N ( (sha, bottom, top, dest, whichrem, use_mask) )
5636
    PROTO_T ( shape sha X where bottom X where top X where dest X int whichrem X int use_mask )
5637
{
5638
  int  sz;
5639
  where d;
5640
  int sg = is_signed (sha);
5641
  int r1flag = 0, r2flag = 0;
5642
  int  v;
5643
  int reslab = 0, test_zero = 0, test_ov = 0;
5644
  shape shb = sh(bottom.where_exp);
5645
  d = bottom;
5646
  sz = shape_size(sha);
5647
 
5648
  if (overflow_e != nilexp && !istrap(overflow_e)) {
5649
    if (name (bottom.where_exp) != val_tag || no(bottom.where_exp) == 0)
5650
      test_zero = 1;
5651
    if (sg && (name (bottom.where_exp) != val_tag || no(bottom.where_exp) == -1))
5652
      test_ov = 1;
5653
  }
5654
 
5655
  cond1_set = 0;
5656
  cond2_set = 0;
5657
 
5658
  if ((use_mask || !sg) &&
5659
      name (bottom.where_exp) == val_tag && !isbigval(bottom.where_exp) &&
5660
      (v = no (bottom.where_exp), v > 0 && (v & (v - 1)) == 0)) {
5661
    /* use and if possible (Note this is compatible with ANSI C, but not
5662
       with Ada) */
5663
    int  c = 0;
5664
    int  m = 1;
5665
    while (m != v) {
5666
      ++c;
5667
      m = m << 1;
5668
    };
5669
    and (sha, top, mw (zeroe, lsmask[c]), dest);
5670
    return;
5671
  };
5672
 
5673
  if (sz == 64 && shape_size (shb) == 64 && (
5674
	name (bottom.where_exp) != val_tag || isbigval(bottom.where_exp) ||
5675
 	no (bottom.where_exp) < 0 || sg)) {
5676
    needs_lib64();
5677
    if (eq_where (top, reg0)) {
5678
      ins2 (subl, 32, 32, mw(zeroe, 16), sp);
5679
      extra_stack += 128;
5680
      move (sha, top, mw(ind_sp.where_exp, -128));
5681
      move (sha, bottom, mw(ind_sp.where_exp, -64));
5682
      extra_stack -= 128;
5683
    }
5684
    else {
5685
      move (sha, bottom, pushdest);
5686
      extra_stack += 64;
5687
      move (sha, top, pushdest);
5688
      extra_stack -= 64;
5689
    }
5690
    callins (0, lib64_rem [sg + 2*(whichrem==1)], stack_dec);
5691
    ins2 (addl, 32, 32, mw(zeroe, 16), sp);
5692
    if (overflow_e != nilexp && !optop(overflow_e)) {
5693
      ins2 (movl, 32, 32, mw(lib64_error, 0), reg2);
5694
      if (PIC_code)
5695
        ins2 (movl, 32, 32, ind_reg2, reg2);
5696
      ins2 (testl, 32, 32, reg2, reg2);
5697
      test_exception (f_greater_than_or_equal, slongsh);
5698
    }
5699
    move (sha, reg0, dest);
5700
    return;
5701
  };
5702
 
5703
  if (sz == 8) {
5704
    if (sg)
5705
      change_var (swordsh, top, reg0);
5706
    else
5707
      change_var (uwordsh, top, reg0);
5708
  }
5709
  else
5710
    move (sha, top, reg0);
5711
 
5712
 
5713
  if (flinmem (bottom) || (eq_where (bottom, reg1) && sz > 8) || (whichrem==1 && sg) ) {
5714
    d = reg2;
5715
    if (regsinuse & 0x4 && !eq_where (dest, reg2)) {
5716
      /* preserve ecx if necessary */
5717
      r2flag = 1;
5718
      ins0(pushecx);
5719
#ifdef NEWDWARF
5720
      if (diagnose && dwarf2 && no_frame)
5721
	dw2_track_push();
5722
#endif
5723
      stack_dec -= 32;
5724
      check_stack_max;
5725
    };
5726
    reg0_in_use = 1;
5727
    if (sz == 64) {
5728
      int riu = regsinuse;
5729
      regsinuse |= 0x2;
5730
      move (shb, bottom, reg2);
5731
      regsinuse = riu;
5732
    }
5733
    else
5734
      move (shb, bottom, reg2);
5735
  };
5736
 
5737
  if (test_zero) {		/* avoid divide by zero trap */
5738
    IGNORE cmp (shb, d, zero, f_not_equal, nilexp);
5739
    if (isov(overflow_e))
5740
      test_exception (f_not_equal, shb);
5741
    else {
5742
      reslab = next_lab();
5743
      simple_branch (je, reslab);
5744
    }
5745
  }
5746
 
5747
  if (test_ov) {		/* avoid most_neg divide by -1 trap */
5748
    int divlab = next_lab ();
5749
    if (reslab == 0)
5750
      reslab = next_lab();
5751
    IGNORE cmp (shb, d, mw(zeroe,-1), f_equal, nilexp);
5752
    simple_branch (jne, divlab);
5753
    move (sha, zero, reg0);
5754
    simple_branch (jmp, reslab);
5755
    simple_set_label(divlab);
5756
  }
5757
 
5758
  if (!eq_where (dest, reg1) && regsinuse & 0x2 && sz > 8) {
5759
    r1flag = 1;
5760
    ins0(pushedx);
5761
#ifdef NEWDWARF
5762
    if (diagnose && dwarf2 && no_frame)
5763
      dw2_track_push();
5764
#endif
5765
    stack_dec -= 32;
5766
    check_stack_max;
5767
    invalidate_dest (reg1);
5768
  };
5769
 
5770
  if (sg) {			/* signed */
5771
    switch (sz) {
5772
      case 8:
5773
	ins1 (idivb, 8, d);
5774
	break;
5775
      case 16:
5776
	move(swordsh, reg0, reg1);
5777
	ins2(sarw, 16, 16, mw(zeroe, 15), reg1);
5778
	ins1 (idivw, 16, d);
5779
	break;
5780
      case 64:
5781
	failer(BADOP);
5782
      default:
5783
	move(slongsh, reg0, reg1);
5784
	ins2(sarl, 32, 32, mw(zeroe, 31), reg1);
5785
	ins1 (idivl, 32, d);
5786
    }
5787
    if (whichrem==1) {
5788
      int end = next_lab();
5789
      switch (sz) {
5790
	case 8:
5791
	  ins0("testb %ah,%ah");
5792
	  simple_branch(je, end);
5793
	  move(scharsh, reg2, reg0);
5794
	  ins0("xorb %ah,%cl");
5795
	  simple_branch(jge, end);
5796
	  ins0("addb %al,%ah");
5797
	  break;
5798
	case 16:
5799
	  ins2(testw, 16, 16, reg1, reg1);
5800
	  simple_branch(je, end);
5801
	  move(swordsh, reg2, reg0);
5802
	  ins2(xorw, 16, 16, reg1, reg2);
5803
	  simple_branch(jge, end);
5804
	  ins2(addw, 16, 16, reg0, reg1);
5805
	  break;
5806
	default:
5807
	  ins2(testl, 32, 32, reg1, reg1);
5808
	  simple_branch(je, end);
5809
	  move(slongsh, reg2, reg0);
5810
	  ins2(xorl, 32, 32, reg1, reg2);
5811
	  simple_branch(jge, end);
5812
	  ins2(addl, 32, 32, reg0, reg1);
5813
      }
5814
      simple_set_label(end);
5815
     };
5816
  }
5817
  else {			/* unsigned */
5818
    switch (sz) {
5819
      case 8:
5820
	ins1 (divb, 8, d);
5821
	break;
5822
      case 16:
5823
	ins2 (xorw, 16, 16, reg1, reg1);
5824
	ins1 (divw, 16, d);
5825
	break;
5826
      case 64:
5827
	ins0 (pusheax);
5828
#ifdef NEWDWARF
5829
	if (diagnose && dwarf2 && no_frame)
5830
	  dw2_track_push();
5831
#endif
5832
	move(slongsh, reg1, reg0);
5833
	ins2 (xorl, 32, 32, reg1, reg1);
5834
	ins1 (divl, 32, d);
5835
	ins0 (popeax);
5836
#ifdef NEWDWARF
5837
        if (diagnose && dwarf2 && no_frame)
5838
	  dw2_track_pop();
5839
#endif
5840
	ins1 (divl, 32, d);
5841
	break;
5842
      default:
5843
	ins2 (xorl, 32, 32, reg1, reg1);
5844
	ins1 (divl, 32, d);
5845
    }
5846
  };
5847
  if (sz == 8)
5848
    ins0 ("movb %ah,%al");
5849
  else
5850
  if (sz == 64) {
5851
    move(slongsh, reg1, reg0);
5852
    ins2 (xorl, 32, 32, reg1, reg1);
5853
  }
5854
  else
5855
    move(sha, reg1, reg0);
5856
  invalidate_dest (reg0);
5857
  invalidate_dest (reg1);
5858
  invalidate_dest (reg2);
5859
 
5860
 
5861
  if (r1flag)
5862
   {
5863
     ins0(popedx);
5864
#ifdef NEWDWARF
5865
      if (diagnose && dwarf2 && no_frame)
5866
	dw2_track_pop();
5867
#endif
5868
     stack_dec += 32;
5869
   };
5870
 
5871
  if (reslab != 0)
5872
    simple_set_label (reslab);
5873
 
5874
  if (r2flag)
5875
   {
5876
     ins0(popecx);
5877
#ifdef NEWDWARF
5878
      if (diagnose && dwarf2 && no_frame)
5879
	dw2_track_pop();
5880
#endif
5881
     stack_dec += 32;
5882
   };
5883
 
5884
  move (sha, reg0, dest);
5885
 
5886
  return;
5887
}
5888
 
5889
/* remainder after dividing top by bottom to dest */
5890
void rem2
5891
    PROTO_N ( (sha, bottom, top, dest) )
5892
    PROTO_T ( shape sha X where bottom X where top X where dest )
5893
{
5894
  remit(sha, bottom, top, dest, 2, 0);
5895
  return;
5896
}
5897
 
5898
/* remainder after dividing top by bottom to dest */
5899
void rem0
5900
    PROTO_N ( (sha, bottom, top, dest) )
5901
    PROTO_T ( shape sha X where bottom X where top X where dest )
5902
{
5903
  remit(sha, bottom, top, dest, 0, 1);
5904
  return;
5905
}
5906
 
5907
/* remainder after dividing top by bottom to dest */
5908
void mod
5909
    PROTO_N ( (sha, bottom, top, dest) )
5910
    PROTO_T ( shape sha X where bottom X where top X where dest )
5911
{
5912
  remit(sha, bottom, top, dest, 1, 1);
5913
  return;
5914
}
5915
 
5916
 
5917
/* move address of from to to */
5918
void mova
5919
    PROTO_N ( (from, to) )
5920
    PROTO_T ( where from X where to )
5921
{
5922
  exp fe = from.where_exp;
5923
  exp holdfe = son(fe);
5924
 
5925
  cond1_set = 0;
5926
  cond2_set = 0;
5927
 
5928
  if (name (fe) == reff_tag &&
5929
      name (son (fe)) != ident_tag) {/* add on offset from reff */
5930
    mova (mw (son (fe), from.where_off + no (fe)), to);
5931
    return;
5932
  };
5933
 
5934
  if (name (to.where_exp) == apply_tag) {	/* pushing */
5935
    if (!PIC_code && name (fe) == cont_tag &&
5936
         name (son (fe)) != ident_tag &&
5937
	(name (son (fe)) != name_tag || !isvar (son (son (fe)))) &&
5938
	((extra_stack == 0 && from.where_off == 0) ||
5939
	  !eq_where (mw (son (fe), 0), sp))) {
5940
      contop (fe, 0, to);
5941
      ins1lit (pushl,  32, mw (son (fe), from.where_off));
5942
#ifdef NEWDWARF
5943
      if (diagnose && dwarf2 && no_frame)
5944
	dw2_track_push();
5945
#endif
5946
      end_contop ();
5947
      son(fe) = holdfe;
5948
      return;
5949
    };
5950
    if (!PIC_code &&name (fe) == name_tag &&
5951
        isglob (son (fe)) && isvar (son (fe))) {
5952
      contop (fe, 0, to);
5953
      ins1lit (pushl,  32, from);
5954
#ifdef NEWDWARF
5955
      if (diagnose && dwarf2 && no_frame)
5956
	dw2_track_push();
5957
#endif
5958
      end_contop ();
5959
      son(fe) = holdfe;
5960
      return;
5961
    };
5962
    mova (from, reg0);
5963
    ins1 (pushl,  32, reg0);
5964
#ifdef NEWDWARF
5965
    if (diagnose && dwarf2 && no_frame)
5966
      dw2_track_push();
5967
#endif
5968
    return;
5969
  };
5970
 
5971
 
5972
  if (inmem (to)) {
5973
    mova (from, reg0);
5974
    move (slongsh, reg0, to);
5975
    return;
5976
  };
5977
 
5978
  if (!PIC_code && name (fe) == name_tag && isvar (son (fe)) &&
5979
      isglob (son (fe))) {
5980
    move (slongsh, from, to);
5981
    return;
5982
  };
5983
 
5984
  contop (from.where_exp, 0, to);
5985
 
5986
  if (name (fe) == name_tag && !isvar(son(fe)) && ptno(son(fe)) == reg_pl)
5987
    add(slongsh, mw(fe, 0), mw(zeroe, from.where_off/8), to);
5988
  else
5989
    ins2 (leal,  32,  32, from, to);
5990
 
5991
  invalidate_dest (to);
5992
  end_contop ();
5993
  son(fe) = holdfe;
5994
  return;
5995
}
5996
 
5997
int   adjust_pos
5998
    PROTO_N ( (e, nbits) )
5999
    PROTO_T ( exp e X int nbits )
6000
{
6001
  int   pos;
6002
  UNUSED(nbits);
6003
  pos = no (e) % 8;
6004
  no (e) -= pos;
6005
  return (pos);
6006
}
6007
 
6008
/* find bit position of bitfield defined
6009
   by e, and alter e to address the start
6010
   of the byte */
6011
int   bit_pos_cont
6012
    PROTO_N ( (e, nbits) )
6013
    PROTO_T ( exp e X int nbits )
6014
{
6015
  if (name (e) == reff_tag ||
6016
      name (e) == name_tag)
6017
    return (adjust_pos (e, nbits));
6018
 
6019
  if (name (e) == ident_tag) {
6020
    if (name (bro (son (e))) == reff_tag)
6021
      return (adjust_pos (bro (son (e)), nbits));
6022
 
6023
    if (name (bro (son (e))) == ident_tag)
6024
      return bit_pos_cont (bro (son (e)), nbits);
6025
 
6026
    if (name (bro (son (e))) == name_tag &&
6027
	son (bro (son (e))) == e &&
6028
	name (son (e)) == name_tag)
6029
      return (bit_pos_cont (son (son (e)), nbits));
6030
 
6031
    if (name (son (e)) == name_tag)
6032
      return (adjust_pos (son (e), nbits));
6033
 
6034
    return (0);
6035
  };
6036
 
6037
  failer (BAD_BIT_OPND);
6038
  return (0);
6039
 
6040
}
6041
 
6042
/* find bit position of bitfield defined
6043
   by e, and alter e to address the start
6044
   of the byte. Looks at top level and
6045
   calls bit_pos_cont to it is a cont or
6046
   ass (which needs recursive calling) */
6047
int   bit_pos
6048
    PROTO_N ( (e, nbits) )
6049
    PROTO_T ( exp e X int nbits )
6050
{
6051
  if (name (e) == name_tag)
6052
    return (adjust_pos (e, nbits));
6053
 
6054
  if (name (e) == cont_tag || name (e) == ass_tag)
6055
    return (bit_pos_cont (son (e), nbits));
6056
 
6057
  if (name (e) == ident_tag)
6058
    return (0);
6059
 
6060
  failer (BAD_BIT_OPND);
6061
  return (0);
6062
}
6063
 
6064
void mem_to_bits
6065
    PROTO_N ( (e, sha, dest, stack) )
6066
    PROTO_T ( exp e X shape sha X where dest X ash stack )
6067
{
6068
  int pos, lsn;
6069
  int nbits = shape_size(sha);
6070
  shape dsh;
6071
  char *rs;
6072
  shape move_sh;
6073
 
6074
  cond1_set = 0;
6075
  cond2_set = 0;
6076
 
6077
 
6078
  dsh = (is_signed(sha)) ? slongsh : ulongsh;
6079
 
6080
  pos = bit_pos(e, nbits);
6081
 
6082
  lsn = 32 - nbits - pos;
6083
  rs = (is_signed(sha)) ? sarl : shrl;
6084
	/* right shift with sign extension or not
6085
				*/
6086
 
6087
  if (pos == 0 && (nbits == 8 || nbits == 16)) {
6088
    /* can use byte or word instructions. */
6089
    shape osh;
6090
    exp temp;
6091
 
6092
    if (nbits == 8) {
6093
      if (is_signed(sha))
6094
	osh = scharsh;
6095
      else
6096
	osh = ucharsh;
6097
    }
6098
    else {
6099
      if (is_signed(sha))
6100
	osh = swordsh;
6101
      else
6102
	osh = uwordsh;
6103
    };
6104
 
6105
    sh(e) = osh;
6106
    temp = getexp(dsh, nilexp, 0, e, nilexp, 0, 0, chvar_tag);
6107
    coder(dest, stack, temp);
6108
    retcell(temp);
6109
    return;
6110
  };
6111
 
6112
  if ((pos + nbits) <= 8)
6113
    move_sh = scharsh;
6114
  else
6115
    move_sh = slongsh;
6116
 
6117
  if (!inmem (dest)) {		/* dest is register */
6118
    move (move_sh, mw (e, 0), dest);/* move e to dest */
6119
    if (lsn != 0)
6120
      ins2 (shll,  32,  32, mw (zeroe, lsn), dest);
6121
    invalidate_dest (dest);
6122
    /* shift it left to remove unwanted bits */
6123
    if (nbits != 32)
6124
      ins2 (rs,  32,  32, mw (zeroe, 32 - nbits), dest);
6125
    /* shift it right to remove unwanted bits and propagate sign if
6126
       necessary */
6127
    invalidate_dest (dest);
6128
    return;
6129
  };
6130
 
6131
  move (move_sh, mw (e, 0), reg0);/* move e to reg0 */
6132
  if (lsn != 0)
6133
    ins2 (shll,  32,  32, mw (zeroe, lsn), reg0);
6134
  invalidate_dest (reg0);
6135
  /* shift it left to remove unwanted bits */
6136
  if (nbits != 32)
6137
    ins2 (rs,  32,  32, mw (zeroe, 32 - nbits), reg0);
6138
  /* shift it right to remove unwanted bits and propagate sign if
6139
     necessary */
6140
  move (dsh, reg0, dest);/* move to dest */
6141
  return;
6142
}
6143
 
6144
void bits_to_mem
6145
    PROTO_N ( (e, d, stack) )
6146
    PROTO_T ( exp e X exp d X ash stack )
6147
{
6148
  int pos;
6149
  int nbits = shape_size(sh(e));
6150
  int mask, lsn, k;
6151
  where dest;
6152
  shape move_sh;
6153
  dest = mw(d, 0);
6154
 
6155
  cond1_set = 0;
6156
  cond2_set = 0;
6157
 
6158
  pos = bit_pos (d, nbits);
6159
 
6160
  lsn = 32 - nbits - pos;
6161
  mask = msmask[lsn] + lsmask[pos];
6162
 
6163
  k = lsmask[nbits] << pos;
6164
 
6165
  if ((pos+nbits) <= 8)
6166
   {
6167
    move_sh = scharsh;
6168
    mask &= 0xff;
6169
    k &= 0xff;
6170
   }
6171
  else
6172
    move_sh = slongsh;
6173
 
6174
  if (name(e) == int_to_bitf_tag && name (son(e)) == val_tag) {
6175
    if (no (son(e)) == lsmask[nbits]) {
6176
      /* if we are assigning all ones, just or them in */
6177
      or (move_sh, mw (zeroe, k), dest, dest);
6178
      return;
6179
    };
6180
    if (no (son(e)) == 0) {
6181
      /* if we are assigning all ones, just or them in */
6182
      k = ~k;
6183
      if ((pos+nbits) <= 8)
6184
        k &= 0xff;
6185
      and (move_sh, mw (zeroe, k), dest, dest);
6186
      return;
6187
    };
6188
  };
6189
 
6190
  if (pos == 0 && (nbits == 8 || nbits == 16)) {
6191
    shape osh;
6192
 
6193
    if (nbits == 8)
6194
      osh = ucharsh;
6195
    else
6196
      osh = uwordsh;
6197
    if (name(e) == int_to_bitf_tag)
6198
     {
6199
	if (name(son(e)) == val_tag) {
6200
	  move(osh, mw(son(e), 0), dest);
6201
	}
6202
	else {
6203
         coder(reg0, stack, son(e));
6204
         move (osh, reg0, dest);
6205
	};
6206
     }
6207
    else
6208
       move(osh, mw(e, 0), dest);
6209
    return;
6210
  };
6211
 
6212
  /* mask the bits we are putting in out of the dest */
6213
  if (name (e) != val_tag) {	/* this needs improvement */
6214
    if (name(e) == int_to_bitf_tag)
6215
       coder(reg0, stack, son(e));
6216
    else
6217
       move(sh(e), mw(e, 0), reg0);
6218
    and (slongsh, mw (zeroe, lsmask[nbits]), reg0, reg0);
6219
    /* mask it to the right size */
6220
    if (pos != 0)
6221
      ins2 (shll,  32,  32, mw (zeroe, pos), reg0);
6222
    invalidate_dest (reg0);
6223
    /* shift it into position */
6224
    keep_short = 0;	/* stop use of reg0 by and */
6225
    and (move_sh, mw (zeroe, mask), dest, dest);
6226
    add (move_sh, reg0, dest, dest);/* and add it into the dest */
6227
    return;
6228
  }
6229
  else {
6230
    k = (no (e) & lsmask[nbits]) << pos;
6231
    /* constant bits we are assigning */
6232
    if (k == 0)
6233
      return;			/* if we are assigning zero we don't need
6234
				   anything more */
6235
    move (slongsh, mw (zeroe, k), reg0);
6236
    /* we don't need this move to reg0 since add looks after this better
6237
    */
6238
    keep_short = 0;
6239
    and (move_sh, mw (zeroe, mask), dest, dest);
6240
    add (move_sh, reg0, dest, dest);/* add into dest */
6241
    return;
6242
  };
6243
}
6244
 
6245
 
6246
 
6247
 
6248
/* apply floating point operation op
6249
   between fstack0 and memory. reverse
6250
   arguments of operation if rev. */
6251
void fopm
6252
    PROTO_N ( (sha, op, rev, wh) )
6253
    PROTO_T ( shape sha X unsigned char op X int rev X where wh )
6254
{
6255
  exp hold = son(wh.where_exp);
6256
  contop (wh.where_exp, 0, reg0);
6257
  if (name (sha) == shrealhd) {	/* floats */
6258
    switch (op) {
6259
      case fplus_tag:
6260
	ins1 (fadds,  32, wh);
6261
	end_contop ();
6262
	son(wh.where_exp) = hold;
6263
	return;
6264
      case fminus_tag:
6265
	if (rev)
6266
	  ins1 (fsubrs,  32, wh);
6267
	else
6268
	  ins1 (fsubs,  32, wh);
6269
	end_contop ();
6270
	son(wh.where_exp) = hold;
6271
	return;
6272
      case fmult_tag:
6273
	ins1 (fmuls,  32, wh);
6274
	end_contop ();
6275
	son(wh.where_exp) = hold;
6276
	return;
6277
      case fdiv_tag:
6278
	if (rev)
6279
	  ins1 (fdivrs,  32, wh);
6280
	else
6281
	  ins1 (fdivs,  32, wh);
6282
	end_contop ();
6283
	son(wh.where_exp) = hold;
6284
	return;
6285
      default:
6286
	failer (BAD_FLOP);
6287
	end_contop ();
6288
	son(wh.where_exp) = hold;
6289
	return;
6290
    };
6291
  };
6292
 
6293
  switch (op) {			/* doubles */
6294
    case fplus_tag:
6295
      ins1 (faddl,  64, wh);
6296
      end_contop ();
6297
      son(wh.where_exp) = hold;
6298
      return;
6299
    case fminus_tag:
6300
      if (rev)
6301
	ins1 (fsubrl,  64, wh);
6302
      else
6303
	ins1 (fsubl,  64, wh);
6304
      end_contop ();
6305
      son(wh.where_exp) = hold;
6306
      return;
6307
    case fmult_tag:
6308
      ins1 (fmull,  64, wh);
6309
      end_contop ();
6310
      son(wh.where_exp) = hold;
6311
      return;
6312
    case fdiv_tag:
6313
      if (rev)
6314
	ins1 (fdivrl,  64, wh);
6315
      else
6316
	ins1 (fdivl,  64, wh);
6317
      end_contop ();
6318
      son(wh.where_exp) = hold;
6319
      return;
6320
    default:
6321
      failer (BAD_FLOP);
6322
      end_contop ();
6323
      son(wh.where_exp) = hold;
6324
      return;
6325
  };
6326
}
6327
 
6328
 
6329
 
6330
/* apply floating point operation op
6331
   between fstack0 and fstackn. Reverse
6332
   arguments of operation if rev. */
6333
void fopr
6334
    PROTO_N ( (op, rev, wh, d, and_pop) )
6335
    PROTO_T ( unsigned char op X int rev X where wh X where d X int and_pop )
6336
{
6337
  switch (op) {
6338
    case fplus_tag:
6339
      if (and_pop) {
6340
	ins2 (faddp, 0, 0, wh, d);
6341
	pop_fl;
6342
      }
6343
      else
6344
	ins2 (fadd, 0, 0, wh, d);
6345
      break;
6346
    case fminus_tag:
6347
      if (rev) {
6348
	if (and_pop) {
6349
	  ins2 (fsubrp, 0, 0, wh, d);
6350
	  pop_fl;
6351
	}
6352
	else
6353
	  ins2 (fsubr, 0, 0, wh, d);
6354
      }
6355
      else {
6356
	if (and_pop) {
6357
	  ins2 (fsubp, 0, 0, wh, d);
6358
	  pop_fl;
6359
	}
6360
	else
6361
	  ins2 (fsub, 0, 0, wh, d);
6362
      };
6363
      break;
6364
    case fmult_tag:
6365
      if (and_pop) {
6366
	ins2 (fmulp, 0, 0, wh, d);
6367
	pop_fl;
6368
      }
6369
      else
6370
	ins2 (fmul, 0, 0, wh, d);
6371
      break;
6372
    case fdiv_tag:
6373
      if (rev) {
6374
	if (and_pop) {
6375
	  ins2 (fdivrp, 0, 0, wh, d);/* (1,arg1-in-st0,arg2,1) -> arg2 */
6376
	  pop_fl;
6377
	}
6378
	else
6379
	  ins2 (fdivr, 0, 0, wh, d); /* (1,arg2,arg1-in-st0,0) -> st0 */
6380
      }
6381
      else {
6382
	if (and_pop) {
6383
	  ins2 (fdivp, 0, 0, wh, d); /* (0,arg2-in-st0,arg1,1) -> arg1 */
6384
	  pop_fl;
6385
	}
6386
	else
6387
	  ins2 (fdiv, 0, 0, wh, d);  /* (0,arg1,arg2-in-st0,0) -> st0 */
6388
      };
6389
      break;
6390
    default:
6391
      failer (BAD_FLOP);
6392
      break;
6393
  };
6394
 
6395
  return;
6396
}
6397
 
6398
 
6399
/* apply binary floating point operation
6400
   to arg1 and arg2 and put result into
6401
   dest */
6402
void fl_binop
6403
    PROTO_N ( (op, sha, arg1, arg2, dest, last_arg) )
6404
    PROTO_T ( unsigned char op X shape sha X where arg1 X where arg2 X where dest X exp last_arg )
6405
{
6406
  int   m1 = flinmem (arg1);
6407
  int   m2 = flinmem (arg2);
6408
  int   m3 = flinmem (dest);
6409
  int tst = (m1 << 2) + (m2 << 1) + m3;
6410
 
6411
  if (name(sha) == doublehd && tst > 1)
6412
   {
6413
     move(sha, arg1, flstack);
6414
     move(sha, arg2, flstack);
6415
     switch (op)
6416
      {
6417
        case fplus_tag:
6418
           ins0("faddp %st,%st(1)"); break;
6419
        case fminus_tag:
6420
	   ins0("fsubp %st,%st(1)"); break;
6421
        case fmult_tag:
6422
	   ins0("fmulp %st,%st(1)"); break;
6423
        case fdiv_tag:
6424
	   ins0("fdivp %st,%st(1)"); break;
6425
      };
6426
     pop_fl;
6427
     move(sha, flstack, dest);
6428
     return;
6429
   };
6430
 
6431
  switch (tst) {
6432
    case 6:
6433
    case 7:
6434
      move (sha, arg2, flstack);
6435
      fopm (sha, op, 0, arg1);
6436
 
6437
      move (sha, flstack, dest);
6438
      return;
6439
    case 4:
6440
      if (eq_where (arg2, dest)) {
6441
	int  fd = in_fl_reg (dest.where_exp);
6442
	if (fd && get_reg_no (fd) == fstack_pos) {
6443
	  fopm (sha, op, 0, arg1);
6444
 
6445
	  return;
6446
	};
6447
	move (sha, arg1, flstack);
6448
	fopr (op, 1, flstack, dest, 1); /* 1: fdivrp st,st(2) */
6449
 
6450
	return;
6451
      };
6452
      /* fall through to case 5 */
6453
    case 5:
6454
 
6455
      if (use_pop (last_arg, arg2.where_exp) == 2) {
6456
	fopm (sha, op, 0, arg1);
6457
 
6458
	move (sha, flstack, dest);
6459
	return;
6460
      };
6461
 
6462
      move (sha, arg1, flstack);
6463
      fopr (op, 1, arg2, flstack, 0); /* 2: fdivr st(2),st */
6464
 
6465
      move (sha, flstack, dest);
6466
      return;
6467
    case 2:
6468
      if (eq_where (arg1, dest)) {
6469
	int  fd = in_fl_reg (dest.where_exp);
6470
	if (fd && get_reg_no (fd) == fstack_pos) {
6471
	  fopm (sha, op, 1, arg2);
6472
 
6473
	  return;
6474
	};
6475
	move (sha, arg2, flstack);
6476
	fopr (op, 0, flstack, dest, 1);/* 3: fdivp st,st(2) */
6477
 
6478
	return;
6479
      };
6480
      /* fall through to case 3 */
6481
    case 3:
6482
      if (use_pop (last_arg, arg1.where_exp) == 2) {
6483
	fopm (sha, op, 1, arg2);
6484
 
6485
	move (sha, flstack, dest);
6486
	return;
6487
      };
6488
 
6489
      move (sha, arg2, flstack);
6490
      fopr (op, 0, arg1, flstack, 0); /* 4: fdiv st(2),st */
6491
 
6492
      move (sha, flstack, dest);
6493
      return;
6494
    case 0:
6495
    case 1:
6496
      {
6497
	int   up1;
6498
	int   up2;
6499
	up1 = use_pop_ass (last_arg, arg1.where_exp);
6500
	up2 = use_pop_ass (last_arg, arg2.where_exp);
6501
 
6502
	if (tst == 0) {
6503
	  int  fd1 = get_reg_no(in_fl_reg (arg1.where_exp));
6504
	  int  fd2 = get_reg_no(in_fl_reg (arg2.where_exp));
6505
 
6506
	  if (up1 == 2 && fd2 != fstack_pos && eq_where(arg2, dest)) {
6507
	    fopr(op, 1, flstack, arg2, 1); /* 8: fdivrp st,st(3) */
6508
	    return;
6509
	  };
6510
	  if (up2 == 2 && fd1 != fstack_pos && eq_where(arg1, dest)) {
6511
	    fopr(op, 0, flstack, arg1, 1); /* 11:  fdivp st,st(3) */
6512
	    return;
6513
	  };
6514
	};
6515
 
6516
	{
6517
	  if (up1 == 2) {
6518
	    int  fd2;
6519
	    fd2 = in_fl_reg (arg2.where_exp);
6520
	    if (get_reg_no (fd2) != fstack_pos) {
6521
	      if (tst == 0) {
6522
	        fopr (op, 1, arg2, flstack, 0); /* 9: fdivr st(1),st */
6523
	        move (sha, flstack, dest);
6524
	        return;
6525
	      }
6526
	      else
6527
	      if (up2 == 1) {
6528
	        fopr (op, 1, flstack, arg2, 1); /* 7: divrp st,st(1) */
6529
	        move (sha, flstack, dest);
6530
	        return;
6531
	      };
6532
	    };
6533
	  };
6534
 
6535
	  if (up2 == 2) {
6536
	    int  fd1;
6537
	    fd1 = in_fl_reg (arg1.where_exp);
6538
	    if (get_reg_no (fd1) != fstack_pos) {
6539
	      if (tst == 0) {
6540
	        fopr (op, 0, arg1, flstack, 0); /* 10: fdiv st(2), st */
6541
	        move (sha, flstack, dest);
6542
	        return;
6543
	      }
6544
	      else
6545
	      if (up1 == 1) {
6546
	        fopr (op, 0, flstack, arg1, 1); /* untested */
6547
	        move (sha, flstack, dest);
6548
	        return;
6549
	      }
6550
	      else {
6551
		fopr(op, 0, arg1, flstack, 0); /* 6: fdiv st(2),st */
6552
		move (sha, flstack, dest);
6553
		return;
6554
	      };
6555
	    };
6556
	  };
6557
	};
6558
 
6559
 
6560
	move (sha, arg2, flstack);
6561
	fopr (op, 0, arg1, flstack, 0); /* 5: fdiv st(2),st */
6562
 
6563
	move (sha, flstack, dest);
6564
	return;
6565
	};
6566
 
6567
 
6568
  };
6569
}
6570
 
6571
 
6572
/* apply binary floating point operation
6573
   to list of arguments arglist and put result
6574
   into dest */
6575
void fl_multop
6576
    PROTO_N ( (op, sha, arglist, dest) )
6577
    PROTO_T ( unsigned char op X shape sha X exp arglist X where dest )
6578
{
6579
  exp arg1 = arglist;
6580
  exp arg2 = bro(arg1);
6581
  if (last (arg1)) {	/* only one arg, so just move to dest */
6582
    move (sha, mw (arg1, 0), dest);
6583
    return;
6584
  }
6585
  if (last (arg2)) {	/* two args */
6586
    fl_binop (op, sha, mw (arg1, 0), mw (arg2, 0), dest, arg2);
6587
    return;
6588
  }
6589
  move(sha, mw (arg1, 0), flstack);
6590
  for (;;) {
6591
    move(sha, mw (arg2, 0), flstack);
6592
    switch (op)
6593
     {
6594
	case fplus_tag:
6595
	   ins0("faddp %st,%st(1)"); break;
6596
	case fmult_tag:
6597
	   ins0("fmulp %st,%st(1)"); break;
6598
	default:
6599
	   failer (BAD_FLOP); break;
6600
      };
6601
    pop_fl;
6602
    if (last(arg2)) break;
6603
    arg2 = bro(arg2);
6604
  }
6605
  move(sha, flstack, dest);
6606
  return;
6607
}
6608
 
6609
 
6610
/* rounds the value in the top of fl stack
6611
   and pops it into "to". Rounding
6612
   according to mode:
6613
 
6614
      1 round down:
6615
      2 round up:
6616
      3 round toward 0
6617
      4 is round as state
6618
   ul is true iff dest is unsigned >= 32
6619
   sz is 32 unless dest is 64-bit */
6620
static  void round_code
6621
    PROTO_N ( (mode, ul, sz) )
6622
    PROTO_T ( int mode X int ul X int sz )
6623
{
6624
  if (mode == 0 || mode == 4) {
6625
    sub (slongsh, mw (zeroe, sz/8), sp, sp);
6626
    extra_stack += sz;
6627
    check_stack_max;
6628
  }
6629
  else {
6630
    sub (slongsh, mw (zeroe, (sz+32)/8), sp, sp);
6631
    extra_stack += (sz+32);
6632
    check_stack_max;
6633
    ins1 (fstcw, size16, mw (ind_sp.where_exp, (-(sz+32))));
6634
    if (ul && mode ==3) {	/* round toward zero unsigned */
6635
      int labpos = next_lab();
6636
      int labend = next_lab();
6637
      ins0 (ftst);
6638
      ins1 (fnstsw, 16, reg0);
6639
      testah(flpt_test_no[f_less_than]);
6640
      move (swordsh, mw (ind_sp.where_exp, (-(sz+32))), reg0);
6641
      simple_branch (jpe, labpos);
6642
      or (swordsh, mw (zeroe, (mode << 10)), reg0, reg0);  /* neg, round toward zero */
6643
      simple_branch (jmp, labend);
6644
      simplest_set_lab (labpos);
6645
      or (swordsh, mw (zeroe, (1 << 10)), reg0, reg0);  /* pos, round down */
6646
      simplest_set_lab (labend);
6647
    }
6648
    else {
6649
      move (swordsh, mw (ind_sp.where_exp, (-(sz+32))), reg0);
6650
      or (swordsh, mw (zeroe, (mode << 10)), reg0, reg0);
6651
    };
6652
    move (swordsh, reg0, mw (ind_sp.where_exp, (-(sz+16))));
6653
    invalidate_dest (reg0);
6654
    ins1 (fldcw, size16, mw (ind_sp.where_exp, (-(sz+16))));
6655
  };
6656
  if (ul) {
6657
    if (sz == 64) {
6658
      move (doublesh, mw (sllmaxe, 0), flstack);
6659
      ins0("fsubrp %st,%st(1)");
6660
      pop_fl;
6661
    }
6662
    else
6663
      ins1 (fsubl, size64, mw (smaxe, 0));
6664
  };
6665
  ins0 (frndint);
6666
  ins1 ((sz == 64 ? fistpll : fistpl), sz, mw (ind_sp.where_exp, (-sz)));
6667
  if (mode != 0 && mode != 4) {
6668
    ins1 (fldcw, size16, mw (ind_sp.where_exp, (-(sz+32))));
6669
    add (slongsh, mw (zeroe, 4), sp, sp);
6670
    extra_stack -= 32;
6671
  };
6672
  invalidate_dest(ind_sp);
6673
  return;
6674
}
6675
 
6676
 
6677
static  void roundit
6678
    PROTO_N ( (sha, from, to, mode) )
6679
    PROTO_T ( shape sha X where from X where to X int mode )
6680
{
6681
  shape shfrom = sh (from.where_exp);
6682
  int ul = (name (sha) == ulonghd || name (sha) == u64hd);
6683
  int sz = (shape_size (sha) == 64) ? 64 : 32;
6684
 
6685
  cond1_set = 0;
6686
  cond2_set = 0;
6687
 
6688
  move (shfrom, from, flstack);
6689
 
6690
  round_code (mode, ul, sz);
6691
  if (ul) {
6692
    xor (ulongsh, mw(ind_sp.where_exp, -32), mw(zeroe, (int)((unsigned int)1<<31)),
6693
	mw(ind_sp.where_exp, -32));
6694
  }
6695
  pop_fl;
6696
  if (flinmem (to)) {
6697
    move (sha, mw(ind_sp.where_exp, -sz), reg0);
6698
    invalidate_dest(reg0);
6699
    add (slongsh, mw (zeroe, sz/8), sp, sp);
6700
    extra_stack -= sz;
6701
    move (sha, reg0, to);
6702
  }
6703
  else
6704
   {
6705
    move (sha, mw(ind_sp.where_exp, -sz), to);
6706
    add (slongsh, mw (zeroe, sz/8), sp, sp);
6707
    extra_stack -= sz;
6708
   };
6709
  return;
6710
}
6711
 
6712
 
6713
/* floating point round */
6714
void frnd0
6715
    PROTO_N ( (sha, from, to) )
6716
    PROTO_T ( shape sha X where from X where to )
6717
{
6718
  roundit (sha, from, to, 0);
6719
  return;
6720
}
6721
 
6722
/* floating point round */
6723
void frnd1
6724
    PROTO_N ( (sha, from, to) )
6725
    PROTO_T ( shape sha X where from X where to )
6726
{
6727
  roundit (sha, from, to, 1);
6728
  return;
6729
}
6730
 
6731
/* floating point round */
6732
void frnd2
6733
    PROTO_N ( (sha, from, to) )
6734
    PROTO_T ( shape sha X where from X where to )
6735
{
6736
  roundit (sha, from, to, 2);
6737
  return;
6738
}
6739
 
6740
/* floating point round */
6741
void frnd3
6742
    PROTO_N ( (sha, from, to) )
6743
    PROTO_T ( shape sha X where from X where to )
6744
{
6745
  roundit (sha, from, to, 3);
6746
  return;
6747
}
6748
 
6749
/* floating point round */
6750
void frnd4
6751
    PROTO_N ( (sha, from, to) )
6752
    PROTO_T ( shape sha X where from X where to )
6753
{
6754
  roundit (sha, from, to, 4);
6755
  return;
6756
}
6757
 
6758
/* float the integer from, result to */
6759
void floater
6760
    PROTO_N ( (sha, from, to) )
6761
    PROTO_T ( shape sha X where from X where to )
6762
{
6763
  shape shfrom = sh (from.where_exp);
6764
  int  szf;
6765
  int im;
6766
  exp holdfe;
6767
  szf = shape_size(shfrom);
6768
  im = inmem (from);
6769
 
6770
 
6771
  if (!im || szf < 32) {
6772
    if (szf < 32) {
6773
      change_var (slongsh, from, reg0);
6774
      ins1 (pushl,  32, reg0);
6775
#ifdef NEWDWARF
6776
      if (diagnose && dwarf2 && no_frame)
6777
	dw2_track_push();
6778
#endif
6779
      from = ind_sp;
6780
    }
6781
    else {
6782
      if (szf == 64) {
6783
	ins0 (pushedx);
6784
#ifdef NEWDWARF
6785
	if (diagnose && dwarf2 && no_frame)
6786
	  dw2_track_push();
6787
#endif
6788
	ins0 (pusheax);
6789
#ifdef NEWDWARF
6790
	if (diagnose && dwarf2 && no_frame)
6791
	  dw2_track_push();
6792
#endif
6793
      }
6794
      else {
6795
	ins1 (pushl, szf, from);
6796
#ifdef NEWDWARF
6797
	if (diagnose && dwarf2 && no_frame)
6798
	  dw2_track_push();
6799
#endif
6800
      }
6801
      from = ind_sp;
6802
    };
6803
  };
6804
 
6805
  holdfe = son(from.where_exp);
6806
  contop (from.where_exp, 0, reg0);
6807
  ins1 ((szf == 64 ? fildll : fildl), szf, from);
6808
  if (name (shfrom) == ulonghd || name (shfrom) == u64hd) {
6809
    int  lab = next_lab ();
6810
    ins2 (cmpl, szf, szf, zero, from);
6811
    simple_branch (jge, lab);
6812
    if (szf == 64) {
6813
      move (doublesh, mw (sllmaxe, 0), flstack);
6814
      ins0("faddp %st,%st(1)");
6815
    }
6816
    else
6817
      ins1 (faddl, size64, mw (dlongmaxe, 0));
6818
    simple_set_label (lab);
6819
  };
6820
  end_contop ();
6821
 
6822
  if (!im || szf < 32) {
6823
    ins2 (addl,  32,  32, mw (zeroe, (szf == 64 ? 8 : 4)), sp);
6824
  };
6825
  push_fl;
6826
  move (sha, flstack, to);
6827
  son(from.where_exp) = holdfe;
6828
  return;
6829
}
6830
 
6831
/* change floating variety of from to sha,
6832
   put in to. Shortening change now dealt
6833
   with by test_fl_ovfl */
6834
void changefl
6835
    PROTO_N ( (sha, from, to) )
6836
    PROTO_T ( shape sha X where from X where to )
6837
{
6838
  shape shfrom = sh (from.where_exp);
6839
  if (in_fl_reg (from.where_exp)) {/* from is in a fl reg */
6840
	/* change in case of shortening now dealt with by test_fl_ovfl */
6841
    move (sha, from, to);	/* just move to destination */
6842
    return;
6843
  };
6844
 
6845
  /* from is not in fl reg */
6846
  move (shfrom, from, flstack);
6847
  move (sha, flstack, to);
6848
  return;
6849
}
6850
 
6851
/* floating point negate */
6852
void fl_neg
6853
    PROTO_N ( (sha, from, to) )
6854
    PROTO_T ( shape sha X where from X where to )
6855
{
6856
  int  f1 = in_fl_reg (from.where_exp);
6857
  int  f2 = in_fl_reg (to.where_exp);
6858
 
6859
 
6860
  if (f1 != 0 && f2 != 0 &&
6861
      get_reg_no (f1) == fstack_pos &&
6862
      get_reg_no (f2) == fstack_pos) {
6863
    ins0 (fchs);
6864
    return;
6865
  };
6866
  move (sha, from, flstack);
6867
  ins0 (fchs);
6868
  move (sha, flstack, to);
6869
  return;
6870
}
6871
 
6872
/* floating point abs */
6873
void fl_abs
6874
    PROTO_N ( (sha, from, to) )
6875
    PROTO_T ( shape sha X where from X where to )
6876
{
6877
  int  f1 = in_fl_reg (from.where_exp);
6878
  int  f2 = in_fl_reg (to.where_exp);
6879
 
6880
 
6881
  if (f1 != 0 && f2 != 0 &&
6882
      get_reg_no (f1) == fstack_pos &&
6883
      get_reg_no (f2) == fstack_pos) {
6884
    ins0 (fabs);
6885
    return;
6886
  };
6887
  move (sha, from, flstack);
6888
  ins0 (fabs);
6889
  move (sha, flstack, to);
6890
  return;
6891
}
6892
 
6893
/*
6894
    For each of 14 possible comparison operators replace the sahf, j??
6895
    as follows:
6896
 
6897
<	andb $0b00000101,%ah; jpo	!<	andb $0b00000101,%ah; jpe
6898
>	andb $0b01000101,%ah; jz	!>	andb $0b01000101,%ah; jnz
6899
<=	andb $0b01000001,%ah; jpo	!<=	andb $0b01000001,%ah; jpe
6900
>=	andb $0b00000101,%ah; jz	!>=	andb $0b00000101,%ah; jnz
6901
==	andb $0b01000100,%ah; jpo	!=	andb $0b01000100,%ah; jpe
6902
<>	andb $0b01000000,%ah; jz	!<>	andb $0b01000000,%ah; jnz
6903
<>=	andb $0b00000100,%ah; jz	!<>=	andb $0b00000100,%ah; jnz
6904
*/
6905
 
6906
 
6907
/* floating point compare */
6908
void fl_comp
6909
    PROTO_N ( (sha, pos, neg, e) )
6910
    PROTO_T ( shape sha X where pos X where neg X exp e )
6911
{
6912
				/* can improve this to use other
6913
				   comparison instructions */
6914
  cond1_set = 0;
6915
  cond2_set = 0;
6916
  move (sha, neg, flstack);
6917
  move (sha, pos, flstack);
6918
  ins0 (fcompp);
6919
 
6920
  ins1 (fnstsw,  16, reg0);
6921
 
6922
  testah(flpt_test_no[test_number(e)]);
6923
 
6924
  invalidate_dest (reg0);
6925
  pop_fl;
6926
  pop_fl;
6927
  return;
6928
}
6929
 
6930
/* use test instruction */
6931
void test
6932
    PROTO_N ( (sha, a, b) )
6933
    PROTO_T ( shape sha X where a X where b )
6934
{
6935
  char *t;
6936
  int  sz;
6937
  exp hold;
6938
 
6939
  sz = shape_size(sha);
6940
 
6941
  switch (sz) {
6942
    case 8:
6943
      t = testb;
6944
      break;
6945
    case 16:
6946
      t = testw;
6947
      break;
6948
    default:
6949
      t = testl;
6950
  };
6951
 
6952
  cond1_set = 0;
6953
  cond2_set = 0;
6954
 
6955
  if (inmem (a) && inmem (b)) {
6956
    hold = son(b.where_exp);
6957
    move (sha, a, reg0);
6958
    contop (b.where_exp, 1, reg0);
6959
    ins2 (t, sz, sz, reg0, b);
6960
    end_contop ();
6961
    son(b.where_exp) = hold;
6962
    return;
6963
  };
6964
  if (!inmem (b) && name (a.where_exp) != val_tag) {
6965
    hold = son(a.where_exp);
6966
    contop (a.where_exp,  (eq_where (reg0, a) || eq_where (reg0, b)),
6967
	reg0);
6968
    ins2 (t, sz, sz, b, a);
6969
    end_contop ();
6970
    son(a.where_exp) = hold;
6971
    return;
6972
  };
6973
  hold = son(b.where_exp);
6974
  contop (b.where_exp,  (eq_where (reg0, a) || eq_where (reg0, b)),
6975
      reg0);
6976
  ins2 (t, sz, sz, a, b);
6977
  end_contop ();
6978
  son(b.where_exp) = hold;
6979
  return;
6980
}
6981
 
6982
 
6983
/* decrease the stack */
6984
void decstack
6985
    PROTO_N ( (longs) )
6986
    PROTO_T ( int longs )
6987
{
6988
 
6989
  ins2 (subl,  32,  32, mw (zeroe, (longs / 8)), sp);
6990
  return;
6991
}
6992
 
6993
void long_jump
6994
    PROTO_N ( (e) )
6995
    PROTO_T ( exp e )
6996
{
6997
  ins0(popebp);
6998
  ins0(ret);
6999
  return;
7000
}
7001
 
7002
 
7003
 
7004
static int fp_clear = 0;
7005
 
7006
void reset_fpucon
7007
    PROTO_Z ()
7008
{
7009
  fp_clear = 0;
7010
  if (fpucon == normal_fpucon)
7011
    return;
7012
  if (fpucon & ~normal_fpucon & (int)0xd) {
7013
    ins0(fclex);
7014
    fp_clear = 1;
7015
  }
7016
  if (ferrsize < 32)
7017
    ferrsize = 32;
7018
  ins1 (fldcw, 16, mw(ferrmem,0));
7019
  fpucon = normal_fpucon;
7020
}
7021
 
7022
static void set_fpucon
7023
    PROTO_N ( (mask, val) )
7024
    PROTO_T ( int mask X int val )
7025
{
7026
  if ((fpucon & mask) == val)
7027
    return;
7028
  fpucon = ((~mask & fpucon) | val);
7029
  if (ferrsize < 32)
7030
    ferrsize = 32;
7031
  move (uwordsh, mw(zeroe, fpucon), mw(ferrmem, 16));
7032
  ins1 (fldcw, 16, mw(ferrmem,16));
7033
}
7034
 
7035
void setup_fl_ovfl
7036
    PROTO_N ( (e) )
7037
    PROTO_T ( exp e )
7038
{
7039
  int traps = 0xd;
7040
  int ival;
7041
  int eprmask = 0x300;
7042
  if (errhandle(e) == 0) {
7043
    if (name(sh(e)) == doublehd)
7044
      set_fpucon (eprmask, eprmask);
7045
    return;
7046
  }
7047
  if (!fp_clear && !optop(e)) {
7048
    ins0(fclex);
7049
    fp_clear = 1;
7050
  }
7051
  ival = (istrap(e) ? 0 : traps);
7052
  if (name(sh(e)) == doublehd || name(sh(e)) == s64hd || name(sh(e)) == u64hd)
7053
    set_fpucon ((eprmask | traps), (eprmask | ival));
7054
  else
7055
    set_fpucon (traps, ival);
7056
  return;
7057
}
7058
 
7059
void test_fl_ovfl
7060
    PROTO_N ( (e, dest) )
7061
    PROTO_T ( exp e X where dest )
7062
{
7063
  int r;
7064
  if (errhandle(e) == 0)
7065
    return;
7066
  r = in_fl_reg(dest.where_exp);
7067
  if (r && (name(sh(e)) == realhd || name(sh(e)) == shrealhd)) {
7068
	/* overflow won't register until stored in memory */
7069
    where m;
7070
    int reqsize = 32 + shape_size(sh(e));
7071
    if (ferrsize < reqsize)
7072
      ferrsize = reqsize;
7073
    m = mw(ferrmem,32);
7074
    if (get_reg_no(r) == fstack_pos && !optop(e)) {
7075
	/* avoid move, which pops the stack */
7076
      if (name(sh(e)) == realhd)
7077
	ins1 (fstl, 64, m);
7078
      else
7079
	ins1 (fsts, 32, m);
7080
    }
7081
    else {
7082
      move (sh(e), dest, m);
7083
      if (optop(e))		/* replace by suitable value */
7084
	move (sh(e), m, dest);
7085
    }
7086
  }
7087
  if (optop(e)) {
7088
    fp_clear = 0;
7089
    return;
7090
  }
7091
  if (isov(e))  {
7092
    if (eq_where (dest, reg0)) {
7093
      ins0(pusheax);
7094
#ifdef NEWDWARF
7095
      if (diagnose && dwarf2 && no_frame)
7096
	dw2_track_push();
7097
#endif
7098
    }
7099
    ins1 (fstsw,  16, reg0);
7100
    ins2(testb, 8, 8, mw(zeroe, 13), reg0);
7101
		/* Overflow, Zero divide or Invalid  */
7102
    if (eq_where (dest, reg0)) {
7103
      ins0(popeax);
7104
#ifdef NEWDWARF
7105
      if (diagnose && dwarf2 && no_frame)
7106
	dw2_track_pop();
7107
#endif
7108
    }
7109
    branch(f_equal, pt(son(pt(e))), 0, scharhd);
7110
    invalidate_dest(reg0);
7111
  };
7112
  return;
7113
}
7114
 
7115
exp find_stlim_var
7116
    PROTO_Z ()
7117
{
7118
  return (make_extn ("__trans386_stack_limit", ulongsh, 1));
7119
}
7120
 
7121
void checkalloc_stack
7122
    PROTO_N ( (sz, b) )
7123
    PROTO_T ( where sz X int b )
7124
{
7125
  /* uses reg1 */
7126
  int erlab = next_lab ();
7127
  int cnlab = next_lab ();
7128
  if (cont_stacklimit == nilexp) {
7129
    cont_stacklimit = make_extn ("__trans386_stack_limit", ulongsh, 1);
7130
    if (!PIC_code)
7131
      cont_stacklimit = getexp (ulongsh, nilexp, 1, cont_stacklimit, nilexp, 0, 0, cont_tag);
7132
  }
7133
  ins2 (movl, 32, 32, sp, reg1);
7134
  ins2 (subl, 32, 32, sz, reg1);
7135
  simple_branch (jb, erlab);
7136
  if (PIC_code) {
7137
    ins2 (movl, 32, 32, mw(cont_stacklimit, 0), reg0);
7138
    ins2 (cmpl, 32, 32, ind_reg0, reg1);
7139
    simple_branch (ja, cnlab);
7140
  }
7141
  else {
7142
    ins2 (cmpl, 32, 32, mw(cont_stacklimit, 0), reg1);
7143
    simple_branch (ja, cnlab);
7144
  }
7145
  simple_set_label (erlab);
7146
  trap_ins (f_stack_overflow);
7147
  simple_set_label (cnlab);
7148
  if (b)
7149
    ins2 (movl, 32, 32, reg1, sp);
7150
}
7151
 
7152
/* Builtin functions. All args are operands */
7153
void special_ins
7154
    PROTO_N ( (id, arg, dest) )
7155
    PROTO_T ( char * id X exp arg X where dest )
7156
{
7157
  if (!strcmp (id, "__trans386_special") && name(arg) == val_tag) {
7158
    switch (no(arg)) {
7159
      case 0:
7160
	ins0(fwait);
7161
	return;
7162
      case 1:
7163
	ins0(finit);
7164
	fpucon = 0x37f;
7165
	reset_fpucon();
7166
	return;
7167
      case 2:
7168
	ins0(fclex);
7169
	return;
7170
    };
7171
  }
7172
  failer (BADOP);
7173
}
7174
 
7175
void save_stack
7176
    PROTO_Z ()
7177
{
7178
  if (extra_stack || stack_dec)
7179
    failer ("unclean stack");
7180
  ins2 (movl, 32, 32, sp, firstlocal);
7181
}
7182
 
7183
void restore_stack
7184
    PROTO_Z ()
7185
{
7186
  if (extra_stack || stack_dec)
7187
    failer ("unclean stack");
7188
  ins2 (movl, 32, 32, firstlocal, sp);
7189
}
7190
 
7191
void start_asm
7192
    PROTO_Z ()
7193
{
7194
  outnl ();
7195
#ifdef as_comment_symbol
7196
  outc ('\t'); outc (as_comment_symbol);
7197
  outs (" ASM sequence start");
7198
  outnl ();
7199
#endif
7200
  return;
7201
}
7202
 
7203
void end_asm
7204
    PROTO_Z ()
7205
{
7206
#ifdef as_comment_symbol
7207
  outc ('\t'); outc (as_comment_symbol);
7208
  outs (" ASM sequence ends");
7209
  outnl ();
7210
#endif
7211
  outnl ();
7212
  return;
7213
}
7214
 
7215
void asm_ins
7216
    PROTO_N ( (e) )
7217
    PROTO_T ( exp e )
7218
{
7219
  if (name(son(e)) == string_tag)
7220
    outs (nostr(son(e)));
7221
  else {
7222
    int prev_use_bp = must_use_bp;
7223
    must_use_bp = 1;	/* scan2 must ensure !no_frame */
7224
    operand (shape_size(son(e)), mw (son(e), 0), 1, 0);
7225
    must_use_bp = prev_use_bp;
7226
  }
7227
  return;
7228
}