Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /trunk/src/installers/amd64/common/instr386.c – Rev 6

Subversion Repositories tendra.SVN

Rev

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

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