Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
7 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
33
 
34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
42
 
43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
45
 
46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
49
 
50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
53
 
54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
/* 80x86/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,
7 7u83 430
  0x1fffffff, 0x3fffffff, 0x7fffffff,(int)0xffffffff
2 7u83 431
};
432
 
433
int  msmask[33] = {
434
  0,
7 7u83 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
2 7u83 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
7 7u83 452
(shape sha, int inv)
2 7u83 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;
7 7u83 459
      jmp_overflow(jd, is_signed(sha), inv);
2 7u83 460
    }
461
    else
462
    if (istrap(overflow_e)) {
463
      overflow_e = nilexp;
7 7u83 464
      trap_overflow(is_signed(sha), inv);
2 7u83 465
    }
466
    overflow_e = oe;
467
  }
468
  return;
469
}
470
 
471
static void test_exception
7 7u83 472
(int test_no, shape sha)
2 7u83 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;
7 7u83 479
      branch(test_no, jd, is_signed(sha), name(sha));
2 7u83 480
    }
481
    else
482
    if (istrap(overflow_e)) {
483
      overflow_e = nilexp;
7 7u83 484
      test_trap(test_no, is_signed(sha), name(sha));
2 7u83 485
    }
486
    overflow_e = oe;
487
  }
488
  return;
489
}
490
 
491
static void do_exception
7 7u83 492
(void)
2 7u83 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;
7 7u83 499
      jump(jd, 0);
2 7u83 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
7 7u83 514
(exp n, exp ln)
2 7u83 515
{
516
  exp id;
7 7u83 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 ||
2 7u83 524
		name(n) == ass_tag))
7 7u83 525
    n = bro(n);
2 7u83 526
  if (n == id)
7 7u83 527
    return(get_reg_no(no(id)) - fstack_pos + 2);
528
  return(0);
2 7u83 529
}
530
 
531
 
532
static int   use_pop
7 7u83 533
(exp n, exp ln)
2 7u83 534
{
535
  exp id;
7 7u83 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);
2 7u83 543
  if (n == id)
7 7u83 544
    return(get_reg_no(no(id)) - fstack_pos + 2);
545
  return(0);
2 7u83 546
}
547
 
548
int  count_regs
7 7u83 549
(int mask)
2 7u83 550
{
7 7u83 551
  return(bits_in[mask & 0xf] + bits_in[(mask >> 4) & 0x3]);
2 7u83 552
}
553
 
554
static void cmp64_contop
7 7u83 555
(int d)
2 7u83 556
{
557
  if (d && contop_dopop) {
558
    int lolab = next_lab();
7 7u83 559
    simple_branch(je, lolab);
2 7u83 560
    if (contop_dopop == 1)
561
     {
7 7u83 562
      ins1(popl, size32, SPILLREG);
2 7u83 563
#ifdef NEWDWARF
564
      if (diagnose && dwarf2 && no_frame)
565
	dw2_track_pop();
566
#endif
567
     }
568
    else
569
     {
7 7u83 570
	exp ap = getexp(f_bottom, nilexp, 0, sp.where_exp,
2 7u83 571
                          nilexp, 0, 4, reff_tag);
7 7u83 572
        ins2(leal, size32, size32, mw(ap, 0), sp);
2 7u83 573
     };
7 7u83 574
    simple_branch(jmp, cmp_64hilab);
575
    simplest_set_lab(lolab);
2 7u83 576
  }
577
  else
7 7u83 578
    simple_branch(jne, cmp_64hilab);
2 7u83 579
  return;
580
}
581
 
582
 
583
void end_contop
7 7u83 584
(void)
2 7u83 585
{
586
  if (contop_level == 0)
587
    reg0_in_use = 0;
588
  if (contop_dopop) {
589
    if (contop_dopop == 1)
590
     {
7 7u83 591
      ins1(popl, size32, SPILLREG);
2 7u83 592
#ifdef NEWDWARF
593
      if (diagnose && dwarf2 && no_frame)
594
	dw2_track_pop();
595
#endif
596
     }
597
    else
598
     {
7 7u83 599
	exp ap = getexp(f_bottom, nilexp, 0, sp.where_exp,
2 7u83 600
                          nilexp, 0, 4, reff_tag);
7 7u83 601
        ins2(leal, size32, size32, mw(ap, 0), sp);
2 7u83 602
     };
7 7u83 603
    invalidate_dest(SPILLREG);
2 7u83 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
7 7u83 614
(exp a, int r0inuse, where dest)
2 7u83 615
{
7 7u83 616
  unsigned char  n = name(a);
2 7u83 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)
7 7u83 631
      && name(son(a)) == ident_tag) {
2 7u83 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 */
7 7u83 639
    int  inreg1 = ptno(son(son(id1))) == reg_pl;
2 7u83 640
					/* true if def of outer identity
641
					   is already in a register */
642
    int  reg_mask = (~regsinuse) & 0x3e;
7 7u83 643
    int  regs_free = count_regs(reg_mask);
2 7u83 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 */
7 7u83 658
      int  inreg2 = ptno(son(son(id2))) == reg_pl;
2 7u83 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 */
7 7u83 665
      fin = bro(son(fin));
2 7u83 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) {
7 7u83 675
	    ptno(id1) = reg_pl;
2 7u83 676
	    no (id1) = 1;		/* id1 uses reg0 */
7 7u83 677
	    ptno(id2) = reg_pl;
678
	    no(id2) = no(son(son(id2)));
2 7u83 679
	  }
680
	  else {
7 7u83 681
	    ptno(id2) = reg_pl;
2 7u83 682
	    no (id2) = 1;		/* id2 uses reg0 */
7 7u83 683
	    ptno(id1) = reg_pl;
684
	    no(id1) = no(son(son(id1)));
2 7u83 685
	  };
686
 
7 7u83 687
	  coder(mw(id1, 0), st, son(id1));
2 7u83 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;
7 7u83 702
	    f = first_reg(reg_mask);
2 7u83 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 */
7 7u83 711
	    offset = no(fin);
712
	    fin = son(fin);
2 7u83 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 */
7 7u83 718
	  if (name(bro(son(fin))) == name_tag) {
2 7u83 719
			/* the offset is named, so add the pointer to the
720
			   offset and put in the free register */
7 7u83 721
	    add(slongsh, mw(son(id2), 0), mw(son(id1), 0), use_reg);
2 7u83 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 */
7 7u83 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),
2 7u83 730
		use_reg);
7 7u83 731
	    add(slongsh, mw(son(id2), 0), use_reg, use_reg);
2 7u83 732
	  };
733
          overflow_e = old_overflow_e;
734
 
735
	  if (offset != 0) {
736
			/* put back the reff if there was one */
7 7u83 737
	    exp r = getexp(sh(son(a)), nilexp, 0, use_reg.where_exp,
2 7u83 738
		nilexp, 0, offset, reff_tag);
7 7u83 739
	    son(a) = r;
2 7u83 740
	  }
741
	  else
7 7u83 742
	    son(a) = use_reg.where_exp;
2 7u83 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 */
7 7u83 750
	ins1(pushl, size32, SPILLREG);
2 7u83 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 */
7 7u83 759
	  offset = no(fin);
760
	  fin = son(fin);
2 7u83 761
	};
762
 
763
        old_overflow_e = overflow_e;
764
        overflow_e = nilexp;
765
		/* it must be an addptr */
7 7u83 766
	if (name(bro(son(fin))) == name_tag) {
2 7u83 767
		/* the offset is named */
7 7u83 768
	  move(slongsh, mw(son(id1), 0), SPILLREG);
2 7u83 769
			/* put the offset in SPILLREG */
770
 
7 7u83 771
	  if (eq_where(SPILLREG, mw(son(id2), 0)))
2 7u83 772
			/* id2 is the SPILLREG, so add the pushed value */
7 7u83 773
	    add(slongsh, stack0, SPILLREG, SPILLREG);
2 7u83 774
	  else
775
			/* otherwise add def of id2 to SPILLREG */
7 7u83 776
	    add(slongsh, mw(son(id2), 0), SPILLREG, SPILLREG);
2 7u83 777
	}
778
	else {
779
		/* the offset is an offset_mult */
7 7u83 780
	  exp m = bro(son(fin));
781
	  move(slongsh, mw(son(id1), 0), SPILLREG);
2 7u83 782
			/* number to SPILLREG */
7 7u83 783
	  mult(slongsh, SPILLREG, mw(bro(son(m)), 0), SPILLREG);
2 7u83 784
			/* multiply by size */
7 7u83 785
	  if (eq_where(SPILLREG, mw(son(id2), 0)))
2 7u83 786
			/* id2 is the SPILLREG, so add the pushed value */
7 7u83 787
	    add(slongsh, stack0, SPILLREG, SPILLREG);
2 7u83 788
	  else
789
			/* otherwise add def of id2 to SPILLREG */
7 7u83 790
	    add(slongsh, mw(son(id2), 0), SPILLREG, SPILLREG);
2 7u83 791
	};
792
        overflow_e = old_overflow_e;
793
 
794
	if (offset != 0) {	/* put back the reff if needed */
7 7u83 795
	  exp r = getexp(sh(son(a)), nilexp, 0, SPILLREG.where_exp,
2 7u83 796
	      nilexp, 0, offset, reff_tag);
7 7u83 797
	  son(a) = r;
2 7u83 798
	}
799
	else
7 7u83 800
	  son(a) = SPILLREG.where_exp;
2 7u83 801
			/* code the rest in the caller */
802
 
803
	contop_level--;
804
 
7 7u83 805
	if (!eq_where(dest, SPILLREG))
2 7u83 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
 
7 7u83 837
	move(slongsh, mw(son(id1), 0), SPILLREG);
2 7u83 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--;
7 7u83 845
	if (!eq_where(dest, SPILLREG))
2 7u83 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 */
7 7u83 853
      move(slongsh, mw(son(id1), 0), reg0);
2 7u83 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
7 7u83 882
(void)
2 7u83 883
{
884
				/* set up the constants */
7 7u83 885
  int  flongmax = new_flpt();
886
  int  fllmax = new_flpt();
887
  int  fslongmax = new_flpt();
888
  int  fsllmax = new_flpt();
2 7u83 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++) {
7 7u83 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);
2 7u83 908
  };
909
 
7 7u83 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,
2 7u83 914
      flongmax, real_tag);
7 7u83 915
  smaxe = getexp(realsh, nilexp, 0, nilexp, nilexp, 0,
2 7u83 916
      fslongmax, real_tag);
7 7u83 917
  sllmaxe = getexp(doublesh, nilexp, 0, nilexp, nilexp, 0,
2 7u83 918
      fsllmax, real_tag);
7 7u83 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,
2 7u83 922
      flongmax, real_tag);
7 7u83 923
  dllmaxe = getexp(doublesh, nilexp, 0, nilexp, nilexp, 0,
2 7u83 924
      fllmax, real_tag);
7 7u83 925
  pushid = getexp(f_bottom, nilexp, 0, nilexp, nilexp, 0, 0, apply_tag);
2 7u83 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
 
7 7u83 939
  dummys = getexp(slongsh, nilexp, 0, nilexp, nilexp, 0, 0, val_tag);
940
  dummyu = getexp(ulongsh, nilexp, 0, nilexp, nilexp, 0, 0, val_tag);
2 7u83 941
 
7 7u83 942
  reg0id = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 943
      0x1, ident_tag);
944
  ptno(reg0id) = reg_pl;
7 7u83 945
  reg0 = mw(getexp(slongsh, nilexp, 0, reg0id, nilexp, 0, 0, name_tag),
2 7u83 946
      0);
947
 
7 7u83 948
  reg0charid = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 949
      0x1, ident_tag);
950
  ptno(reg0charid) = reg_pl;
7 7u83 951
  reg0char = mw(getexp(scharsh, nilexp, 0, reg0id,
2 7u83 952
	nilexp, 0, 0, name_tag),
953
      0);
954
 
7 7u83 955
  reg1id = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 956
      0x2, ident_tag);
957
  ptno(reg1id) = reg_pl;
7 7u83 958
  reg1 = mw(getexp(slongsh, nilexp, 0, reg1id, nilexp, 0, 0, name_tag),
2 7u83 959
      0);
960
 
7 7u83 961
  reg2id = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 962
      0x4, ident_tag);
963
  ptno(reg2id) = reg_pl;
7 7u83 964
  reg2 = mw(getexp(slongsh, nilexp, 0, reg2id, nilexp, 0, 0, name_tag),
2 7u83 965
      0);
966
 
7 7u83 967
  reg3id = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 968
      0x8, ident_tag);
969
  ptno(reg3id) = reg_pl;
7 7u83 970
  reg3 = mw(getexp(slongsh, nilexp, 0, reg3id, nilexp, 0, 0, name_tag),
2 7u83 971
      0);
972
 
973
 
7 7u83 974
  reg4id = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 975
      0x10, ident_tag);
976
  ptno(reg4id) = reg_pl;
7 7u83 977
  reg4 = mw(getexp(slongsh, nilexp, 0, reg4id, nilexp, 0, 0, name_tag),
2 7u83 978
      0);
979
 
7 7u83 980
  reg5id = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 981
      0x20, ident_tag);
982
  ptno(reg5id) = reg_pl;
7 7u83 983
  reg5 = mw(getexp(slongsh, nilexp, 0, reg5id, nilexp, 0, 0, name_tag),
2 7u83 984
      0);
985
 
7 7u83 986
  reg6id = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 987
      0x40, ident_tag);
988
  ptno(reg6id) = reg_pl;
7 7u83 989
  reg6 = mw(getexp(slongsh, nilexp, 0, reg6id, nilexp, 0, 0, name_tag),
2 7u83 990
      0);
991
 
7 7u83 992
  flstackid = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 993
      0x10000, ident_tag);
994
  ptno(flstackid) = reg_pl;
7 7u83 995
  flstack = mw(getexp(realsh, nilexp, 0, flstackid, nilexp,
2 7u83 996
	0, 0, name_tag),
997
      0);
998
 
7 7u83 999
  reg0uid = getexp(f_bottom, nilexp, 0, dummyu, nilexp, 0,
2 7u83 1000
      0x1, ident_tag);
1001
  ptno(reg0uid) = reg_pl;
7 7u83 1002
  reg0u = mw(getexp(ulongsh, nilexp, 0, reg0uid, nilexp, 0, 0, name_tag),
2 7u83 1003
      0);
1004
 
7 7u83 1005
  spid = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 1006
      128, ident_tag);
1007
  ptno(spid) = reg_pl;
7 7u83 1008
  sp = mw(getexp(slongsh, nilexp, 0, spid, nilexp, 0, 0, name_tag), 0);
2 7u83 1009
 
7 7u83 1010
  bpid = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0,
2 7u83 1011
      64, ident_tag);
1012
  ptno(bpid) = reg_pl;
7 7u83 1013
  bp = mw(getexp(slongsh, nilexp, 0, bpid, nilexp, 0, 0, name_tag), 0);
2 7u83 1014
 
1015
 
7 7u83 1016
  stack0ref = getexp(f_top, nilexp, 0, sp.where_exp, nilexp, 0, -32,
2 7u83 1017
      reff_tag);
7 7u83 1018
  stack0 = mw(getexp(f_pointer(f_alignment(slongsh)), nilexp, 0,
2 7u83 1019
	stack0ref, nilexp, 0, 0, cont_tag), 0);
1020
 
7 7u83 1021
  ind_reg0 = mw(getexp(f_pointer(f_alignment(slongsh)), nilexp, 0,
2 7u83 1022
	reg0.where_exp, nilexp, 0, 0, cont_tag), 0);
7 7u83 1023
  ind_reg1 = mw(getexp(f_pointer(f_alignment(slongsh)), nilexp, 0,
2 7u83 1024
	reg1.where_exp, nilexp, 0, 0, cont_tag), 0);
7 7u83 1025
  ind_reg2 = mw(getexp(f_pointer(f_alignment(slongsh)), nilexp, 0,
2 7u83 1026
	reg2.where_exp, nilexp, 0, 0, cont_tag), 0);
7 7u83 1027
  ind_reg4 = mw(getexp(f_pointer(f_alignment(slongsh)), nilexp, 0,
2 7u83 1028
	reg4.where_exp, nilexp, 0, 0, cont_tag), 0);
7 7u83 1029
  ind_sp = mw(getexp(f_pointer(f_alignment(slongsh)), nilexp, 0, sp.where_exp,
2 7u83 1030
	nilexp, 0, 0, cont_tag), 0);
1031
 
7 7u83 1032
  firstlocalid = getexp(f_bottom, nilexp, 0, dummys, nilexp, 0, 0, ident_tag);
2 7u83 1033
  ptno(firstlocalid) = local_pl;
7 7u83 1034
  firstlocal = mw(getexp(slongsh, nilexp, 0, firstlocalid, nilexp, 0, 0, name_tag), 0);
2 7u83 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
 
7 7u83 1044
  ferrmemid = getexp(f_bottom, nilexp, 0, nilexp, nilexp, 0, 0, ident_tag);
2 7u83 1045
  ptno(ferrmemid) = ferr_pl;
7 7u83 1046
  ferrmem = getexp(realsh, nilexp, 0, ferrmemid, nilexp, 0, 0, name_tag);
2 7u83 1047
 
1048
}
1049
 
1050
 
1051
 
1052
 /* 80386 output routines */
1053
 
1054
 
1055
/* is w in memory and not a constant */
1056
int flinmem
7 7u83 1057
(where w)
2 7u83 1058
{
1059
  exp e = w.where_exp;
7 7u83 1060
  unsigned char  n = name(e);
2 7u83 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) {
7 7u83 1070
      id = son(e);
2 7u83 1071
      recog = 1;
1072
    }
1073
    else {
1074
      if ((n == cont_tag || n == ass_tag) &&
7 7u83 1075
	  name(son(e)) == name_tag && isvar(son(son(e)))) {
1076
	id = son(son(e));
2 7u83 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)
7 7u83 1088
    return(1);
2 7u83 1089
  else {
1090
    SET(id);
1091
  };
1092
 
7 7u83 1093
  if (ptno(id) == reg_pl &&
2 7u83 1094
      (name (sh (son (id))) > ucharhd || no (id) < 0x10))/* 0x10 is edi */
1095
    return (0);  /* there are no char versions of edi, esi */
1096
 
7 7u83 1097
  return(1);
2 7u83 1098
}
1099
 
1100
 
1101
/* is w in memory or an integer or null
1102
   pointer constant */
1103
int inmem
7 7u83 1104
(where w)
2 7u83 1105
{
7 7u83 1106
  unsigned char  n = name(w.where_exp);
2 7u83 1107
  if (n == val_tag ||
1108
	n == null_tag || n == current_env_tag)
7 7u83 1109
    return(0);
1110
  return(flinmem(w));
2 7u83 1111
}
1112
 
1113
int w_islastuse
7 7u83 1114
(where w)
2 7u83 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
7 7u83 1128
(shape sha, where a1, where dest)
2 7u83 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);
7 7u83 1169
    move(slongsh, reg1, reg2);
1170
    move(slongsh, zero, reg1);
2 7u83 1171
    ins1(negl, 32, reg0);
1172
    ins2(sbbl, 32, 32, reg2, reg1);
7 7u83 1173
    try_overflow(sha, 0);
2 7u83 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);
7 7u83 1181
    try_overflow(sha, 0);
2 7u83 1182
  }
1183
  invalidate_dest(q);
1184
  simple_set_label(labno);
1185
  move(sha, q, dest);
1186
  return;
1187
}
1188
 
1189
 
1190
static void maxmin
7 7u83 1191
(shape sha, where a1, where a2, where dest, int ismax)
2 7u83 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)) {
7 7u83 1205
    op12 = (ismax) ? jl : jg;
1206
    op21 = (ismax)? jg : jl;
2 7u83 1207
  }
1208
  else {
7 7u83 1209
    op12 = (ismax) ? jb : ja;
1210
    op21 = (ismax)? ja : jb;
2 7u83 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)) {
7 7u83 1243
    move(sha, a1, dest);
2 7u83 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
    };
7 7u83 1255
    if (name(a2.where_exp)!= val_tag) {
2 7u83 1256
      if (mem1) {
1257
	if (sz == 64) {
1258
		/* a2 must be reg0/1 */
1259
	  regsinuse |= 0x2;
7 7u83 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);
2 7u83 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);
7 7u83 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);
2 7u83 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)) {
7 7u83 1306
	  c = no(a2.where_exp) + a2.where_off;
1307
	  c1 = (is_signed(sha) && c < 0)? -1 : 0;
2 7u83 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) {
7 7u83 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);
2 7u83 1323
	  late_contop = contop_dopop;
1324
	  contop_dopop = 0;
1325
	}
1326
	else {
1327
		/* a1 and dest must be reg0/1 */
7 7u83 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);
2 7u83 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)
7 7u83 1347
      simplest_set_lab(lab64);
2 7u83 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
7 7u83 1385
(shape sha, where a1, where a2, where dest)
2 7u83 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
7 7u83 1393
(shape sha, where a1, where a2, where dest)
2 7u83 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
7 7u83 1401
(shape sha, where a1, where a2, where dest, int plus1)
2 7u83 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
 
7 7u83 1410
  if (name(a) == val_tag && name(sh(a)) == offsethd && al2(sh(a))!= 1) {
1411
    if (name(sha) == offsethd && al2(sha)!= 1)
2 7u83 1412
      no(a) = no(a) / 8;
1413
    sh(a) = slongsh;
1414
  };
7 7u83 1415
  if (name(b) == val_tag && name(sh(b)) == offsethd && al2(sh(b))!= 1) {
1416
    if (name(sha) == offsethd && al2(sha)!= 1)
2 7u83 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
 
7 7u83 1427
  if (eq_where(a1, dest) &&
2 7u83 1428
	(!keep_short || !flinmem(dest))) {	/* altering dest */
7 7u83 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))))) {
2 7u83 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) {
7 7u83 1440
	  ins1(incb, sz, a1);
2 7u83 1441
	};
1442
	if (sz == 16) {
7 7u83 1443
	  ins1(incw, sz, a1);
2 7u83 1444
	};
1445
	if (sz == 32) {
7 7u83 1446
	  ins1(incl, sz, a1);
2 7u83 1447
	};
1448
      }
1449
      else {			/* use dec */
1450
	if (sz == 8) {
7 7u83 1451
	  ins1(decb, sz, a1);
2 7u83 1452
	};
1453
	if (sz == 16) {
7 7u83 1454
	  ins1(decw, sz, a1);
2 7u83 1455
	};
1456
	if (sz == 32) {
7 7u83 1457
	  ins1(decl, sz, a1);
2 7u83 1458
	};
1459
      };
7 7u83 1460
      invalidate_dest(dest);
1461
      end_contop();
1462
      try_overflow(sha, plus1);
2 7u83 1463
      son(a) = hold;
1464
      return;
1465
    };
1466
 
7 7u83 1467
    if (!inmem(a1) || !inmem(a2)) {
2 7u83 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;
7 7u83 1474
      if (inmem(a1))
1475
	contop(a, eq_where(reg0, a2), a1);
2 7u83 1476
      else
7 7u83 1477
	contop(b,
1478
	    (eq_where(reg0, a2) || eq_where(reg0, a1)), a1);
2 7u83 1479
      if (plus1)
7 7u83 1480
	ins0(stc);
2 7u83 1481
      if (sz == 8) {
7 7u83 1482
	ins2((plus1 ? adcb : addb), sz, sz, a2, a1);
2 7u83 1483
      };
1484
      if (sz == 16) {
7 7u83 1485
	ins2((plus1 ? adcw : addw), sz, sz, a2, a1);
2 7u83 1486
      };
1487
      if (sz == 32) {
7 7u83 1488
	ins2((plus1 ? adcl : addl), sz, sz, a2, a1);
2 7u83 1489
      };
1490
      if (sz == 64) {
1491
	where hi1, lo1, hi2, lo2;
1492
	lo1 = a1;
7 7u83 1493
	hi1 = (inmem(a1)? mw(a, aoff + 32): reg1);
1494
	if (name(b) == val_tag) {
2 7u83 1495
	  int c, c1;
1496
	  if (!isbigval(b)) {
7 7u83 1497
	    c = no(b) + boff;
1498
	    c1 = (is_signed(sha) && c < 0)? -1 : 0;
2 7u83 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
	  };
7 7u83 1507
	  lo2 = mw(zeroe, c);
1508
	  hi2 = mw(zeroe, c1);
2 7u83 1509
	}
1510
	else {
1511
	  lo2 = a2;
7 7u83 1512
	  hi2 = (inmem(a2)? mw(b, boff + 32): reg1);
2 7u83 1513
	}
7 7u83 1514
	ins2((plus1 ? adcl : addl), 32, 32, lo2, lo1);
1515
	ins2(adcl, 32, 32, hi2, hi1);
2 7u83 1516
      };
7 7u83 1517
      invalidate_dest(dest);
1518
      end_contop();
2 7u83 1519
      regsinuse = riu;
7 7u83 1520
      try_overflow(sha, plus1);
2 7u83 1521
      son(a) = holda;
1522
      son(b) = holdb;
1523
      return;
1524
    };
1525
 
7 7u83 1526
    move(sha, a2, reg0);
1527
    add_plus(sha, reg0, a1, a1, plus1);
1528
    invalidate_dest(dest);
2 7u83 1529
    return;
1530
  };
1531
 
7 7u83 1532
  if (eq_where(a2, dest) &&
2 7u83 1533
	(!keep_short || !flinmem(dest))) {	/* altering dest */
7 7u83 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))))) {
2 7u83 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
      };
7 7u83 1542
      contop(b, 0, a2);
2 7u83 1543
      if (no (a) + aoff == 1) {	/* use inc */
1544
	if (sz == 8) {
7 7u83 1545
	  ins1(incb, sz, a2);
2 7u83 1546
	};
1547
	if (sz == 16) {
7 7u83 1548
	  ins1(incw, sz, a2);
2 7u83 1549
	};
1550
	if (sz == 32) {
7 7u83 1551
	  ins1(incl, sz, a2);
2 7u83 1552
	};
1553
      }
1554
      else {			/* use dec */
1555
	if (sz == 8) {
7 7u83 1556
	  ins1(decb, sz, a2);
2 7u83 1557
	};
1558
	if (sz == 16) {
7 7u83 1559
	  ins1(decw, sz, a2);
2 7u83 1560
	};
1561
	if (sz == 32) {
7 7u83 1562
	  ins1(decl, sz, a2);
2 7u83 1563
	};
1564
      };
7 7u83 1565
      invalidate_dest(dest);
1566
      end_contop();
1567
      try_overflow(sha, plus1);
2 7u83 1568
      son(a) = hold;
1569
      return;
1570
    };
1571
 
7 7u83 1572
    if (!inmem(a1) || !inmem(a2)) {
2 7u83 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;
7 7u83 1579
      if (inmem(a1))
1580
	contop(a, eq_where(reg0, a2), a2);
2 7u83 1581
      else
7 7u83 1582
	contop(b,
1583
	    (eq_where(reg0, a2) || eq_where(reg0, a1)), a2);
2 7u83 1584
      if (plus1)
7 7u83 1585
	ins0(stc);
2 7u83 1586
      if (sz == 8) {
7 7u83 1587
	ins2((plus1 ? adcb : addb), sz, sz, a1, a2);
2 7u83 1588
      };
1589
      if (sz == 16) {
7 7u83 1590
	ins2((plus1 ? adcw : addw), sz, sz, a1, a2);
2 7u83 1591
      };
1592
      if (sz == 32) {
7 7u83 1593
	ins2((plus1 ? adcl : addl), sz, sz, a1, a2);
2 7u83 1594
      };
1595
      if (sz == 64) {
1596
	where hi1, lo1, hi2, lo2;
1597
	lo2 = a2;
7 7u83 1598
	hi2 = (inmem(a2)? mw(b, a2.where_off + 32): reg1);
1599
	if (name(a) == val_tag) {
2 7u83 1600
	  int c, c1;
1601
	  if (!isbigval(a)) {
7 7u83 1602
	    c = no(a) + aoff;
1603
	    c1 = (is_signed(sha) && c < 0)? -1 : 0;
2 7u83 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
	  };
7 7u83 1612
	  lo1 = mw(zeroe, c);
1613
	  hi1 = mw(zeroe, c1);
2 7u83 1614
	}
1615
	else {
1616
	  lo1 = a1;
7 7u83 1617
	  hi1 = (inmem(a1)? mw(a, aoff + 32): reg1);
2 7u83 1618
	}
7 7u83 1619
	ins2((plus1 ? adcl : addl), 32, 32, lo1, lo2);
1620
 	ins2(adcl, 32, 32, hi1, hi2);
2 7u83 1621
      };
7 7u83 1622
      invalidate_dest(dest);
1623
      try_overflow(sha, plus1);
1624
      end_contop();
2 7u83 1625
      regsinuse = riu;
1626
      son(a) = holda;
1627
      son(b) = holdb;
1628
      return;
1629
    };
1630
 
7 7u83 1631
    move(sha, a1, reg0);
1632
    add_plus(sha, reg0, a2, a2, plus1);
1633
    invalidate_dest(dest);
2 7u83 1634
    return;
1635
  };
1636
 
7 7u83 1637
  if (name(a) == val_tag && !plus1 && !isbigval(a) && no(a) + aoff == 0) {
2 7u83 1638
    /* adding zero and moving */
1639
    cond1_set = 0;
7 7u83 1640
    move(sha, a2, dest);
2 7u83 1641
    return;
1642
  };
1643
 
7 7u83 1644
  if (name(b) == val_tag && !plus1 && !isbigval(b) && no(b) + boff == 0) {
2 7u83 1645
    /* adding zero and moving */
1646
    cond1_set = 0;
7 7u83 1647
    move(sha, a1, dest);
2 7u83 1648
    return;
1649
  };
1650
 
1651
  /* switch on memory position of a1, a2, dest */
7 7u83 1652
  switch ((inmem(a1) << 2) + (inmem(a2) << 1) + inmem(dest)) {
2 7u83 1653
    case 0:
1654
      {				/* none in memory */
1655
	exp ap;
1656
        int n;
1657
        if (overflow_e != nilexp || sz > 32)
1658
          {
7 7u83 1659
            move(sha, a2, dest);
1660
            add_plus(sha, a1, dest, dest, plus1);
2 7u83 1661
            return;
1662
          };
1663
	/* otherwise cannot be plus1 */
7 7u83 1664
	if (name(a) == val_tag) {
2 7u83 1665
	  if (name (b) == val_tag) {/* we know the answer */
1666
	    cond1_set = 0;
7 7u83 1667
	    move(sha, mw(zeroe,
1668
		    no(a) + no(b) + a1.where_off + a2.where_off),
2 7u83 1669
		    dest);
1670
	    return;
1671
	  };
1672
          if (name(sh(a)) == offsethd)
1673
            n = 1;
1674
          else
1675
            n = 8;
7 7u83 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,
2 7u83 1679
	        reff_tag);
1680
	    cond1_set = 0;
7 7u83 1681
	    ins2(leal, 32, 32, mw(ap, 0), dest);
1682
	    retcell(ap);
1683
	    invalidate_dest(dest);
2 7u83 1684
	    return;
1685
          }
1686
          else  {
1687
            move(sha, a2, dest);
1688
            add(sha, a1, dest, dest);
1689
            return;
1690
          };
1691
	};
7 7u83 1692
	if (name(b) == val_tag) {
2 7u83 1693
          if (name(sh(b)) == offsethd)
1694
            n = 1;
1695
          else
1696
            n = 8;
7 7u83 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,
2 7u83 1700
	        reff_tag);
1701
	    cond1_set = 0;
7 7u83 1702
	    ins2(leal, 32, 32, mw(ap, 0), dest);
1703
	    retcell(ap);
1704
	    invalidate_dest(dest);
2 7u83 1705
	    return;
1706
          }
1707
          else  {
1708
            move(sha, a1, dest);
1709
            add(sha, a2, dest, dest);
1710
            return;
1711
          };
1712
	};
7 7u83 1713
	ap = getexp(f_bottom, nilexp, 0, a, nilexp, 0, 0,
2 7u83 1714
	      addptr_tag);
1715
	{
1716
	  exp temp = bro(a);
7 7u83 1717
	  bro(a) = b;
2 7u83 1718
	  cond1_set = 0;
7 7u83 1719
	  ins2(leal, 32, 32, mw(ap, 0), dest);
1720
	  retcell(ap);
1721
          invalidate_dest(dest);
2 7u83 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 */
7 7u83 1731
      add_plus(sha, a1, a2, reg0, plus1);
1732
      move(sha, reg0, dest);
2 7u83 1733
      return;
1734
    case 2: 			/* a2 in memory others not */
7 7u83 1735
      if (eq_where(a1, reg0))
2 7u83 1736
	reg0_in_use = 1;
7 7u83 1737
      move(sha, a2, dest);
1738
      add_plus(sha, a1, dest, dest, plus1);
1739
      invalidate_dest(dest);
2 7u83 1740
      return;
1741
    case 4: 			/* a1 in memory others not */
7 7u83 1742
      if (eq_where(a2, reg0))
2 7u83 1743
	reg0_in_use = 1;
7 7u83 1744
      move(sha, a1, dest);
1745
      add_plus(sha, a2, dest, dest, plus1);
1746
      invalidate_dest(dest);
2 7u83 1747
      return;
1748
    default: 			/* case 6 a1 and a2 in memory, dest not */
7 7u83 1749
      move(sha, a2, reg0);
1750
      add_plus(sha, a1, reg0, reg0, plus1);
1751
      move(sha, reg0, dest);
2 7u83 1752
      return;
1753
  };
1754
}
1755
 
1756
 
1757
/* add values a1, a2 of shape sha and put them in dest */
1758
void add
7 7u83 1759
(shape sha, where a1, where a2, where dest)
2 7u83 1760
{
7 7u83 1761
  add_plus(sha, a1, a2, dest, 0);
2 7u83 1762
  return;
1763
}
1764
 
1765
 
1766
/* negate a1 in sup_dest then add a2 and put in dest */
1767
void inverted_sub
7 7u83 1768
(shape sha, where a1, where a2, where sup_dest, where dest)
2 7u83 1769
{
1770
  if (overflow_e == nilexp) {
7 7u83 1771
    negate(sha, a1, sup_dest);
1772
    add_plus(sha, a2, sup_dest, dest, 0);
2 7u83 1773
  }
1774
  else {
1775
    exp old_overflow_e = overflow_e;
1776
    overflow_e = nilexp;
7 7u83 1777
    not(sha, a1, sup_dest);
2 7u83 1778
    overflow_e = old_overflow_e;
7 7u83 1779
    add_plus(sha, a2, sup_dest, dest, 1);
2 7u83 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
7 7u83 1789
(shape sha, where a1, where a2, where dest)
2 7u83 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
 
7 7u83 1797
  if (name(a) == val_tag && name(sh(a)) == offsethd && al2(sh(a))!= 1) {
1798
    if (name(sha) == offsethd && al2(sha)!= 1)
2 7u83 1799
      no(a) = no(a) / 8;
1800
    sh(a) = slongsh;
1801
  };
7 7u83 1802
  if (name(b) == val_tag && name(sh(b)) == offsethd && al2(sh(b))!= 1) {
1803
    if (name(sha) == offsethd && al2(sha)!= 1)
2 7u83 1804
      no(b) = no(b) / 8;
1805
    sh(b) = slongsh;
1806
  };
1807
 
7 7u83 1808
  if (name(sha) & 1) {
2 7u83 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
 
7 7u83 1820
  if (eq_where(a2, dest) &&
2 7u83 1821
	(!keep_short || !flinmem(dest))) {
7 7u83 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))))) {
2 7u83 1825
      exp hold = son(b);
1826
      if (no (a) + aoff == 0) {	/* we didn't know the conditions */
1827
	cond1_set = 0;
1828
	return;
1829
      };
7 7u83 1830
      contop(b, 0, a2);
2 7u83 1831
      if (no (a) + aoff == 1) {	/* use dec */
1832
	if (sz == 8) {
7 7u83 1833
	  ins1(decb, sz, a2);
2 7u83 1834
	};
1835
	if (sz == 16) {
7 7u83 1836
	  ins1(decw, sz, a2);
2 7u83 1837
	};
1838
	if (sz == 32) {
7 7u83 1839
	  ins1(decl, sz, a2);
2 7u83 1840
	};
1841
      }
1842
      else {			/* use inc */
1843
	if (sz == 8) {
7 7u83 1844
	  ins1(incb, sz, a2);
2 7u83 1845
	};
1846
	if (sz == 16) {
7 7u83 1847
	  ins1(incw, sz, a2);
2 7u83 1848
	};
1849
	if (sz == 32) {
7 7u83 1850
	  ins1(incl, sz, a2);
2 7u83 1851
	};
1852
      };
7 7u83 1853
      invalidate_dest(dest);
1854
      end_contop();
1855
      try_overflow(sha, 0);
2 7u83 1856
      son(b) = hold;
1857
      return;
1858
    };
1859
 
7 7u83 1860
    if (!inmem(a1) || !inmem(a2)) {
2 7u83 1861
      int riu = regsinuse;
1862
      exp holda = son(a);
1863
      exp holdb = son(b);
1864
      if (sz == 64)
1865
	regsinuse |= 0x2;
7 7u83 1866
      if (inmem(a1))
1867
	contop(a, eq_where(reg0, a2), a2);
2 7u83 1868
      else
7 7u83 1869
	contop(b,
1870
	    (eq_where(reg0, a2) || eq_where(reg0, a1)), a2);
2 7u83 1871
      if (sz == 8) {
7 7u83 1872
	ins2(subb, sz, sz, a1, a2);
2 7u83 1873
      };
1874
      if (sz == 16) {
7 7u83 1875
	ins2(subw, sz, sz, a1, a2);
2 7u83 1876
      };
1877
      if (sz == 32) {
7 7u83 1878
	ins2(subl, sz, sz, a1, a2);
2 7u83 1879
      };
1880
      if (sz == 64) {
1881
	where hi1, lo1, hi2, lo2;
1882
	lo2 = a2;
7 7u83 1883
	hi2 = (inmem(a2)? mw(b, a2.where_off + 32): reg1);
1884
	if (name(a) == val_tag) {
2 7u83 1885
	  int c, c1;
1886
	  if (!isbigval(a)) {
7 7u83 1887
	    c = no(a) + aoff;
1888
	    c1 = (is_signed(sha) && c < 0)? -1 : 0;
2 7u83 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
	  };
7 7u83 1897
	  lo1 = mw(zeroe, c);
1898
	  hi1 = mw(zeroe, c1);
2 7u83 1899
	}
1900
	else {
1901
	  lo1 = a1;
7 7u83 1902
	  hi1 = (inmem(a1)? mw(a, aoff + 32): reg1);
2 7u83 1903
	}
7 7u83 1904
 	ins2(subl, 32, 32, lo1, lo2);
1905
 	ins2(sbbl, 32, 32, hi1, hi2);
2 7u83 1906
      };
7 7u83 1907
      invalidate_dest(dest);
1908
      end_contop();
2 7u83 1909
      regsinuse = riu;
7 7u83 1910
      try_overflow(sha, 0);
2 7u83 1911
      son(a) = holda;
1912
      son(b) = holdb;
1913
      return;
1914
    };
1915
 
7 7u83 1916
    move(sha, a1, reg0);
1917
    sub(sha, reg0, dest, dest);
1918
    invalidate_dest(dest);
2 7u83 1919
    return;
1920
  };
1921
 
7 7u83 1922
  if (name(a) == val_tag && !isbigval(a) && no(a) + aoff == 0) {
2 7u83 1923
    cond1_set = 0;
7 7u83 1924
    move(sha, a2, dest);
2 7u83 1925
    return;
1926
  };
1927
 
7 7u83 1928
  switch ((inmem(a1) << 2) + (inmem(a2) << 1) + inmem(dest)) {
2 7u83 1929
    case 0:
1930
    case 2: 			/* a2 may be in mem, others not */
7 7u83 1931
      if (!eq_where(a1, dest)) {
1932
	if (eq_where(a1, reg0))
2 7u83 1933
	  reg0_in_use = 1;
7 7u83 1934
	move(sha, a2, dest);
1935
	sub(sha, a1, dest, dest);
1936
	invalidate_dest(dest);
2 7u83 1937
	return;
1938
      };
7 7u83 1939
      if (eq_where(a1, reg0) || eq_where(a2, reg0)) {
1940
	if (eq_where(a2, reg0))
2 7u83 1941
	  reg0_in_use = 1;
7 7u83 1942
	inverted_sub(sha, a1, a2, dest, dest);
2 7u83 1943
	return;
1944
      };
7 7u83 1945
      inverted_sub(sha, a1, a2, reg0, dest);
2 7u83 1946
      return;
1947
    case 4:  			/* a1 in memory others not */
7 7u83 1948
      if (eq_where(dest, reg0)) {
1949
	move(sha, a2, reg0);
1950
	sub(sha, a1, reg0, reg0);
1951
	invalidate_dest(dest);
2 7u83 1952
	return;
1953
      };		/* else drop through */
1954
    case 1:
1955
    case 3:
1956
    case 5:
1957
    case 7: 			/* dest is in memory */
7 7u83 1958
      sub(sha, a1, a2, reg0);
1959
      move(sha, reg0, dest);
2 7u83 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 */
7 7u83 1964
      inverted_sub(sha, a1, a2, reg0, dest);
2 7u83 1965
      return;
1966
  };
1967
}
1968
 
1969
 
1970
/* put a negated into dest, shape sha */
1971
void negate
7 7u83 1972
(shape sha, where a, where dest)
2 7u83 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) {
7 7u83 1983
      ins1(negb, sz, dest);
1984
      invalidate_dest(dest);
2 7u83 1985
    };
1986
    if (sz == 16) {
7 7u83 1987
      ins1(negw, sz, dest);
1988
      invalidate_dest(dest);
2 7u83 1989
    };
1990
    if (sz == 32) {
7 7u83 1991
      ins1(negl, sz, dest);
1992
      invalidate_dest(dest);
2 7u83 1993
    };
1994
    if (sz == 64) {	/* must be reg0/1 */
7 7u83 1995
      move(slongsh, reg1, reg2);
1996
      move(slongsh, zero, reg1);
2 7u83 1997
      ins1(negl, 32, reg0);
1998
      ins2(sbbl, 32, 32, reg2, reg1);
7 7u83 1999
      try_overflow(sha, 0);
2000
      invalidate_dest(reg0);
2001
      invalidate_dest(reg1);
2002
      invalidate_dest(reg2);
2 7u83 2003
      return;
2004
    };
7 7u83 2005
    try_overflow(sha, 0);
2 7u83 2006
    return;
2007
  };
2008
 
7 7u83 2009
  if (!inmem(a) && name(a.where_exp)!= val_tag &&
2010
     (w_islastuse(a) || eq_where(a, reg0))) {
2 7u83 2011
    /* a is a register and no longer needed */
7 7u83 2012
    negate(sha, a, a);
2013
    move(sha, a, dest);
2 7u83 2014
    return;
2015
  };
2016
 
2017
  if (!inmem (dest)) {		/* dest is a register */
7 7u83 2018
    move(sha, a, dest);
2019
    negate(sha, dest, dest);
2020
    invalidate_dest(dest);
2 7u83 2021
    return;
2022
  };
2023
 
2024
  /* dest is in memory, a is either in memory or needed, it won't be reg0
2025
  */
7 7u83 2026
  move(sha, a, reg0);
2027
  negate(sha, reg0, reg0);
2028
  move(sha, reg0, dest);
2 7u83 2029
  return;
2030
}
2031
 
2032
/* put not(a) into dest, shape sha */
2033
void not
7 7u83 2034
(shape sha, where a, where dest)
2 7u83 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) {
7 7u83 2044
      ins1(notb, sz, dest);
2045
      invalidate_dest(dest);
2 7u83 2046
      return;
2047
    };
2048
    if (sz == 16) {
7 7u83 2049
      ins1(notw, sz, dest);
2050
      invalidate_dest(dest);
2 7u83 2051
      return;
2052
    };
2053
    if (sz == 32) {
7 7u83 2054
      ins1(notl, sz, dest);
2055
      invalidate_dest(dest);
2 7u83 2056
      return;
2057
    };
2058
    if (sz == 64) {	/* must be reg0/1 */
7 7u83 2059
      ins1(notl, 32, reg0);
2060
      ins1(notl, 32, reg1);
2061
      invalidate_dest(reg0);
2062
      invalidate_dest(reg1);
2 7u83 2063
      return;
2064
    };
2065
  };
2066
 
7 7u83 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);
2 7u83 2071
    return;
2072
  };
2073
 
2074
  if (!inmem (dest)) {		/* dest is a register */
7 7u83 2075
    move(sha, a, dest);
2076
    not(sha, dest, dest);
2077
    invalidate_dest(dest);
2 7u83 2078
    return;
2079
  };
2080
 
2081
  /* dest is in memory, a is either in memory or needed, it won't be reg0
2082
  */
7 7u83 2083
  move(sha, a, reg0);
2084
  not(sha, reg0, reg0);
2085
  move(sha, reg0, dest);
2 7u83 2086
  return;
2087
}
2088
 
2089
 
2090
 
2091
 
2092
/* floating register for e */
2093
int  in_fl_reg
7 7u83 2094
(exp e)
2 7u83 2095
{
7 7u83 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);
2 7u83 2100
  };
7 7u83 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);
2 7u83 2106
  };
7 7u83 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);
2 7u83 2112
  };
7 7u83 2113
  if (ne == ident_tag && ptno(e) == reg_pl) {
2114
    int  n = no(e);
2115
    return((n > 0x80)? n : 0);
2 7u83 2116
  };
7 7u83 2117
  return(0);
2 7u83 2118
}
2119
 
2120
 
2121
/* is e in the floating point stack top ? */
2122
int in_fstack
7 7u83 2123
(exp e)
2 7u83 2124
{
7 7u83 2125
  int  f = in_fl_reg(e);
2126
  int  fpos = (f)? get_reg_no(f): 0;
2127
  return(fpos == fstack_pos);
2 7u83 2128
}
2129
 
2130
 
2131
 
2132
/* is e in a register */
2133
int  in_reg
7 7u83 2134
(exp e)
2 7u83 2135
{
7 7u83 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)))
2 7u83 2140
      n = (n | (int)0x80000000);
7 7u83 2141
    return(n);
2 7u83 2142
  };
7 7u83 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))))
2 7u83 2148
      n = (n | (int)0x80000000);
7 7u83 2149
    return(n);
2 7u83 2150
  };
7 7u83 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))))
2 7u83 2156
      n = (n | (int)0x80000000);
7 7u83 2157
    return(n);
2 7u83 2158
  };
7 7u83 2159
  if (ne == ident_tag && ptno(e) == reg_pl) {
2160
    int  n = no(e);
2161
    if (!iscaonly(e) && isvar(e))
2 7u83 2162
      n = (n | (int)0x80000000);
7 7u83 2163
    return(n);
2 7u83 2164
  };
2165
  if (ne == current_env_tag)
7 7u83 2166
    return(0x40);
2167
  return(0);
2 7u83 2168
}
2169
 
2170
static int all_in_regs
7 7u83 2171
(exp e)
2 7u83 2172
{
2173
  exp id1, id2;
7 7u83 2174
  unsigned char  n = name(e);
2 7u83 2175
 
2176
  if ((n == cont_tag || n == ass_tag || n == reff_tag)
7 7u83 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);
2 7u83 2185
  };
2186
 
7 7u83 2187
  return(1);
2 7u83 2188
}
2189
 
2190
int two_contops
7 7u83 2191
(exp fe, exp te)
2 7u83 2192
{
7 7u83 2193
  int   nr = count_regs((~regsinuse) & 0x3e);
2 7u83 2194
  if (nr >= 2)
7 7u83 2195
    return(1);
2 7u83 2196
  if (nr == 1)
7 7u83 2197
    return(all_in_regs(fe) || all_in_regs(te));
2198
  return(all_in_regs(fe) && all_in_regs(te));
2 7u83 2199
}
2200
 
2201
 
2202
/* move value of shape sha from "from" to "to" */
2203
void move
7 7u83 2204
(shape sha, where from, where to)
2 7u83 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;
7 7u83 2214
  sz = rounder(shape_size(sha), 8);
2 7u83 2215
 
2216
 
2217
 
7 7u83 2218
  if (sz == 0 || eq_where(from, to))
2 7u83 2219
    return;
2220
 
2221
  /* move does not set conditions. Only clear if to spoils cond record */
2222
 
7 7u83 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)))) {
2 7u83 2229
    cond1_set = 0;
2230
    cond2_set = 0;
2231
  };
2232
 
2233
  if (name(fe) == reff_tag ||
2234
	(PIC_code && name(fe) == name_tag &&
7 7u83 2235
	  isglob(son(fe)) &&
2236
	 (name(sha) == offsethd) &&
2 7u83 2237
	  !brog(son(fe)) ->  dec_u.dec_val.extnamed))
2238
    {
2239
      mova(from, to);
2240
      return;
2241
    };
2242
 
7 7u83 2243
  if (name(sha) >= shrealhd && name(sha) <= doublehd) {
2 7u83 2244
    /* moving a float or double */
7 7u83 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;
2 7u83 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 && */
7 7u83 2255
	  use_pop_ass(to.where_exp, from.where_exp)!= 2) {
2 7u83 2256
	if (flinmem (to)) {	/* are going to pop the floating point
2257
				   stack */
2258
	  contop (te, 0, reg0);	/* compute address of to if necessary */
7 7u83 2259
	  if (name(sha) == shrealhd)
2260
	    ins1(fsts, 32, to);
2 7u83 2261
	  else
7 7u83 2262
	  if (name(sha) == realhd)
2263
	    ins1(fstl, 64, to);
2 7u83 2264
	  else {
7 7u83 2265
	    ins1(fstpt, 96, to);
2266
	    ins1(fldt, 96, to);
2 7u83 2267
	  };
7 7u83 2268
	  end_contop();
2 7u83 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)
7 7u83 2279
	move(sha, from, flstack);
2 7u83 2280
      /* push from into floating point stack */
2281
      if (flinmem (to)) {	/* store from fstack0 into memory and pop
2282
				*/
7 7u83 2283
	contop(te, 0, reg0);
2284
	if (name(sha) == shrealhd)
2285
	  ins1(fstps, 32, to);
2 7u83 2286
	else
7 7u83 2287
	if (name(sha) == realhd)
2288
	  ins1(fstpl, 64, to);
2 7u83 2289
	else
7 7u83 2290
	  ins1(fstpt, 96, to);
2 7u83 2291
	pop_fl;
7 7u83 2292
	end_contop();
2 7u83 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
    };
7 7u83 2304
    if (in_fl_reg(to.where_exp)) {
2 7u83 2305
      int fz;
7 7u83 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))) {
2 7u83 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 */
7 7u83 2319
	  if (name(sha) == shrealhd)
2320
	    ins1(flds, 32, from);
2 7u83 2321
	  else
7 7u83 2322
	  if (name(sha) == realhd)
2323
	    ins1(fldl, 64, from);
2 7u83 2324
	  else
7 7u83 2325
	    ins1(fldt, 96, from);
2326
	  end_contop();
2 7u83 2327
	}
2328
	else {
2329
	  if (f1pos == fstack_pos) {/* push fstack0 */
7 7u83 2330
	    load_stack0();
2 7u83 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 ) */
7 7u83 2338
	contop(te, 0, reg0);
2339
	if (name(sha) == shrealhd)
2340
	  ins1(fstps, 32, to);
2 7u83 2341
	else
7 7u83 2342
	if (name(sha) == realhd)
2343
	  ins1(fstpl, 64, to);
2 7u83 2344
	else
7 7u83 2345
	  ins1(fstpt, 96, to);
2 7u83 2346
	pop_fl;
7 7u83 2347
	end_contop();
2 7u83 2348
	son(fe) = holdfe;
2349
	son(te) = holdte;
2350
	return;
2351
      };
2352
 
7 7u83 2353
      f2 = in_fl_reg(to.where_exp);
2354
      f2pos = get_reg_no(f2);
2 7u83 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) {
7 7u83 2389
      reg_w = equiv_reg(from, sz);
2 7u83 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)) {
7 7u83 2404
	  c = no(fe) + from.where_off;
2405
	  c1 = (name(sha) == s64hd && c < 0)? -1 : 0;
2 7u83 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
	}
7 7u83 2414
	ins1(pushl, 32, mw(zeroe, c1));
2 7u83 2415
#ifdef NEWDWARF
2416
	if (diagnose && dwarf2 && no_frame)
2417
	  dw2_track_push();
2418
#endif
2419
 
7 7u83 2420
	ins1(pushl, 32, mw(zeroe, c));
2 7u83 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
      }
7 7u83 2430
      move(sha, from, reg0);
2431
      ins0(pushedx);
2 7u83 2432
#ifdef NEWDWARF
2433
      if (diagnose && dwarf2 && no_frame)
2434
	dw2_track_push();
2435
#endif
2436
 
7 7u83 2437
      ins0(pusheax);
2 7u83 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 ||
7 7u83 2448
        (is80486 && inmem(from))) {
2449
      move(sha, from, reg0);
2450
      ins1(pushl, 32, reg0);
2 7u83 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
    };
7 7u83 2460
    contop(from.where_exp, 0, reg0);
2461
    ins1(pushl, sz, from);
2 7u83 2462
#ifdef NEWDWARF
2463
    if (diagnose && dwarf2 && no_frame)
2464
      dw2_track_push();
2465
#endif
2466
 
7 7u83 2467
    end_contop();
2 7u83 2468
    son(fe) = holdfe;
2469
    son(te) = holdte;
2470
    return;
2471
  };
2472
 
2473
 
7 7u83 2474
  if (inmem(from) && inmem(to) && ((sz <= 32 && sz != 24)
2 7u83 2475
				|| name(sha) == u64hd || name(sha) == s64hd)) {
2476
    /* from and to are both in memory */
7 7u83 2477
    move(sha, from, reg0);
2478
    move(sha, reg0, to);
2 7u83 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)) {
7 7u83 2501
      c = no(fe) + from.where_off;
2 7u83 2502
      if (sz == 64)
7 7u83 2503
	c1 = (name(sha) == s64hd && c < 0)? -1 : 0;
2 7u83 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
 
7 7u83 2521
    contop(te, 0, to);
2 7u83 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;
7 7u83 2527
      ins2(xorl, 32, 32, to, to);
2528
      invalidate_dest(to);
2529
      end_contop();
2 7u83 2530
      son(fe) = holdfe;
2531
      son(te) = holdte;
2532
      return;
2533
    };
2534
 
2535
    /* use fastest operation for each size of constant */
2536
 
7 7u83 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();
2 7u83 2541
      son(fe) = holdfe;
2542
      son(te) = holdte;
2543
      return;
2544
    };
2545
 
2546
    if (sz == 16) {
7 7u83 2547
      ins2(movw, sz, sz, mw(zeroe,(c & 0xffff)), to);
2548
      invalidate_dest(to);
2549
      end_contop();
2 7u83 2550
      son(fe) = holdfe;
2551
      son(te) = holdte;
2552
      return;
2553
    };
2554
 
2555
    if (sz == 64) {
7 7u83 2556
      if (eq_where(to, reg0)) {
2 7u83 2557
	if (c == 0)
7 7u83 2558
	  ins2(xorl, 32, 32, reg0, reg0);
2 7u83 2559
	else
7 7u83 2560
	  ins2(movl, 32, 32, mw(zeroe, c), reg0);
2 7u83 2561
	if (c1 == 0)
7 7u83 2562
	  ins2(xorl, 32, 32, reg1, reg1);
2 7u83 2563
	else
7 7u83 2564
	  ins2(movl, 32, 32, mw(zeroe, c1), reg1);
2565
	invalidate_dest(reg0);
2566
	invalidate_dest(reg1);
2 7u83 2567
      }
2568
      else {
7 7u83 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);
2 7u83 2572
      }
7 7u83 2573
      end_contop();
2 7u83 2574
      son(fe) = holdfe;
2575
      son(te) = holdte;
2576
      return;
2577
    }
2578
 
2579
    if (inmem(to) && (c == 0 &&
7 7u83 2580
	((name(te) == ass_tag && name(son(te)) == name_tag &&
2 7u83 2581
		isvar(son(son(te)))) ||
2582
		(name(te) == ident_tag)))) {
7 7u83 2583
      reg_w = equiv_reg(from, sz);
2 7u83 2584
      if (reg_w.where_exp != nilexp)
7 7u83 2585
	move(sha, reg_w, to);
2 7u83 2586
      else {
2587
        move(slongsh, from, reg0);
2588
        move(slongsh, reg0, to);
2589
        move_reg(from, reg0, sha);
2590
      };
2591
    }
2592
    else {
7 7u83 2593
      ins2(movl, 32, 32, from, to);
2 7u83 2594
    }
2595
 
7 7u83 2596
    invalidate_dest(to);
2597
    end_contop();
2 7u83 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 */
7 7u83 2608
    if (!inmem(from) &&
2609
	(in_reg(from.where_exp) & 0x70)) {
2610
      if (!inmem(to)) {
2611
	move(slongsh, from, to);
2 7u83 2612
	son(fe) = holdfe;
2613
	son(te) = holdte;
2614
	return;
2615
      };
7 7u83 2616
      move(slongsh, from, reg0);
2617
      move(sha, reg0, to);
2 7u83 2618
      son(fe) = holdfe;
2619
      son(te) = holdte;
2620
      return;
2621
    };
2622
 
7 7u83 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);
2 7u83 2627
	son(fe) = holdfe;
2628
	son(te) = holdte;
2629
	return;
2630
      };
7 7u83 2631
      move(sha, from, reg0);
2632
      move(slongsh, reg0, to);
2 7u83 2633
      son(fe) = holdfe;
2634
      son(te) = holdte;
2635
      return;
2636
    };
2637
 
7 7u83 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();
2 7u83 2644
    }
2645
    else {
7 7u83 2646
      reg_w = equiv_reg(from, sz);
2 7u83 2647
      if (reg_w.where_exp != nilexp) {
7 7u83 2648
	move(sha, reg_w, to);
2649
	move_reg(from, to, sha);
2 7u83 2650
      }
2651
      else {
7 7u83 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();
2 7u83 2657
      };
2658
    };
2659
    son(fe) = holdfe;
2660
    son(te) = holdte;
2661
    return;
2662
  };
2663
  if (sz == 16) {		/* moving 16 bits */
7 7u83 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();
2 7u83 2670
    }
2671
    else {
7 7u83 2672
      reg_w = equiv_reg(from, sz);
2 7u83 2673
      if (reg_w.where_exp != nilexp) {
7 7u83 2674
	move(sha, reg_w, to);
2675
	move_reg(from, to, sha);
2 7u83 2676
      }
2677
      else {
7 7u83 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();
2 7u83 2683
      };
2684
    };
2685
    son(fe) = holdfe;
2686
    son(te) = holdte;
2687
    return;
2688
  };
2689
  if (sz == 32) {		/* moving 32 bits */
2690
 
7 7u83 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();
2 7u83 2697
    }
2698
    else {
7 7u83 2699
      reg_w = equiv_reg(from, sz);
2 7u83 2700
      if (reg_w.where_exp != nilexp) {
7 7u83 2701
	move(sha, reg_w, to);
2702
	move_reg(from, to, sha);
2 7u83 2703
      }
2704
      else {
7 7u83 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();
2 7u83 2710
      };
2711
    };
2712
    son(fe) = holdfe;
2713
    son(te) = holdte;
2714
    return;
2715
  };
2716
 
7 7u83 2717
  if (sz == 64 && (eq_where(to, reg0) || eq_where(from, reg0))) {
2 7u83 2718
				/* moving reg0 & reg1 to or from memory */
2719
    where w1;
2720
    int riu = regsinuse;
7 7u83 2721
    if (!eq_where(from, reg0)) {
2 7u83 2722
      regsinuse |= 0x2;
7 7u83 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();
2 7u83 2730
    }
2731
    else
7 7u83 2732
    if (!eq_where(to, reg0)) {
2 7u83 2733
      regsinuse |= 0x2;
7 7u83 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();
2 7u83 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)) {
7 7u83 2748
     if ((regsinuse & 0x7e)!= 0x7e) {
2 7u83 2749
        int  foff = from.where_off;
2750
        int  toff = to.where_off;
2751
        int  old_regsinuse = regsinuse;
2752
        where extra_reg;
2753
 
7 7u83 2754
        contop(fe, 1, to);
2 7u83 2755
        regsinuse = top_regsinuse;
2756
        contop_level++;
2757
        reg0_in_use = 1;
7 7u83 2758
        contop(te, 1, to);
2 7u83 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
	};
7 7u83 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));
2 7u83 2793
	invalidate_dest(reg0);
2794
	invalidate_dest(extra_reg);
2795
	invalidate_dest(to);
7 7u83 2796
        end_contop();
2 7u83 2797
        contop_level--;
7 7u83 2798
        end_contop();
2 7u83 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
 
7 7u83 2810
  if (sz <= (40 * 8) && two_contops(fe, te)) {
2 7u83 2811
    int  i;
2812
    int  foff = from.where_off;
2813
    int  toff = to.where_off;
2814
    int  old_regsinuse = regsinuse;
2815
 
2816
 
7 7u83 2817
    contop(fe, 1, to);
2 7u83 2818
    regsinuse = top_regsinuse;
2819
    contop_level++;
2820
    reg0_in_use = 1;
7 7u83 2821
    contop(te, 1, to);
2 7u83 2822
    regsinuse = old_regsinuse;
2823
 
2824
    /* use movl as far as possible */
2825
    for (i = 0; i <= (sz - 32); i = i + 32) {
7 7u83 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));
2 7u83 2829
    };
2830
    if (i == sz) {
7 7u83 2831
      invalidate_dest(reg0);
2832
      end_contop();
2 7u83 2833
      contop_level--;
7 7u83 2834
      end_contop();
2 7u83 2835
      son(fe) = holdfe;
2836
      son(te) = holdte;
2837
      return;
2838
    };
2839
    /* move final word and byte if necessary */
2840
    if ((sz - i) >= 16) {
7 7u83 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));
2 7u83 2844
      i += 16;
2845
    };
2846
    if ((sz - i) >= 8) {
7 7u83 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));
2 7u83 2850
    };
7 7u83 2851
    invalidate_dest(reg0);
2852
    end_contop();
2 7u83 2853
    contop_level--;
7 7u83 2854
    end_contop();
2 7u83 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;
7 7u83 2873
      ins0(pushesi);
2 7u83 2874
#ifdef NEWDWARF
2875
      if (diagnose && dwarf2 && no_frame)
2876
	dw2_track_push();
2877
#endif
2878
    };
2879
    if (regsinuse & 0x10) {
2880
      extra_stack += 32;
7 7u83 2881
      ins0(pushedi);
2 7u83 2882
#ifdef NEWDWARF
2883
      if (diagnose && dwarf2 && no_frame)
2884
	dw2_track_push();
2885
#endif
2886
    };
2887
    if (regsinuse & 0x4) {
2888
      extra_stack += 32;
7 7u83 2889
      ins0(pushecx);
2 7u83 2890
#ifdef NEWDWARF
2891
      if (diagnose && dwarf2 && no_frame)
2892
	dw2_track_push();
2893
#endif
2894
    };
2895
    old_regsinuse = regsinuse;
2896
    if (regsinuse & 0x20) {
7 7u83 2897
      mova(from, pushdest);
2 7u83 2898
      extra_stack += 32;
2899
    }
2900
    else {
7 7u83 2901
      mova(from, reg5);
2 7u83 2902
      regsinuse |= 0x20;
2903
    };
2904
 
7 7u83 2905
    mova(to, reg4);
2 7u83 2906
    regsinuse = old_regsinuse;
2907
 
7 7u83 2908
    move(slongsh, mw(zeroe,(sz / 32)), reg2);
2 7u83 2909
 
2910
    if (regsinuse & 0x20) {
7 7u83 2911
      ins0(popesi);
2 7u83 2912
#ifdef NEWDWARF
2913
      if (diagnose && dwarf2 && no_frame)
2914
	dw2_track_pop();
2915
#endif
2916
    }
7 7u83 2917
    ins0(rep);
2918
    ins0(movsl);
2 7u83 2919
 
2920
    /* and move the last word and byte if necessary */
2921
    sz = sz % 32;
2922
    if (sz >= 16) {
7 7u83 2923
      ins0(movsw);
2 7u83 2924
      sz -= 16;
2925
    };
2926
    if (sz == 8)
7 7u83 2927
      ins0(movsb);
2 7u83 2928
 
2929
 
7 7u83 2930
    invalidate_dest(reg2);
2931
    invalidate_dest(reg4);
2932
    invalidate_dest(reg5);
2 7u83 2933
    if (regsinuse & 0x4) {
7 7u83 2934
      ins0(popecx);
2 7u83 2935
#ifdef NEWDWARF
2936
      if (diagnose && dwarf2 && no_frame)
2937
	dw2_track_pop();
2938
#endif
2939
    };
2940
    if (regsinuse & 0x10) {
7 7u83 2941
      ins0(popedi);
2 7u83 2942
#ifdef NEWDWARF
2943
      if (diagnose && dwarf2 && no_frame)
2944
	dw2_track_pop();
2945
#endif
2946
    };
2947
    if (regsinuse & 0x20) {
7 7u83 2948
      ins0(popesi);
2 7u83 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;
7 7u83 2957
    invalidate_dest(to);
2 7u83 2958
    son(fe) = holdfe;
2959
    son(te) = holdte;
2960
    return;
2961
  };
2962
}
2963
 
2964
/* use rep movsb */
2965
void movecont
7 7u83 2966
(where from, where to, where length, int nooverlap)
2 7u83 2967
{
2968
  if (nooverlap) {
2969
    int  old_extra_stack = extra_stack;
2970
    if (regsinuse & 0x20) {
2971
      extra_stack += 32;
7 7u83 2972
      ins0(pushesi);
2 7u83 2973
#ifdef NEWDWARF
2974
      if (diagnose && dwarf2 && no_frame)
2975
	dw2_track_push();
2976
#endif
2977
    }
2978
    if (regsinuse & 0x10) {
2979
      extra_stack += 32;
7 7u83 2980
      ins0(pushedi);
2 7u83 2981
#ifdef NEWDWARF
2982
      if (diagnose && dwarf2 && no_frame)
2983
	dw2_track_push();
2984
#endif
2985
    }
7 7u83 2986
    ins0(pushecx);
2 7u83 2987
#ifdef NEWDWARF
2988
    if (diagnose && dwarf2 && no_frame)
2989
      dw2_track_push();
2990
#endif
2991
    extra_stack += 32;
7 7u83 2992
    move(sh(from.where_exp), from, pushdest);
2 7u83 2993
    extra_stack += 32;
7 7u83 2994
    move(sh(to.where_exp), to, pushdest);
2 7u83 2995
    extra_stack += 32;
7 7u83 2996
    move(sh(length.where_exp), length, pushdest);
2997
    ins0(popecx);
2 7u83 2998
#ifdef NEWDWARF
2999
    if (diagnose && dwarf2 && no_frame)
3000
      dw2_track_pop();
3001
#endif
7 7u83 3002
    ins0(popedi);
2 7u83 3003
#ifdef NEWDWARF
3004
    if (diagnose && dwarf2 && no_frame)
3005
      dw2_track_pop();
3006
#endif
7 7u83 3007
    ins0(popesi);
2 7u83 3008
#ifdef NEWDWARF
3009
    if (diagnose && dwarf2 && no_frame)
3010
      dw2_track_pop();
3011
#endif
7 7u83 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);
2 7u83 3021
#ifdef NEWDWARF
3022
    if (diagnose && dwarf2 && no_frame)
3023
      dw2_track_pop();
3024
#endif
3025
    if (regsinuse & 0x10) {
7 7u83 3026
      ins0(popedi);
2 7u83 3027
#ifdef NEWDWARF
3028
      if (diagnose && dwarf2 && no_frame)
3029
	dw2_track_pop();
3030
#endif
3031
    }
3032
    if (regsinuse & 0x20) {
7 7u83 3033
      ins0(popesi);
2 7u83 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;
7 7u83 3042
    invalidate_dest(reg0);
3043
    invalidate_dest(reg2);
3044
    invalidate_dest(to);
2 7u83 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)
7 7u83 3053
      name_memmove = make_extn("memmove", f_proc, 0);
2 7u83 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
7 7u83 3069
(void)
2 7u83 3070
{
3071
		/* leave proc, discarding any callee parameters */
3072
		/* can overwrite %ecx */
7 7u83 3073
  int n = (remove_struct_ref && has_struct_res(crt_proc_exp))? 32 : 0;
2 7u83 3074
  if (callee_size >= 0) {
3075
    if ((n += callee_size) == 0)
7 7u83 3076
      ins0(ret);
2 7u83 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)
7 7u83 3084
      add(slongsh, mw(zeroe, n/8), sp, sp);
3085
    ins0("jmp *%ecx");
2 7u83 3086
  }
3087
  return;
3088
}
3089
 
3090
void stack_return
7 7u83 3091
(int longs)
2 7u83 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
   };
7 7u83 3147
  add(slongsh, mw(zeroe,(longs / 8)), sp, sp);
2 7u83 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
7 7u83 3158
(int longs, exp fn, int ret_stack_dec)
2 7u83 3159
{
3160
  cond1_set = 0;
3161
  cond2_set = 0;
7 7u83 3162
  if (name(fn) == name_tag && !isvar(son(fn)) && isglob(son(fn))) {
3163
    exp ind = getexp(f_proc, nilexp, 0, fn, nilexp, 0,
2 7u83 3164
	0, cont_tag);
3165
#ifdef NEWDWARF
3166
    if (current_dg_info) {
7 7u83 3167
      current_dg_info->data.i_call.brk = set_dw_text_label();
2 7u83 3168
      current_dg_info->data.i_call.p.k = WH_STR;
7 7u83 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;
2 7u83 3171
    }
3172
#endif
7 7u83 3173
    ins1(call, 32, mw(ind, 0));
3174
    retcell(ind);
2 7u83 3175
  }
3176
  else {
7 7u83 3177
    if (inmem(mw(fn, 0))) {
3178
      move(slongsh, mw(fn, 0), reg0);
2 7u83 3179
      fn = reg0.where_exp;
3180
    };
3181
#ifdef NEWDWARF
3182
    if (current_dg_info) {
3183
      int rn;
7 7u83 3184
      if (name(fn) ==name_tag && !isvar(son(fn)))
2 7u83 3185
	rn = no(son(fn));
3186
      else
7 7u83 3187
      if (name(fn) ==cont_tag && name(son(fn)) ==name_tag &&
2 7u83 3188
		isvar(son(son(fn))))
3189
	rn = no(son(son(fn)));
3190
      else {
7 7u83 3191
	failer("where?");
2 7u83 3192
	rn = 1;
3193
      }
7 7u83 3194
      current_dg_info->data.i_call.brk = set_dw_text_label();
2 7u83 3195
      current_dg_info->data.i_call.p.k = WH_REG;
7 7u83 3196
      current_dg_info->data.i_call.p.u.l = get_reg_no(rn);
2 7u83 3197
    }
3198
#endif
7 7u83 3199
    ins1ind(call, 32, mw(fn, 0));
2 7u83 3200
  };
3201
  stack_dec = ret_stack_dec;
3202
#ifdef NEWDWARF
7 7u83 3203
  START_BB();
2 7u83 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
7 7u83 3214
(exp lab)
2 7u83 3215
{
7 7u83 3216
    if (inmem(mw(lab, 0))) {
3217
      move(slongsh, mw(lab, 0), reg0);
2 7u83 3218
      lab = reg0.where_exp;
3219
    };
7 7u83 3220
    ins1ind(jmp, 32, mw(lab, 0));
2 7u83 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
7 7u83 3234
(shape sha, where from, where min, int nt, exp e)
2 7u83 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 &&
7 7u83 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)
2 7u83 3254
    return 1;			/* we are comparing the value from which
3255
				   the conditions are set with zero */
3256
 
3257
  if (cond2_set &&
7 7u83 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))
2 7u83 3262
    return 0;			/* we are repeating the previous
3263
				   comparison */
3264
 
3265
 
7 7u83 3266
  if (!is_floating(name(sha))) {
2 7u83 3267
    where orig_min;
3268
    orig_min = min;
7 7u83 3269
    has_equiv_from = equiv_reg(from, sz);
2 7u83 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 &&
7 7u83 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)
2 7u83 3287
      return 1;			/* we are comparing the value from which
3288
				   the conditions are set with zero */
3289
 
3290
    if (cond2_set &&
7 7u83 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))
2 7u83 3295
      return 0;			/* we are repeating the previous
3296
				   comparison */
3297
 
3298
    if (((name(min.where_exp) == null_tag && no(min.where_exp) == 0)
7 7u83 3299
	 || eq_where(min, zero)) &&
3300
	!inmem(from)) {
2 7u83 3301
				/* min is zero */
3302
 
3303
      cond1_set = 1;
3304
      cond2_set = 0;
3305
      cond1 = from;
3306
 
3307
 
3308
      if (sz == 8) {
7 7u83 3309
	ins2(testb, sz, sz, from, from);
2 7u83 3310
	return 0;
3311
      };
3312
      if (sz == 16) {
7 7u83 3313
	ins2(testw, sz, sz, from, from);
2 7u83 3314
	return 0;
3315
      };
3316
      if (sz == 32) {
7 7u83 3317
	ins2(testl, sz, sz, from, from);
2 7u83 3318
	return 0;
3319
      };
3320
      if (sz == 64) {	/* !inmem, so from must be reg0/reg1 */
3321
	if (nt >= 5) {
7 7u83 3322
	  ins2(orl, 32, 32, reg1, reg0);
3323
	  invalidate_dest(reg0);
2 7u83 3324
	  cond1_set = 0;
3325
	  return 0;
3326
	}
3327
	else
3328
	if (nt == f_less_than || nt == f_greater_than_or_equal) {
7 7u83 3329
	  ins2(testl, 32, 32, reg1, reg1);
2 7u83 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 &&
7 7u83 3344
       ((name(from.where_exp) == null_tag && no(from.where_exp) == 0) ||
3345
		 eq_where(from, zero)) &&
3346
        !inmem(min)) {
2 7u83 3347
      /* from is zero and the test is == or != so we don't have to reverse
3348
         its sense */
3349
 
3350
      if (sz == 8) {
7 7u83 3351
	ins2(testb, sz, sz, min, min);
2 7u83 3352
	return 0;
3353
      };
3354
      if (sz == 16) {
7 7u83 3355
	ins2(testw, sz, sz, min, min);
2 7u83 3356
	return 0;
3357
      };
3358
      if (sz == 32) {
7 7u83 3359
	ins2(testl, sz, sz, min, min);
2 7u83 3360
	return 0;
3361
      };
3362
      if (sz == 64) {	/* !inmem, so min must be reg0/reg1 */
7 7u83 3363
	ins2(orl, 32, 32, reg1, reg0);
3364
	invalidate_dest(reg0);
2 7u83 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) &&
7 7u83 3373
        inmem(from) && has_equiv_from.where_exp == nilexp) {
2 7u83 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
 
7 7u83 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 &&
2 7u83 3406
	    name(son(from.where_exp)) == name_tag &&
3407
	    !isvar(son(son(from.where_exp))))) {
7 7u83 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) &&
2 7u83 3414
              !brog(son(from.where_exp)) ->  dec_u.dec_val.extnamed))) ||
3415
	      name(from.where_exp) == reff_tag)
7 7u83 3416
	  mova(from, reg0);
2 7u83 3417
	else
7 7u83 3418
	  move(sha, from, reg0);
2 7u83 3419
	son(from.where_exp) = hold_from;
3420
	from = reg0;
3421
	hold_from = son(from.where_exp);
3422
      }
3423
      else {
7 7u83 3424
	if (inmem(from)) {
2 7u83 3425
	  if (sz == 64)
3426
	    regsinuse |= 0x2;
7 7u83 3427
	  contop(from.where_exp, eq_where(reg0, min), reg0);
2 7u83 3428
	  contop_done = 1;
3429
	};
3430
      };
3431
 
3432
      if ((name(min.where_exp) == val_tag || name(min.where_exp) == env_offset_tag) &&
7 7u83 3433
           ((name(from.where_exp) == val_tag || name(from.where_exp) == env_offset_tag) ||
3434
		(keep_short && inmem(from)))) {
3435
        move(sha, from, reg0);
2 7u83 3436
	son(from.where_exp) = hold_from;
3437
        from = reg0;
3438
	hold_from = son(from.where_exp);
3439
      };
3440
 
7 7u83 3441
      if (eq_where(from, reg0) && eq_where(min, reg0)
3442
				&& !eq_where(orig_min, reg0)) {
2 7u83 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;
7 7u83 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) &&
2 7u83 3453
             !brog(son(me)) ->  dec_u.dec_val.extnamed) ||
7 7u83 3454
	  (name(me) == reff_tag && name(son(me)) == name_tag &&
3455
	    !isvar(son(son(me))))) {
3456
	if (eq_where(from, reg0)) {
2 7u83 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;
7 7u83 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);
2 7u83 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
	};
7 7u83 3478
	mova(min, reg0);
2 7u83 3479
	son(min.where_exp) = hold_min;
3480
	min = reg0;
3481
	hold_min = son(min.where_exp);
3482
     }
3483
      else {
7 7u83 3484
	if (inmem(min)) {
2 7u83 3485
	  if (sz == 64)
3486
	    regsinuse |= 0x2;
7 7u83 3487
	  contop(min.where_exp, eq_where(reg0, from), reg0);
2 7u83 3488
	  contop_done = 1;
3489
	};
3490
      };
3491
 
7 7u83 3492
      if (sz == 8 && (eq_where(min, reg4) || eq_where(min, reg5))) {
3493
	if (!eq_where(from, reg0)) {
3494
	  move(sha, min, reg0);
2 7u83 3495
	  son(min.where_exp) = hold_min;
3496
	  min = reg0;
3497
	  hold_min = son(min.where_exp);
3498
	}
3499
	else {
7 7u83 3500
	  sub(sha, min, reg0, reg0);
2 7u83 3501
	  if (contop_done)
7 7u83 3502
	    end_contop();
2 7u83 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)
7 7u83 3512
	  end_contop();
2 7u83 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;
7 7u83 3520
	if (eq_where(from, reg0)) {
2 7u83 3521
	  fromlo = reg0;
3522
	  fromhi = reg1;
3523
	}
3524
	else {
3525
	  fromlo = from;
7 7u83 3526
	  fromhi = mw(from.where_exp, from.where_off + 32);
2 7u83 3527
	}
7 7u83 3528
	if (eq_where(min, reg0)) {
2 7u83 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);
7 7u83 3537
	    c1 = (is_signed(sha) && c < 0)? -1 : 0;
2 7u83 3538
	    if (c == 0 && (nt == f_greater_than_or_equal || nt == f_less_than)) {
3539
				/* sign bit says it all, so ignore fromlo */
7 7u83 3540
	      ins2(cmpl, 32, 32, zero, fromhi);
2 7u83 3541
	      if (contop_done)
7 7u83 3542
		end_contop();
2 7u83 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
	  }
7 7u83 3556
	  minlo = mw(zeroe, c);
3557
	  minhi = mw(zeroe, c1);
2 7u83 3558
	}
3559
	else {
3560
	  minlo = min;
7 7u83 3561
	  minhi = mw(min.where_exp, min.where_off + 32);
2 7u83 3562
	}
3563
	if (nt >= 5 || !is_signed(sha)) {
7 7u83 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);
2 7u83 3569
	  if (contop_done)
7 7u83 3570
	    end_contop();
2 7u83 3571
	  regsinuse = riu;
3572
	  son(from.where_exp) = hold_from;
3573
	  son(min.where_exp) = hold_min;
3574
	  return 0;
3575
	}
7 7u83 3576
	cmp_64hilab = next_lab();
3577
	ins2(cmpl, 32, 32, minhi, fromhi);
2 7u83 3578
	cmp64_contop (contop_done);	/* if hi unequal, undo contop and jump to cmp_64hilab */
7 7u83 3579
	ins2(cmpl, 32, 32, minlo, fromlo);
2 7u83 3580
        if (contop_done)
7 7u83 3581
	  end_contop();
2 7u83 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
7 7u83 3603
(where from)
2 7u83 3604
{
7 7u83 3605
    return(!inmem(from) && name(from.where_exp)!= val_tag &&
3606
	(in_reg(from.where_exp) & 0x70));
2 7u83 3607
}
3608
 
3609
/* change variety from (which has shape
3610
   fsh) to sha, and put in to */
3611
void change_var_sh
7 7u83 3612
(shape sha, shape fsh, where from, where to)
2 7u83 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 */
7 7u83 3628
  switch (name(sha)) {
2 7u83 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);
7 7u83 3660
      sha = (sgt)? slongsh: ulongsh;
2 7u83 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)) {
7 7u83 3671
      val = dochvar(no(fe), sha);
3672
      if (overflow_e != nilexp && (dochvar(no(fe), fsh)!= val || (val < 0 &&
2 7u83 3673
		((szt == 32 && (sgt != sgf)) || (szt == 64 && !sgt && sgf)))))
7 7u83 3674
	do_exception();
3675
      no(fe) = val;
2 7u83 3676
    }
3677
    else {
3678
      flt64 x;
3679
      int ov;
3680
      x = flt_to_f64(no(fe), sgf, &ov);
7 7u83 3681
      val = dochvar((int)(x.small), sha);
2 7u83 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)))
7 7u83 3687
	do_exception();
2 7u83 3688
      if (szt != 64) {
7 7u83 3689
	no(fe) = val;
3690
	clearbigval(fe);
2 7u83 3691
      }
3692
    };
7 7u83 3693
    sh(fe) = sha;
3694
    move(sha, from, to);
2 7u83 3695
    return;
3696
  };
3697
 
3698
 
3699
  if (name(fsh) == bitfhd) {
3700
    if (szf < 8) {
3701
      if (sgf && !sgt) {
7 7u83 3702
	and(scharsh, from, mw(zeroe,(1 << szf) - 1), reg0);
2 7u83 3703
	from = reg0;
3704
      }
3705
      szf = 8;
7 7u83 3706
      fsh = (sgf)? scharsh : ucharsh;
2 7u83 3707
    }
3708
    else
3709
    if (szf < 16) {
3710
      if (sgf && !sgt) {
7 7u83 3711
	and(swordsh, from, mw(zeroe,(1 << szf) - 1), reg0);
2 7u83 3712
	from = reg0;
3713
      }
3714
      szf = 16;
7 7u83 3715
      fsh = (sgf)? swordsh : uwordsh;
2 7u83 3716
    }
3717
    else
3718
    if (szf < 32) {
3719
      if (sgf && !sgt) {
7 7u83 3720
	and(slongsh, from, mw(zeroe,(1 << szf) - 1), reg0);
2 7u83 3721
	from = reg0;
3722
      }
3723
      szf = 32;
7 7u83 3724
      fsh = (sgf)? slongsh : ulongsh;
2 7u83 3725
    }
3726
  }
3727
 
3728
  if (overflow_e != nilexp && (sgt < sgf || (szt - sgt) < (szf - sgf))) {
7 7u83 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;
2 7u83 3732
    if (inmem(from)) {
7 7u83 3733
      move(fsh, from, reg0);
2 7u83 3734
      from = reg0;
3735
    };
3736
    if (szf == 64) {
3737
      if (szt == 64) {
7 7u83 3738
	IGNORE cmp(slongsh, reg1, zero, f_greater_than_or_equal, nilexp);
3739
	test_exception(f_greater_than_or_equal, slongsh);
2 7u83 3740
      }
3741
      else {
3742
	int lab1;
7 7u83 3743
	IGNORE cmp(slongsh, reg1, zero, f_equal, nilexp);
2 7u83 3744
	if (sgf && sgt) {
7 7u83 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);
2 7u83 3754
	}
3755
	else
7 7u83 3756
	  test_exception(f_equal, slongsh);
2 7u83 3757
	if (szt != 32 || sgt) {
7 7u83 3758
	  IGNORE cmp(ulongsh, reg0, mw(zeroe,max), f_less_than_or_equal, nilexp);
3759
	  test_exception(f_less_than_or_equal, ulongsh);
2 7u83 3760
	};
3761
	if (sgf && sgt)
7 7u83 3762
	  simplest_set_lab(lab1);
2 7u83 3763
      };
3764
    }
3765
    else {
3766
      if (sgf && (!sgt || szt < szf)) {
7 7u83 3767
	IGNORE cmp(fsh, from, mw(zeroe,min), f_greater_than_or_equal, nilexp);
3768
	test_exception(f_greater_than_or_equal, fsh);
2 7u83 3769
      };
3770
      if ((szt - sgt) < (szf - sgf)) {
7 7u83 3771
	IGNORE cmp(fsh, from, mw(zeroe,max), f_less_than_or_equal, nilexp);
3772
	test_exception(f_less_than_or_equal, fsh);
2 7u83 3773
      };
3774
    };
3775
  }
3776
 
3777
  if (szf == 8) {
3778
    if (bad_from_reg(from)) {
7 7u83 3779
      move(slongsh, from, reg0);
2 7u83 3780
      from = reg0;
3781
    };
3782
 
3783
    if (szt == 8) {
7 7u83 3784
      move(sha, from, to);
2 7u83 3785
      return;
3786
    };
3787
 
3788
    if (szt == 16) {
3789
      if (sgf) {
7 7u83 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);
2 7u83 3796
	}
3797
	else {
7 7u83 3798
	  contop(fe, eq_where(reg0, from), to);
3799
	  ins2(movsbw, szf, szt, from, to);
3800
	  invalidate_dest(to);
3801
	  end_contop();
2 7u83 3802
	};
3803
	son(fe) = holdfe;
3804
	return;
3805
      }
3806
      else {
7 7u83 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);
2 7u83 3813
	}
3814
	else {
7 7u83 3815
	  contop(fe, eq_where(reg0, from), to);
3816
	  ins2(movzbw, szf, szt, from, to);
3817
	  invalidate_dest(to);
3818
	  end_contop();
2 7u83 3819
	};
3820
	son(fe) = holdfe;
3821
	return;
3822
      };
3823
    };
3824
    if (szt >= 32) {
3825
      if (sgf) {
7 7u83 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();
2 7u83 3831
	  if (szt == 64) {
3832
	    if (sgt) {
7 7u83 3833
	      move(slongsh, reg0, reg1);
3834
	      ins2(sarl, 8, 32, mw(zeroe,31), reg1);
2 7u83 3835
	    }
3836
	    else
7 7u83 3837
	      move(ulongsh, zero, reg1);
2 7u83 3838
	  };
7 7u83 3839
	  move(sha, reg0, to);
2 7u83 3840
	}
3841
	else {
7 7u83 3842
	  contop(fe, eq_where(reg0, from), to);
3843
	  ins2(movsbl, szf, szt, from, to);
3844
	  invalidate_dest(to);
3845
	  end_contop();
2 7u83 3846
	};
3847
	son(fe) = holdfe;
3848
	return;
3849
      };
7 7u83 3850
      if (inmem(to) || szt == 64) {
2 7u83 3851
	move(scharsh, from, reg0);
3852
	and(slongsh, reg0, mw(zeroe, 0xff), reg0);
3853
	if (szt == 64)
7 7u83 3854
	  move(ulongsh, zero, reg1);
3855
	move(sha, reg0, to);
2 7u83 3856
	}
3857
      else {
7 7u83 3858
	if (eq_where(to, reg4) || eq_where(to, reg5) ||
2 7u83 3859
		 eq_where(to, reg6)) {
7 7u83 3860
	  contop(fe, eq_where(reg0, from), to);
3861
	  ins2(movzbl, szf, szt, from, to);
3862
	  invalidate_dest(to);
3863
	  end_contop();
2 7u83 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)) {
7 7u83 3878
        move(slongsh, from, reg0);
2 7u83 3879
        from = reg0;
3880
      };
3881
 
3882
      if (sgt) {
7 7u83 3883
	if (inmem(to)) {
3884
	  move(sh(fe), from, reg0);
3885
	  move(sha, reg0, to);
2 7u83 3886
	}
3887
	else
7 7u83 3888
	  move(sha, from, to);
2 7u83 3889
	son(fe) = holdfe;
3890
	return;
3891
      };
7 7u83 3892
      move(sha, from, to);
2 7u83 3893
      son(fe) = holdfe;
3894
      return;
3895
    };
3896
    if (szt == 16) {
7 7u83 3897
      move(sha, from, to);
2 7u83 3898
      son(fe) = holdfe;
3899
      return;
3900
    };
3901
    if (sgf) {
7 7u83 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();
2 7u83 3907
	if (szt == 64) {
3908
	  if (sgt) {
7 7u83 3909
	    move(slongsh, reg0, reg1);
3910
	    ins2(sarl, 8, 32, mw(zeroe,31), reg1);
2 7u83 3911
	  }
3912
	  else
7 7u83 3913
	    move(ulongsh, zero, reg1);
2 7u83 3914
	};
7 7u83 3915
	move(sha, reg0, to);
2 7u83 3916
      }
3917
      else {
7 7u83 3918
	contop(fe, eq_where(reg0, from), to);
3919
	ins2(movswl, szf, szt, from, to);
3920
	invalidate_dest(to);
3921
	end_contop();
2 7u83 3922
      };
3923
      son(fe) = holdfe;
3924
      return;
3925
    };
7 7u83 3926
    if (inmem(to) || szt == 64) {
2 7u83 3927
      move(swordsh, from, reg0);
3928
      and(slongsh, reg0, mw(zeroe, 0xffff), reg0);
3929
      if (szt == 64)
7 7u83 3930
	move(ulongsh, zero, reg1);
3931
      move(sha, reg0, to);
2 7u83 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)) {
7 7u83 3944
        move(slongsh, from, reg0);
2 7u83 3945
        from = reg0;
3946
      };
3947
      if (sgt) {
7 7u83 3948
        if (inmem(from) && inmem(to)) {
3949
	  move(sh(fe), from, reg0);
3950
	  move(sha, reg0, to);
2 7u83 3951
        }
3952
        else
7 7u83 3953
	  move(sha, from, to);
2 7u83 3954
	son(fe) = holdfe;
3955
        return;
3956
      };
7 7u83 3957
      move(sha, from, to);
2 7u83 3958
      son(fe) = holdfe;
3959
      return;
3960
    };
3961
 
3962
    if (szt == 16) {
3963
      if (sgt) {
7 7u83 3964
        if (inmem(to)) {
3965
	  move(sha, from, reg0);
3966
  	  move(sha, reg0, to);
2 7u83 3967
        }
3968
        else
7 7u83 3969
  	  move(sha, from, to);
2 7u83 3970
	son(fe) = holdfe;
3971
        return;
3972
      };
7 7u83 3973
      move(sha, from, to);
2 7u83 3974
      son(fe) = holdfe;
3975
      return;
3976
    };
3977
    if (szt > szf) {
7 7u83 3978
      move(slongsh, from, reg0);
2 7u83 3979
      if (sgf && sgt) {
7 7u83 3980
	move(slongsh, reg0, reg1);
3981
	ins2(sarl, 8, 32, mw(zeroe,31), reg1);
2 7u83 3982
      }
3983
      else
7 7u83 3984
	move(ulongsh, zero, reg1);
3985
      invalidate_dest(reg0);
2 7u83 3986
      from = reg0;
3987
    }
7 7u83 3988
    move(sha, from, to);
2 7u83 3989
    son(fe) = holdfe;
3990
    return;
3991
  };
3992
 
7 7u83 3993
  if (!sgf) {
3994
    move(sha, from, to);
2 7u83 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
7 7u83 4006
(shape sha, where from, where to)
2 7u83 4007
{
4008
  exp fe = from.where_exp;
7 7u83 4009
  shape fsh = sh(fe);
2 7u83 4010
  exp old_overflow_e = overflow_e;
4011
  overflow_e = nilexp;
7 7u83 4012
  change_var_sh(sha, fsh, from, to);
2 7u83 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
7 7u83 4019
(shape sha, where from, where to)
2 7u83 4020
{
4021
  exp fe = from.where_exp;
7 7u83 4022
  shape fsh = sh(fe);
4023
  change_var_sh(sha, fsh, from, to);
2 7u83 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
7 7u83 4034
(char *opb, char *opw, char *opl, int one, shape sha, where a1, where a2, where dest)
2 7u83 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
 
7 7u83 4045
  if (name(a) == val_tag && !isbigval(a) && no(a) + aoff == one) {
4046
    move(sha, a2, dest);
2 7u83 4047
    return;
4048
  };
4049
 
7 7u83 4050
  if (name(b) == val_tag && !isbigval(b) && no(b) + boff == one) {
4051
    move(sha, a1, dest);
2 7u83 4052
    return;
4053
  };
4054
 
4055
  cond1_set = 1;
4056
  cond2_set = 0;
4057
  cond1 = dest;			/* conditions will be set from dest */
4058
 
7 7u83 4059
  if (eq_where(a1, dest) &&
2 7u83 4060
	(!keep_short || !flinmem(dest))) {
7 7u83 4061
    if (!inmem(a1) || !inmem(a2)) {
2 7u83 4062
      /* use 2 address */
4063
      int riu = regsinuse;
4064
      if (sz == 64)
4065
	regsinuse |= 0x2;
7 7u83 4066
      if (inmem(a1))
4067
	contop(a, eq_where(reg0, a2), a1);
2 7u83 4068
      else
7 7u83 4069
	contop(b,
4070
	    (eq_where(reg0, a2) || eq_where(reg0, a1)), a1);
2 7u83 4071
      if (sz == 8) {
7 7u83 4072
	ins2(opb, sz, sz, a2, a1);
2 7u83 4073
      }
4074
      else
4075
      if (sz == 16) {
7 7u83 4076
	ins2(opw, sz, sz, a2, a1);
2 7u83 4077
      }
4078
      else
4079
      if (sz == 32) {
7 7u83 4080
	ins2(opl, sz, sz, a2, a1);
2 7u83 4081
      }
4082
      else
4083
      if (sz == 64) {
4084
	where dhi, dlo, shi, slo;
4085
	if (inmem(a1)) {
4086
	  dlo = a1;
7 7u83 4087
	  dhi = mw(a, aoff+32);
2 7u83 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;
7 7u83 4097
	    c1 = (name(sha) == s64hd && c < 0)? -1 : 0;
2 7u83 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)
7 7u83 4107
	    ins2(opl, 32, 32, mw(zeroe, c), dlo);
2 7u83 4108
	  if (c1 != one)
7 7u83 4109
	    ins2(opl, 32, 32, mw(zeroe, c1), dhi);
2 7u83 4110
	}
4111
	else {
4112
	  if (inmem(a2)) {
4113
	    slo = a2;
7 7u83 4114
	    shi = mw(b, boff+32);
2 7u83 4115
	  }
4116
	  else {
4117
	    slo = reg0;
4118
	    shi = reg1;
4119
	  };
7 7u83 4120
	  ins2(opl, 32, 32, slo, dlo);
4121
	  ins2(opl, 32, 32, shi, dhi);
2 7u83 4122
	};
4123
      };
7 7u83 4124
      invalidate_dest(dest);
4125
      end_contop();
2 7u83 4126
      regsinuse = riu;
4127
      son(a) = holda;
4128
      son(b) = holdb;
4129
      return;
4130
    };
4131
 
7 7u83 4132
    move(sha, a2, reg0);
4133
    andetc(opb, opw, opl, one, sha, reg0, dest, dest);
2 7u83 4134
    return;
4135
  };
4136
 
7 7u83 4137
  if (eq_where(a2, dest) &&
2 7u83 4138
	(!keep_short || !flinmem(dest))) {	/* use 2 address */
7 7u83 4139
    if (!inmem(a1) || !inmem(a2)) {
2 7u83 4140
      int riu = regsinuse;
4141
      if (sz == 64)
4142
	regsinuse |= 0x2;
7 7u83 4143
      if (inmem(a1))
4144
	contop(a, eq_where(reg0, a2), a2);
2 7u83 4145
      else
7 7u83 4146
	contop(b,
4147
	    (eq_where(reg0, a1) || eq_where(reg0, a2)), a2);
2 7u83 4148
      if (sz == 8) {
7 7u83 4149
	ins2(opb, sz, sz, a1, a2);
2 7u83 4150
      }
4151
      else
4152
      if (sz == 16) {
7 7u83 4153
	ins2(opw, sz, sz, a1, a2);
2 7u83 4154
      }
4155
      if (sz == 32) {
7 7u83 4156
	ins2(opl, sz, sz, a1, a2);
2 7u83 4157
      }
4158
      else
4159
      if (sz == 64) {
4160
	where dhi, dlo, shi, slo;
4161
	if (inmem(a2)) {
4162
	  dlo = a2;
7 7u83 4163
	  dhi = mw(b, boff+32);
2 7u83 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;
7 7u83 4173
	    c1 = (name(sha) == s64hd && c < 0)? -1 : 0;
2 7u83 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)
7 7u83 4183
	    ins2(opl, 32, 32, mw(zeroe, c), dlo);
2 7u83 4184
	  if (c1 != one)
7 7u83 4185
	    ins2(opl, 32, 32, mw(zeroe, c1), dhi);
2 7u83 4186
	}
4187
	else {
4188
	  if (inmem(a1)) {
4189
	    slo = a1;
7 7u83 4190
	    shi = mw(a, aoff+32);
2 7u83 4191
	  }
4192
	  else {
4193
	    slo = reg0;
4194
	    shi = reg1;
4195
	  };
7 7u83 4196
	  ins2(opl, 32, 32, slo, dlo);
4197
	  ins2(opl, 32, 32, shi, dhi);
2 7u83 4198
	};
4199
      };
7 7u83 4200
      invalidate_dest(dest);
4201
      end_contop();
2 7u83 4202
      regsinuse = riu;
4203
      son(a) = holda;
4204
      son(b) = holdb;
4205
      return;
4206
    };
4207
 
7 7u83 4208
    move(sha, a1, reg0);
4209
    andetc(opb, opw, opl, one, sha, reg0, dest, dest);
2 7u83 4210
    return;
4211
  };
4212
 
7 7u83 4213
  switch ((inmem(a1) << 2) + (inmem(a2) << 1) + inmem(dest)) {
2 7u83 4214
    case 0:
7 7u83 4215
      move(sha, a2, dest);
4216
      andetc(opb, opw, opl, one, sha, a1, dest, dest);
2 7u83 4217
      return;
4218
    case 1:
4219
    case 3:
4220
    case 5:
4221
    case 7:
7 7u83 4222
      andetc(opb, opw, opl, one, sha, a1, a2, reg0);
4223
      move(sha, reg0, dest);
2 7u83 4224
      return;
4225
    case 2:
7 7u83 4226
      if (eq_where(a1, reg0))
2 7u83 4227
	reg0_in_use = 1;
7 7u83 4228
      move(sha, a2, dest);
4229
      andetc(opb, opw, opl, one, sha, a1, dest, dest);
2 7u83 4230
      return;
4231
    case 4:
7 7u83 4232
      if (eq_where(a2, reg0))
2 7u83 4233
	reg0_in_use = 1;
7 7u83 4234
      move(sha, a1, dest);
4235
      andetc(opb, opw, opl, one, sha, a2, dest, dest);
2 7u83 4236
      return;
4237
    default: 			/* case 6 */
7 7u83 4238
      move(sha, a2, reg0);
4239
      andetc(opb, opw, opl, one, sha, a1, reg0, reg0);
4240
      move(sha, reg0, dest);
2 7u83 4241
      return;
4242
  };
4243
 
4244
}
4245
 
4246
void and
7 7u83 4247
(shape sha, where a1, where a2, where dest)
2 7u83 4248
{
7 7u83 4249
  andetc(andb, andw, andl, -1, sha, a1, a2, dest);
2 7u83 4250
  return;
4251
}
4252
 
4253
void or
7 7u83 4254
(shape sha, where a1, where a2, where dest)
2 7u83 4255
{
7 7u83 4256
  andetc(orb, orw, orl, 0, sha, a1, a2, dest);
2 7u83 4257
  return;
4258
}
4259
 
4260
void xor
7 7u83 4261
(shape sha, where a1, where a2, where dest)
2 7u83 4262
{
7 7u83 4263
  andetc(xorb, xorw, xorl, 0, sha, a1, a2, dest);
2 7u83 4264
  return;
4265
}
4266
 
4267
 
4268
static void needs_lib64
7 7u83 4269
(void)
2 7u83 4270
{
4271
  if (!lib64_set) {
7 7u83 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);
2 7u83 4283
    if (!PIC_code)
7 7u83 4284
      lib64_error = getexp(slongsh, nilexp, 1, lib64_error, nilexp, 0, 0, cont_tag);
2 7u83 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
7 7u83 4295
(shape sha, shape sh1, shape sh2, where a1, where a2)
2 7u83 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) {
7 7u83 4301
    if (shape_size(sh2)!= 32 || (eq_where(a2, reg0) && !eq_where(a1, reg0))) {
4302
      mult64(sha, sh2, sh1, a2, a1);
2 7u83 4303
      return;
4304
    };
7 7u83 4305
    if (eq_where(a1, reg0)) {
4306
      int difsg = (is_signed(sh1)!= is_signed(sh2));
2 7u83 4307
      int lab1, lab2;
4308
      regsinuse |= 0x2;
7 7u83 4309
      contop(a2.where_exp, 1, a2);
2 7u83 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;
7 7u83 4316
	move(sh2, a2, reg2);
2 7u83 4317
	a2 = reg2;
4318
      };
4319
      if (difsg && is_signed(sh2)) {
7 7u83 4320
	if (inmem(a2)) {
4321
	  ins2(movl, 32, 32, a2, reg2);
2 7u83 4322
	  a2 = reg2;
4323
	};
7 7u83 4324
	ins2(xchg, 32, 32, reg0, reg2);
2 7u83 4325
      };
4326
      if (difsg) {
4327
	lab1 = next_lab();
4328
	lab2 = next_lab();
7 7u83 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);
2 7u83 4337
      }
4338
      else
7 7u83 4339
        ins1((is_signed(sh1)? imull : mull), 32, a2);
4340
      end_contop();
2 7u83 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)) {
7 7u83 4347
      mult64(sha, sh2, sh1, a2, a1);
2 7u83 4348
      return;
4349
    };
4350
    if (is_signed(sh1)) {
7 7u83 4351
      if (name(a1.where_exp)!= val_tag) {
4352
	move(sh1, a1, reg0);
4353
	mult64(sha, sh1, sh2, reg0, a2);
2 7u83 4354
	return;
4355
      };
4356
      if ((no(a1.where_exp) + a1.where_off) >= 0 || is_signed(sh2)) {
7 7u83 4357
	move(sh2, a2, reg0);
4358
	mult64(sha, sh2, sh2, reg0, a1);
2 7u83 4359
	return;
4360
      };
4361
	/* otherwise, we are multiplying negative constant by unsigned */
7 7u83 4362
      move(sh1, a1, reg0);
4363
      contop(a2.where_exp, 1, a2);
2 7u83 4364
      if (name(a2.where_exp) == val_tag) {
4365
	reg0_in_use = 1;
7 7u83 4366
	move(sh2, a2, reg2);
2 7u83 4367
	a2 = reg2;
4368
      };
7 7u83 4369
      ins1(mull, 32, a2);
4370
      ins2(subl, 32, 32, a2, reg1);
4371
      end_contop();
2 7u83 4372
      son(a2.where_exp) = holda2;
4373
      return;
4374
    };
4375
	/* both are unsigned */
4376
    if (name(a1.where_exp) == val_tag) {
7 7u83 4377
      move(sh1, a1, reg0);
4378
      mult64(sha, sh1, sh2, reg0, a2);
2 7u83 4379
      return;
4380
    };
4381
    {
7 7u83 4382
      move(sh2, a2, reg0);
4383
      mult64(sha, sh2, sh1, reg0, a1);
2 7u83 4384
      return;
4385
    };
4386
  };
4387
 
4388
  if (overflow_e != nilexp && !optop(overflow_e)) {
4389
				/* need library proc to check for overflow */
4390
    needs_lib64();
7 7u83 4391
    if (eq_where(a1, reg0)) {
2 7u83 4392
      a1 = a2;
4393
      a2 = reg0;
4394
    };
7 7u83 4395
    move(sha, a2, pushdest);
2 7u83 4396
    extra_stack += 64;
7 7u83 4397
    move(sha, a1, pushdest);
2 7u83 4398
    extra_stack -= 64;
7 7u83 4399
    callins(0,(is_signed(sha)? lib64_s_mult : lib64_u_mult), stack_dec);
2 7u83 4400
    add(slongsh, mw(zeroe, 16), sp, sp);
7 7u83 4401
    ins2(movl, 32, 32, mw(lib64_error, 0), reg2);
2 7u83 4402
    if (PIC_code)
7 7u83 4403
      ins2(movl, 32, 32, ind_reg2, reg2);
4404
    ins2(testl, 32, 32, reg2, reg2);
4405
    test_exception(f_greater_than_or_equal, slongsh);
2 7u83 4406
    return;
4407
  };
4408
 
4409
  if (shape_size(sh2) == 32 || (name(a2.where_exp) == val_tag && !isbigval(a2.where_exp))) {
7 7u83 4410
    if (eq_where(a1, reg0)) {
2 7u83 4411
      reg0_in_use = 1;
4412
      regsinuse |= 0x2;
7 7u83 4413
      move(slongsh, a2, reg2);
2 7u83 4414
    }
4415
    else {
7 7u83 4416
      move(slongsh, a2, reg2);
2 7u83 4417
      regsinuse |= 0x4;
7 7u83 4418
      move(sha, a1, reg0);
2 7u83 4419
    }
7 7u83 4420
    ins0(pushedx);
2 7u83 4421
#ifdef NEWDWARF
4422
    if (diagnose && dwarf2 && no_frame)
4423
      dw2_track_push();
4424
#endif
4425
    if (is_signed(sha) && is_signed(sh2) &&
7 7u83 4426
	 (name(a2.where_exp)!= val_tag || (no(a2.where_exp) + a2.where_off) < 0)) {
4427
      ins0(pusheax);
2 7u83 4428
#ifdef NEWDWARF
4429
      if (diagnose && dwarf2 && no_frame)
4430
	dw2_track_push();
4431
#endif
7 7u83 4432
      ins1(mull, 32, reg2);
4433
      if (name(a2.where_exp)!= val_tag) {
2 7u83 4434
	int lab1 = next_lab();
7 7u83 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);
2 7u83 4439
      }
4440
      else
7 7u83 4441
	ins2(subl, 32, 32, ind_sp, reg1);
4442
      ins2(addl, 32, 32, mw(zeroe,4), sp);
2 7u83 4443
    }
4444
    else
7 7u83 4445
      ins1(mull, 32, reg2);
4446
    ins2(imull, 32, 32, ind_sp, reg2);
4447
    ins2(addl, 32, 32, reg2, reg1);
4448
    ins0(popecx);
2 7u83 4449
#ifdef NEWDWARF
4450
    if (diagnose && dwarf2 && no_frame)
4451
      dw2_track_pop();
4452
#endif
4453
    regsinuse = riu;
4454
    return;
4455
  };
4456
 
7 7u83 4457
  if (eq_where(a1, a2)) {
4458
    move(sha, a1, reg0);
4459
    ins0(pushedx);
2 7u83 4460
#ifdef NEWDWARF
4461
    if (diagnose && dwarf2 && no_frame)
4462
      dw2_track_push();
4463
#endif
7 7u83 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);
2 7u83 4470
#ifdef NEWDWARF
4471
    if (diagnose && dwarf2 && no_frame)
4472
      dw2_track_pop();
4473
#endif
4474
    return;
4475
  };
4476
 
7 7u83 4477
  if (eq_where(a2, reg0)) {
2 7u83 4478
    son(a2.where_exp) = holda2;
4479
    a2 = a1;
4480
    holda2 = son(a2.where_exp);
4481
    a1 = reg0;
4482
  };
7 7u83 4483
  move(sha, a1, reg0);
2 7u83 4484
  reg0_in_use = 1;
4485
  regsinuse |= 0x6;
7 7u83 4486
  contop(a2.where_exp, 1, a2);
4487
  ins0(pushedx);
2 7u83 4488
#ifdef NEWDWARF
4489
  if (diagnose && dwarf2 && no_frame)
4490
    dw2_track_push();
4491
#endif
4492
  extra_stack += 32;
7 7u83 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);
2 7u83 4498
#ifdef NEWDWARF
4499
  if (diagnose && dwarf2 && no_frame)
4500
    dw2_track_pop();
4501
#endif
4502
  extra_stack -= 32;
7 7u83 4503
  ins2(imull, 32, 32, a2, reg2);
4504
  ins2(addl, 32, 32, reg2, reg1);
4505
  end_contop();
2 7u83 4506
  regsinuse = riu;
4507
  son(a2.where_exp) = holda2;
4508
  return;
4509
}
4510
 
4511
 
4512
static void clean_multiply
7 7u83 4513
(int stored)
2 7u83 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
7 7u83 4532
(shape sha, where a1, where a2, where dest)
2 7u83 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) {
7 7u83 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);
2 7u83 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
  };
7 7u83 4560
  invalidate_dest(reg0);
4561
  if (name(a2.where_exp) == val_tag && sz != 8 &&
4562
	(is_signed(sha) || overflow_e == nilexp || optop(overflow_e))) {
2 7u83 4563
    	    /* x * const -> y */
7 7u83 4564
    contop(a1.where_exp, eq_where(reg0, a1), dest);
4565
    if (!inmem(dest)) {
2 7u83 4566
        /* x * const -> reg */
7 7u83 4567
      if (name(a1.where_exp) == val_tag) {
4568
	move(sha, a1, dest);
2 7u83 4569
	son(a1.where_exp) = hold_a1;
4570
	a1 = dest;
4571
	hold_a1 = son(a1.where_exp);
4572
      };
7 7u83 4573
      ins3(in, sz, sz, sz, a2, a1, dest);
4574
      invalidate_dest(dest);
4575
      end_contop();
4576
      try_overflow(sha, 0);
2 7u83 4577
      son(a1.where_exp) = hold_a1;
4578
      return;
4579
    };
4580
       /* x * const -> notreg   : use reg0 */
7 7u83 4581
    if (name(a1.where_exp) == val_tag) {
4582
      move(sha, a1, reg0);
2 7u83 4583
      son(a1.where_exp) = hold_a1;
4584
      a1 = reg0;
4585
      hold_a1 =  son(a1.where_exp);
4586
    };
7 7u83 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);
2 7u83 4592
    son(a1.where_exp) = hold_a1;
4593
    return;
4594
  };
4595
 
7 7u83 4596
  if (is_signed(sha) && sz != 8) {
2 7u83 4597
      /* signed : we don't have to disturb eax/edx */
7 7u83 4598
    if (!inmem(dest)) {
4599
      if (eq_where(a2, dest)) {
4600
	contop(a1.where_exp,
4601
	    (eq_where(reg0, a1) || eq_where(reg0, a2)),
2 7u83 4602
	    dest);
7 7u83 4603
	ins2(in, sz, sz, a1, dest);
4604
	invalidate_dest(dest);
4605
	end_contop();
4606
        try_overflow(sha, 0);
2 7u83 4607
	son(a1.where_exp) = hold_a1;
4608
	return;
4609
      };
7 7u83 4610
      if (eq_where(a1, dest)) {
4611
	contop(a2.where_exp,
4612
	    (eq_where(reg0, a1) || eq_where(reg0, a2)),
2 7u83 4613
	    dest);
7 7u83 4614
	ins2(in, sz, sz, a2, dest);
4615
	invalidate_dest(dest);
4616
	end_contop();
4617
        try_overflow(sha, 0);
2 7u83 4618
	son(a2.where_exp) = hold_a2;
4619
	return;
4620
      };
4621
    };
7 7u83 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);
2 7u83 4629
      son(a1.where_exp) = hold_a1;
4630
      return;
4631
    };
7 7u83 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);
2 7u83 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 */
7 7u83 4645
    if (!is_signed(sha))
2 7u83 4646
      in = &in[1];
7 7u83 4647
    if ((regsinuse & 0x2) && !eq_where(dest, reg1)) {
2 7u83 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;
7 7u83 4656
      invalidate_dest(reg1);
2 7u83 4657
    };
7 7u83 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);
2 7u83 4664
	}
4665
	else {
7 7u83 4666
	  ins1(in, sz, a1);
2 7u83 4667
	};
7 7u83 4668
        invalidate_dest(reg0);
2 7u83 4669
        invalidate_dest(reg1);
7 7u83 4670
	invalidate_dest(a1);
4671
	end_contop();
4672
	clean_multiply(stored);
4673
        try_overflow(sha, 0);
2 7u83 4674
	son(a1.where_exp) = hold_a1;
4675
	return;
4676
      };
7 7u83 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);
2 7u83 4682
	}
4683
	else {
7 7u83 4684
	  ins1(in, sz, a2);
2 7u83 4685
	};
7 7u83 4686
        invalidate_dest(reg0);
2 7u83 4687
        invalidate_dest(reg1);
7 7u83 4688
	invalidate_dest(a2);
4689
	end_contop();
4690
	clean_multiply(stored);
4691
        try_overflow(sha, 0);
2 7u83 4692
	son(a2.where_exp) = hold_a2;
4693
	return;
4694
      };
4695
    };
7 7u83 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);
2 7u83 4701
      }
4702
      else {
7 7u83 4703
	ins1(in, sz, a1);
2 7u83 4704
      };
7 7u83 4705
      invalidate_dest(a1);
4706
      invalidate_dest(reg0);
2 7u83 4707
      invalidate_dest(reg1);
7 7u83 4708
      end_contop();
4709
      clean_multiply(stored);
4710
      try_overflow(sha, 0);
4711
      move(sha, reg0, dest);
2 7u83 4712
      son(a1.where_exp) = hold_a1;
4713
      return;
4714
    };
7 7u83 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);
2 7u83 4720
    }
4721
    else {
7 7u83 4722
      ins1(in, sz, a2);
2 7u83 4723
    };
7 7u83 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);
2 7u83 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
7 7u83 4744
(where a1, where a2, where dest, int inc)
2 7u83 4745
{
4746
  int  i,
4747
        j;
7 7u83 4748
  int  n = no(a2.where_exp) + a2.where_off;
2 7u83 4749
  shape sha = slongsh;
4750
  exp holdd = son(dest.where_exp);
4751
 
7 7u83 4752
  if (name(sh(a2.where_exp)) == offsethd && al2(sh(a2.where_exp))!= 1)
2 7u83 4753
     n = n / 8;
4754
 
4755
  cond1_set = 0;
4756
  cond2_set = 0;
4757
 
4758
  if (n == 0) {
7 7u83 4759
    move(sha, zero, dest);
2 7u83 4760
    return;
4761
  };
4762
 
4763
  if (n == 1) {
7 7u83 4764
    move(sha, a1, dest);
2 7u83 4765
    return;
4766
  };
4767
 
4768
 
4769
  switch (n) {
4770
    case 2:
7 7u83 4771
      if (inmem(a1)) {
2 7u83 4772
	where newdest;
7 7u83 4773
	newdest = (inmem(dest))? reg0 : dest;
4774
	move(sha, a1, newdest);
4775
	add(sha, newdest, newdest, dest);
2 7u83 4776
	return;
4777
      }
4778
      add(sha, a1, a1, dest);
4779
      return;
4780
    case 3:
7 7u83 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);
2 7u83 4786
	son(dest.where_exp) = holdd;
4787
	return;
4788
      };
7 7u83 4789
      contop(dest.where_exp, eq_where(reg0, a1), dest);
4790
      mult_op(inc, a1, a1, 2, dest);
4791
      invalidate_dest(dest);
2 7u83 4792
      son(dest.where_exp) = holdd;
4793
      return;
4794
    case 5:
7 7u83 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);
2 7u83 4800
	son(dest.where_exp) = holdd;
4801
	return;
4802
      };
7 7u83 4803
      contop(dest.where_exp, eq_where(reg0, a1), dest);
4804
      mult_op(inc, a1, a1, 4, dest);
4805
      invalidate_dest(dest);
2 7u83 4806
      son(dest.where_exp) = holdd;
4807
      return;
4808
    case 7:
4809
      if (!inmem(a1) && !inmem(dest) && !eq_where(a1, dest)) {
7 7u83 4810
	longc_mult(a1, mw(zeroe, 8), dest, inc);
2 7u83 4811
	sub(sha, a1, dest, dest);
4812
	return;
4813
      };
4814
      if (!inmem(a1) && !inmem(dest)) {
4815
	if (!eq_where(a1, reg0)) {
7 7u83 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);
2 7u83 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
7 7u83 4830
	  mult_op(inc, a1, a1, 2, reg1);
4831
	  mult_op(inc, reg1, reg0, 4, dest);
4832
	  invalidate_dest(dest);
2 7u83 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
      };
7 7u83 4846
      multiply(sha, a1, a2, dest);
2 7u83 4847
      return;
4848
    case 9:
7 7u83 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);
2 7u83 4854
	son(dest.where_exp) = holdd;
4855
	return;
4856
      };
7 7u83 4857
      contop(dest.where_exp, eq_where(reg0, a1), dest);
4858
      mult_op(inc, a1, a1, 8, dest);
4859
      invalidate_dest(dest);
2 7u83 4860
      son(dest.where_exp) = holdd;
4861
      return;
4862
    case 15: {
4863
        if (!inmem(a1)) {
7 7u83 4864
	  mult_op(inc, a1, a1, 2, reg0);
2 7u83 4865
	}
4866
	else  {
7 7u83 4867
	  move(sha, a1, reg0);
4868
	  mult_op(inc, reg0, reg0, 2, reg0);
2 7u83 4869
	};
7 7u83 4870
	contop(dest.where_exp, 1, dest);
4871
	mult_op(inc, reg0, reg0, 4, dest);
4872
	invalidate_dest(reg0);
4873
	invalidate_dest(dest);
2 7u83 4874
	son(dest.where_exp) = holdd;
4875
	return;
4876
      };
4877
    case 25: {
4878
        if (!inmem(a1)) {
7 7u83 4879
	  mult_op(inc, a1, a1, 4, reg0);
2 7u83 4880
	}
4881
	else  {
7 7u83 4882
	  move(sha, a1, reg0);
4883
	  mult_op(inc, reg0, reg0, 4, reg0);
2 7u83 4884
	};
7 7u83 4885
	contop(dest.where_exp, 1, dest);
4886
	mult_op(inc, reg0, reg0, 4, dest);
4887
	invalidate_dest(reg0);
4888
	invalidate_dest(dest);
2 7u83 4889
	son(dest.where_exp) = holdd;
4890
	return;
4891
      };
4892
    default:
4893
      if ((n & (n - 1)) == 0) {
4894
	int  mask = 1;
4895
	int  c;
7 7u83 4896
	for (c = 0;(mask & n) == 0; ++c)
2 7u83 4897
	  mask += mask;
7 7u83 4898
	shiftl(sha, mw(zeroe, c), a1, dest);
2 7u83 4899
	return;
4900
      };
4901
      if ((-n & (-n - 1)) == 0) {
4902
	int  mask = 1;
4903
	int  c;
7 7u83 4904
	for (c = 0;(mask & -n) == 0; ++c)
2 7u83 4905
	  mask += mask;
7 7u83 4906
	shiftl(sha, mw(zeroe, c), a1, dest);
4907
        negate(sha, dest, dest);
2 7u83 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;
7 7u83 4915
	    if (inmem(dest))
2 7u83 4916
	      w = reg0;
4917
	    else
4918
	      w = dest;
7 7u83 4919
	    longc_mult(a1, mw(zeroe, mtab[i]), w, 0);
4920
	    longc_mult(w, mw(zeroe, x), dest, inc);
2 7u83 4921
	    return;
4922
	  };
4923
	  for (j = 0; j < short_mults; ++j) {
4924
	    if (x == mtab[j]) {
4925
	      where w;
7 7u83 4926
	      if (inmem(dest))
2 7u83 4927
		w = reg0;
4928
	      else
4929
		w = dest;
7 7u83 4930
	      longc_mult(a1, mw(zeroe, mtab[i]), w, 0);
4931
	      longc_mult(w, mw(zeroe, x), dest, inc);
2 7u83 4932
	      return;
4933
	    };
4934
	  };
4935
	};
4936
      };
7 7u83 4937
      multiply(sha, a1, a2, dest);
2 7u83 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
7 7u83 4946
(shape sha, where a1, where a2, where dest)
2 7u83 4947
{
4948
  int  inc = 0;
4949
  int sha_size = shape_size(sha);
4950
  cond1_set = 0;
4951
  cond2_set = 0;
4952
 
7 7u83 4953
  if (name(a1.where_exp) == val_tag && sha_size == 32) {
4954
    longc_mult(a2, a1, dest, inc);
2 7u83 4955
    return;
4956
  };
4957
 
7 7u83 4958
  if (name(a2.where_exp) == val_tag && sha_size == 32) {
4959
    longc_mult(a1, a2, dest, inc);
2 7u83 4960
    return;
4961
  };
4962
 
7 7u83 4963
  multiply(sha, a1, a2, dest);
2 7u83 4964
  return;
4965
}
4966
 
4967
 
4968
 
4969
/* shift from wshift places to to. */
4970
void shiftl
7 7u83 4971
(shape sha, where wshift, where from, where to)
2 7u83 4972
{
4973
  exp p = wshift.where_exp;
7 7u83 4974
  int  places = no(p) + wshift.where_off;
2 7u83 4975
  char *shifter;
4976
  int  sz;
7 7u83 4977
  int sig = is_signed(sha);
2 7u83 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;
7 7u83 4986
    move(sha, from, reg0);
2 7u83 4987
    if (name(wshift.where_exp) == val_tag)
7 7u83 4988
      rotshift64(0, sig, wshift);
2 7u83 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;
7 7u83 5001
      move(slongsh, wshift, reg2);
5002
      rotshift64(0, sig, wshift);
5003
      invalidate_dest(reg2);
2 7u83 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
    };
7 7u83 5013
    invalidate_dest(reg0);
5014
    invalidate_dest(reg1);
5015
    move(sha, reg0, to);
2 7u83 5016
    regsinuse = riu;
5017
    return;
5018
  }
5019
 
5020
  switch (sz) {			/* choose shift operation from signedness
5021
				   and length */
5022
    case 8:
7 7u83 5023
      shifter = (sig)? salb : shlb;
2 7u83 5024
      break;
5025
    case 16:
7 7u83 5026
      shifter = (sig)? salw : shlw;
2 7u83 5027
      break;
5028
    default:
7 7u83 5029
      shifter = (sig)? sall : shll;
2 7u83 5030
  };
5031
 
5032
  if (name (p) == val_tag) {	/* no of places is constant */
5033
    if (places >= 32) {
7 7u83 5034
      move(sha, zero, to);
2 7u83 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 */
7 7u83 5055
      contop(to.where_exp, 0, to);
5056
      ins2(shifter, 8, sz, wshift, to);
5057
      invalidate_dest(to);
5058
      end_contop();
2 7u83 5059
      son(to.where_exp) = holdto;
5060
      return;
5061
    };
5062
    if (!inmem (to)) {		/* to is a register */
7 7u83 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();
2 7u83 5068
      son(to.where_exp) = holdto;
5069
      return;
5070
    };
5071
    /* use reg0 to shift in */
7 7u83 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);
2 7u83 5077
    return;
5078
  };
5079
  {				/* we don't know the number of places */
5080
    int   to_reg2,
5081
          wshift_reg2;
7 7u83 5082
    to_reg2 = eq_where(to, reg2);
5083
    wshift_reg2 = eq_where(wshift, reg2);
2 7u83 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
 
7 7u83 5097
    change_var(slongsh, from, reg0);
2 7u83 5098
    reg0_in_use = 1;
7 7u83 5099
    move(slongsh, wshift, reg2);
2 7u83 5100
 
7 7u83 5101
    ins2(shifter, 8, sz, reg2, reg0);
5102
    invalidate_dest(reg0);
5103
    invalidate_dest(reg2);
2 7u83 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 */
7 7u83 5116
    move(sha, reg0, to);
2 7u83 5117
  };
5118
  return;
5119
 
5120
}
5121
 
5122
/* shift from wshift places to to. */
5123
static void rotshiftr
7 7u83 5124
(int shft, shape sha, where wshift, where from, where to)
2 7u83 5125
{
5126
  exp p = wshift.where_exp;
7 7u83 5127
  int  places = no(p) + wshift.where_off;
2 7u83 5128
  char *shifter;
5129
  int  sz;
7 7u83 5130
  int sig = is_signed(sha);
2 7u83 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;
7 7u83 5139
    move(sha, from, reg0);
2 7u83 5140
    if (name(wshift.where_exp) == val_tag)
7 7u83 5141
      rotshift64(shft+1, sig, wshift);
2 7u83 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;
7 7u83 5154
      move(slongsh, wshift, reg2);
5155
      rotshift64(shft+1, sig, wshift);
5156
      invalidate_dest(reg2);
2 7u83 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
    };
7 7u83 5166
    invalidate_dest(reg0);
5167
    invalidate_dest(reg1);
5168
    move(sha, reg0, to);
2 7u83 5169
    regsinuse = riu;
5170
    return;
5171
  }
5172
 
5173
  if (shft == 0) {
5174
    switch (sz) {
5175
      case 8:
7 7u83 5176
        shifter = (sig)? sarb : shrb;
2 7u83 5177
        break;
5178
      case 16:
7 7u83 5179
        shifter = (sig)? sarw : shrw;
2 7u83 5180
        break;
5181
      default:
7 7u83 5182
        shifter = (sig)? sarl : shrl;
2 7u83 5183
    }
5184
  }
5185
  else {
5186
    switch (sz) {
5187
      case 8:
7 7u83 5188
        shifter = (shft == 1)? rorb : rolb;
2 7u83 5189
        break;
5190
      case 16:
7 7u83 5191
        shifter = (shft == 1)? rorw : rolw;
2 7u83 5192
        break;
5193
      default:
7 7u83 5194
        shifter = (shft == 1)? rorl : roll;
2 7u83 5195
    }
5196
  };
5197
 
7 7u83 5198
  if (name(p) == val_tag) {
2 7u83 5199
    if (places >= 32) {
5200
      if (sig)
7 7u83 5201
	no(p) = 31;
2 7u83 5202
      else {
7 7u83 5203
	move(sha, zero, to);
2 7u83 5204
	return;
5205
      };
5206
    };
7 7u83 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();
2 7u83 5212
      son(to.where_exp) = holdto;
5213
      return;
5214
    };
7 7u83 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();
2 7u83 5221
      son(to.where_exp) = holdto;
5222
      return;
5223
    };
7 7u83 5224
    move(sha, from, reg0);
5225
    ins2(shifter, 8, sz, wshift, reg0);
5226
    invalidate_dest(reg0);
5227
    move(sha, reg0, to);
2 7u83 5228
    return;
5229
  };
5230
  {
5231
    int   to_reg2,
5232
          wshift_reg2;
5233
    int selfed = 0;
7 7u83 5234
    to_reg2 = eq_where(to, reg2);
5235
    wshift_reg2 = eq_where(wshift, reg2);
2 7u83 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) &&
7 7u83 5251
	((regsinuse & 0x4) == 0 || wshift_reg2) &&
2 7u83 5252
	 sz == 32) {
7 7u83 5253
      move(slongsh, wshift, reg2);
5254
      ins2(shifter, 8, sz, reg2, to);
5255
      invalidate_dest(to);
5256
      invalidate_dest(reg2);
2 7u83 5257
      selfed = 1;
5258
    }
5259
    else {
7 7u83 5260
      change_var(slongsh, from, reg0);
2 7u83 5261
      reg0_in_use = 1;
7 7u83 5262
      move(slongsh, wshift, reg2);
2 7u83 5263
 
7 7u83 5264
      ins2(shifter, 8, sz, reg2, reg0);
5265
      invalidate_dest(reg0);
5266
      invalidate_dest(reg2);
2 7u83 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)
7 7u83 5281
      move(sha, reg0, to);
2 7u83 5282
  };
5283
  return;
5284
 
5285
}
5286
 
5287
/* shift from wshift places to to. */
5288
void shiftr
7 7u83 5289
(shape sha, where wshift, where from, where to)
2 7u83 5290
{
7 7u83 5291
  rotshiftr(0, sha, wshift, from, to);
2 7u83 5292
  return;
5293
}
5294
 
5295
/* shift from wshift places to to. */
5296
void rotater
7 7u83 5297
(shape sha, where wshift, where from, where to)
2 7u83 5298
{
7 7u83 5299
  rotshiftr(1, sha, wshift, from, to);
2 7u83 5300
  return;
5301
}
5302
 
5303
/* shift from wshift places to to. */
5304
void rotatel
7 7u83 5305
(shape sha, where wshift, where from, where to)
2 7u83 5306
{
7 7u83 5307
  rotshiftr(2, sha, wshift, from, to);
2 7u83 5308
  return;
5309
}
5310
 
5311
/* divide top by bottom and put in dest */
5312
static void divit
7 7u83 5313
(shape sha, where bottom, where top, where dest, int whichdiv, int use_shift)
2 7u83 5314
{
5315
  int sz;
5316
  int v;
5317
  where d;
7 7u83 5318
  int sg = is_signed(sha);
2 7u83 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)) {
7 7u83 5330
    if (name(bottom.where_exp)!= val_tag || no(bottom.where_exp) == 0)
2 7u83 5331
      test_zero = 1;
7 7u83 5332
    if (sg && (name(bottom.where_exp)!= val_tag || no(bottom.where_exp) == -1))
2 7u83 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) &&
7 7u83 5342
      name(bottom.where_exp) == val_tag && !isbigval(bottom.where_exp) &&
5343
     (v = no(bottom.where_exp), v > 0 && (v & (v - 1)) == 0)) {
2 7u83 5344
    int  c = 0;
5345
    int  m = 1;
5346
    where rw;
5347
    if (name(shb) == offsethd &&
7 7u83 5348
          al2(shb)!= 1)
2 7u83 5349
      v = v / 8;
5350
    while (m != v) {
5351
      ++c;
5352
      m = m << 1;
5353
    };
5354
 
7 7u83 5355
    if (c == 0) {
5356
      move(sha, top, dest);
2 7u83 5357
      return;
5358
    };
5359
 
7 7u83 5360
    if (inmem(dest))
2 7u83 5361
      rw = reg0;
5362
    else
5363
      rw = dest;
7 7u83 5364
    move(sha, top, rw);
2 7u83 5365
    switch (sz) {
5366
      case 8:
7 7u83 5367
	ins2((sg)? sarb : shrb, 8, 8, mw(zeroe, c), rw);
2 7u83 5368
	break;
5369
      case 16:
7 7u83 5370
	ins2((sg)? sarw : shrw, 8, 16, mw(zeroe, c), rw);
2 7u83 5371
	break;
5372
      case 64:
5373
	rotshift64 (1, sg, mw (zeroe, c));	/* shift within reg0/reg1 */
5374
	break;
5375
      default: /* case 32 */
7 7u83 5376
	ins2((sg)? sarl : shrl, 8, 32, mw(zeroe, c), rw);
2 7u83 5377
    }
7 7u83 5378
    invalidate_dest(rw);
5379
    if (inmem(dest))
5380
      move(sha, rw, dest);
2 7u83 5381
    return;
5382
  };
5383
 
7 7u83 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)) {
2 7u83 5387
    needs_lib64();
7 7u83 5388
    if (eq_where(top, reg0)) {
5389
      ins2(subl, 32, 32, mw(zeroe, 16), sp);
2 7u83 5390
      extra_stack += 128;
7 7u83 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);
2 7u83 5394
      extra_stack -= 128;
5395
    }
5396
    else {
7 7u83 5397
      move(sha, bottom, pushdest);
2 7u83 5398
      extra_stack += 64;
7 7u83 5399
      move(sha, top, pushdest);
2 7u83 5400
      extra_stack -= 64;
5401
    }
7 7u83 5402
    callins(0, lib64_div[sg + 2*(whichdiv==1)], stack_dec);
5403
    ins2(addl, 32, 32, mw(zeroe, 16), sp);
2 7u83 5404
    if (overflow_e != nilexp && !optop(overflow_e)) {
7 7u83 5405
      ins2(movl, 32, 32, mw(lib64_error, 0), reg2);
2 7u83 5406
      if (PIC_code)
7 7u83 5407
        ins2(movl, 32, 32, ind_reg2, reg2);
5408
      ins2(testl, 32, 32, reg2, reg2);
5409
      test_exception(f_greater_than_or_equal, slongsh);
2 7u83 5410
    }
7 7u83 5411
    move(sha, reg0, dest);
2 7u83 5412
    return;
5413
  };
5414
 
5415
  if (sz == 8) {
5416
    if (sg)
7 7u83 5417
      change_var(swordsh, top, reg0);
2 7u83 5418
    else
7 7u83 5419
      change_var(uwordsh, top, reg0);
2 7u83 5420
  }
5421
  else
7 7u83 5422
    move(sha, top, reg0);
2 7u83 5423
 
5424
 
7 7u83 5425
  if (flinmem(bottom) || (eq_where(bottom, reg1) && sz > 8) || (whichdiv==1 && sg)) {
2 7u83 5426
    d = reg2;
7 7u83 5427
    if (regsinuse & 0x4 && !eq_where(dest, reg2)) {
2 7u83 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;
7 7u83 5442
      move(shb, bottom, reg2);
2 7u83 5443
      regsinuse = riu;
5444
    }
5445
    else
7 7u83 5446
      move(shb, bottom, reg2);
2 7u83 5447
  };
5448
 
5449
  if (test_zero) {		/* avoid divide by zero trap */
7 7u83 5450
    IGNORE cmp(shb, d, zero, f_not_equal, nilexp);
2 7u83 5451
    if (isov(overflow_e))
7 7u83 5452
      test_exception(f_not_equal, shb);
2 7u83 5453
    else {
5454
      reslab = next_lab();
7 7u83 5455
      simple_branch(je, reslab);
2 7u83 5456
    }
5457
  }
5458
 
5459
  if (test_ov) {		/* avoid most_neg divide by -1 trap */
7 7u83 5460
    int divlab = next_lab();
2 7u83 5461
    if (reslab == 0)
5462
      reslab = next_lab();
7 7u83 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);
2 7u83 5467
    simple_set_label(divlab);
5468
  }
5469
 
7 7u83 5470
  if (!eq_where(dest, reg1) && regsinuse & 0x2 && sz > 8) {
2 7u83 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;
7 7u83 5479
    invalidate_dest(reg1);
2 7u83 5480
  };
5481
 
5482
  if (sg) {			/* signed */
5483
    switch (sz) {
5484
      case 8:
7 7u83 5485
	ins1(idivb, 8, d);
2 7u83 5486
	break;
5487
      case 16:
5488
	move(swordsh, reg0, reg1);
5489
	ins2(sarw, 16, 16, mw(zeroe, 15), reg1);
7 7u83 5490
	ins1(idivw, 16, d);
2 7u83 5491
	break;
5492
      case 64:
5493
	failer(BADOP);
5494
      default:
5495
	move(slongsh, reg0, reg1);
5496
	ins2(sarl, 32, 32, mw(zeroe, 31), reg1);
7 7u83 5497
	ins1(idivl, 32, d);
2 7u83 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:
7 7u83 5529
	ins1(divb, 8, d);
2 7u83 5530
	break;
5531
      case 16:
7 7u83 5532
	ins2(xorw, 16, 16, reg1, reg1);
5533
	ins1(divw, 16, d);
2 7u83 5534
	break;
5535
      case 64:
7 7u83 5536
	ins0(pusheax);
2 7u83 5537
#ifdef NEWDWARF
5538
	if (diagnose && dwarf2 && no_frame)
5539
	  dw2_track_push();
5540
#endif
5541
	move(slongsh, reg1, reg0);
7 7u83 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);
2 7u83 5547
#ifdef NEWDWARF
5548
	if (diagnose && dwarf2 && no_frame)
5549
	  dw2_track_pop();
5550
#endif
5551
	break;
5552
      default:
7 7u83 5553
	ins2(xorl, 32, 32, reg1, reg1);
5554
	ins1(divl, 32, d);
2 7u83 5555
    }
5556
  };
7 7u83 5557
  invalidate_dest(reg0);
5558
  invalidate_dest(reg1);
5559
  invalidate_dest(reg2);
2 7u83 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)
7 7u83 5572
    simple_set_label(reslab);
2 7u83 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
 
7 7u83 5584
  move(sha, reg0, dest);
2 7u83 5585
  return;
5586
}
5587
 
5588
 
5589
void div2
7 7u83 5590
(shape sha, where bottom, where top, where dest)
2 7u83 5591
{
7 7u83 5592
  divit(sha, bottom, top, dest, 2, 0);
2 7u83 5593
  return;
5594
}
5595
 
5596
void div1
7 7u83 5597
(shape sha, where bottom, where top, where dest)
2 7u83 5598
{
7 7u83 5599
  divit(sha, bottom, top, dest, 1, 1);
2 7u83 5600
  return;
5601
}
5602
 
5603
void div0
7 7u83 5604
(shape sha, where bottom, where top, where dest)
2 7u83 5605
{
7 7u83 5606
  divit(sha, bottom, top, dest, 0, 1);
2 7u83 5607
  return;
5608
}
5609
 
5610
/* remainder after dividing top by bottom to dest */
5611
static void remit
7 7u83 5612
(shape sha, where bottom, where top, where dest, int whichrem, int use_mask)
2 7u83 5613
{
5614
  int  sz;
5615
  where d;
7 7u83 5616
  int sg = is_signed(sha);
2 7u83 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)) {
7 7u83 5625
    if (name(bottom.where_exp)!= val_tag || no(bottom.where_exp) == 0)
2 7u83 5626
      test_zero = 1;
7 7u83 5627
    if (sg && (name(bottom.where_exp)!= val_tag || no(bottom.where_exp) == -1))
2 7u83 5628
      test_ov = 1;
5629
  }
5630
 
5631
  cond1_set = 0;
5632
  cond2_set = 0;
5633
 
5634
  if ((use_mask || !sg) &&
7 7u83 5635
      name(bottom.where_exp) == val_tag && !isbigval(bottom.where_exp) &&
5636
     (v = no(bottom.where_exp), v > 0 && (v & (v - 1)) == 0)) {
2 7u83 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
    };
7 7u83 5645
    and(sha, top, mw(zeroe, lsmask[c]), dest);
2 7u83 5646
    return;
5647
  };
5648
 
7 7u83 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)) {
2 7u83 5652
    needs_lib64();
7 7u83 5653
    if (eq_where(top, reg0)) {
5654
      ins2(subl, 32, 32, mw(zeroe, 16), sp);
2 7u83 5655
      extra_stack += 128;
7 7u83 5656
      move(sha, top, mw(ind_sp.where_exp, -128));
5657
      move(sha, bottom, mw(ind_sp.where_exp, -64));
2 7u83 5658
      extra_stack -= 128;
5659
    }
5660
    else {
7 7u83 5661
      move(sha, bottom, pushdest);
2 7u83 5662
      extra_stack += 64;
7 7u83 5663
      move(sha, top, pushdest);
2 7u83 5664
      extra_stack -= 64;
5665
    }
7 7u83 5666
    callins(0, lib64_rem[sg + 2*(whichrem==1)], stack_dec);
5667
    ins2(addl, 32, 32, mw(zeroe, 16), sp);
2 7u83 5668
    if (overflow_e != nilexp && !optop(overflow_e)) {
7 7u83 5669
      ins2(movl, 32, 32, mw(lib64_error, 0), reg2);
2 7u83 5670
      if (PIC_code)
7 7u83 5671
        ins2(movl, 32, 32, ind_reg2, reg2);
5672
      ins2(testl, 32, 32, reg2, reg2);
5673
      test_exception(f_greater_than_or_equal, slongsh);
2 7u83 5674
    }
7 7u83 5675
    move(sha, reg0, dest);
2 7u83 5676
    return;
5677
  };
5678
 
5679
  if (sz == 8) {
5680
    if (sg)
7 7u83 5681
      change_var(swordsh, top, reg0);
2 7u83 5682
    else
7 7u83 5683
      change_var(uwordsh, top, reg0);
2 7u83 5684
  }
5685
  else
7 7u83 5686
    move(sha, top, reg0);
2 7u83 5687
 
5688
 
7 7u83 5689
  if (flinmem(bottom) || (eq_where(bottom, reg1) && sz > 8) || (whichrem==1 && sg)) {
2 7u83 5690
    d = reg2;
7 7u83 5691
    if (regsinuse & 0x4 && !eq_where(dest, reg2)) {
2 7u83 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;
7 7u83 5706
      move(shb, bottom, reg2);
2 7u83 5707
      regsinuse = riu;
5708
    }
5709
    else
7 7u83 5710
      move(shb, bottom, reg2);
2 7u83 5711
  };
5712
 
5713
  if (test_zero) {		/* avoid divide by zero trap */
7 7u83 5714
    IGNORE cmp(shb, d, zero, f_not_equal, nilexp);
2 7u83 5715
    if (isov(overflow_e))
7 7u83 5716
      test_exception(f_not_equal, shb);
2 7u83 5717
    else {
5718
      reslab = next_lab();
7 7u83 5719
      simple_branch(je, reslab);
2 7u83 5720
    }
5721
  }
5722
 
5723
  if (test_ov) {		/* avoid most_neg divide by -1 trap */
7 7u83 5724
    int divlab = next_lab();
2 7u83 5725
    if (reslab == 0)
5726
      reslab = next_lab();
7 7u83 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);
2 7u83 5731
    simple_set_label(divlab);
5732
  }
5733
 
7 7u83 5734
  if (!eq_where(dest, reg1) && regsinuse & 0x2 && sz > 8) {
2 7u83 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;
7 7u83 5743
    invalidate_dest(reg1);
2 7u83 5744
  };
5745
 
5746
  if (sg) {			/* signed */
5747
    switch (sz) {
5748
      case 8:
7 7u83 5749
	ins1(idivb, 8, d);
2 7u83 5750
	break;
5751
      case 16:
5752
	move(swordsh, reg0, reg1);
5753
	ins2(sarw, 16, 16, mw(zeroe, 15), reg1);
7 7u83 5754
	ins1(idivw, 16, d);
2 7u83 5755
	break;
5756
      case 64:
5757
	failer(BADOP);
5758
      default:
5759
	move(slongsh, reg0, reg1);
5760
	ins2(sarl, 32, 32, mw(zeroe, 31), reg1);
7 7u83 5761
	ins1(idivl, 32, d);
2 7u83 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:
7 7u83 5796
	ins1(divb, 8, d);
2 7u83 5797
	break;
5798
      case 16:
7 7u83 5799
	ins2(xorw, 16, 16, reg1, reg1);
5800
	ins1(divw, 16, d);
2 7u83 5801
	break;
5802
      case 64:
7 7u83 5803
	ins0(pusheax);
2 7u83 5804
#ifdef NEWDWARF
5805
	if (diagnose && dwarf2 && no_frame)
5806
	  dw2_track_push();
5807
#endif
5808
	move(slongsh, reg1, reg0);
7 7u83 5809
	ins2(xorl, 32, 32, reg1, reg1);
5810
	ins1(divl, 32, d);
5811
	ins0(popeax);
2 7u83 5812
#ifdef NEWDWARF
5813
        if (diagnose && dwarf2 && no_frame)
5814
	  dw2_track_pop();
5815
#endif
7 7u83 5816
	ins1(divl, 32, d);
2 7u83 5817
	break;
5818
      default:
7 7u83 5819
	ins2(xorl, 32, 32, reg1, reg1);
5820
	ins1(divl, 32, d);
2 7u83 5821
    }
5822
  };
5823
  if (sz == 8)
7 7u83 5824
    ins0("movb %ah,%al");
2 7u83 5825
  else
5826
  if (sz == 64) {
5827
    move(slongsh, reg1, reg0);
7 7u83 5828
    ins2(xorl, 32, 32, reg1, reg1);
2 7u83 5829
  }
5830
  else
5831
    move(sha, reg1, reg0);
7 7u83 5832
  invalidate_dest(reg0);
5833
  invalidate_dest(reg1);
5834
  invalidate_dest(reg2);
2 7u83 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)
7 7u83 5848
    simple_set_label(reslab);
2 7u83 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
 
7 7u83 5860
  move(sha, reg0, dest);
2 7u83 5861
 
5862
  return;
5863
}
5864
 
5865
/* remainder after dividing top by bottom to dest */
5866
void rem2
7 7u83 5867
(shape sha, where bottom, where top, where dest)
2 7u83 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
7 7u83 5875
(shape sha, where bottom, where top, where dest)
2 7u83 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
7 7u83 5883
(shape sha, where bottom, where top, where dest)
2 7u83 5884
{
5885
  remit(sha, bottom, top, dest, 1, 1);
5886
  return;
5887
}
5888
 
5889
 
5890
/* move address of from to to */
5891
void mova
7 7u83 5892
(where from, where to)
2 7u83 5893
{
5894
  exp fe = from.where_exp;
5895
  exp holdfe = son(fe);
5896
 
5897
  cond1_set = 0;
5898
  cond2_set = 0;
5899
 
7 7u83 5900
  if (name(fe) == reff_tag &&
2 7u83 5901
      name (son (fe)) != ident_tag) {/* add on offset from reff */
7 7u83 5902
    mova(mw(son(fe), from.where_off + no(fe)), to);
2 7u83 5903
    return;
5904
  };
5905
 
5906
  if (name (to.where_exp) == apply_tag) {	/* pushing */
7 7u83 5907
    if (!PIC_code && name(fe) == cont_tag &&
5908
         name(son(fe))!= ident_tag &&
5909
	(name(son(fe))!= name_tag || !isvar(son(son(fe)))) &&
2 7u83 5910
	((extra_stack == 0 && from.where_off == 0) ||
7 7u83 5911
	  !eq_where(mw(son(fe), 0), sp))) {
5912
      contop(fe, 0, to);
5913
      ins1lit(pushl,  32, mw(son(fe), from.where_off));
2 7u83 5914
#ifdef NEWDWARF
5915
      if (diagnose && dwarf2 && no_frame)
5916
	dw2_track_push();
5917
#endif
7 7u83 5918
      end_contop();
2 7u83 5919
      son(fe) = holdfe;
5920
      return;
5921
    };
7 7u83 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);
2 7u83 5926
#ifdef NEWDWARF
5927
      if (diagnose && dwarf2 && no_frame)
5928
	dw2_track_push();
5929
#endif
7 7u83 5930
      end_contop();
2 7u83 5931
      son(fe) = holdfe;
5932
      return;
5933
    };
7 7u83 5934
    mova(from, reg0);
5935
    ins1(pushl,  32, reg0);
2 7u83 5936
#ifdef NEWDWARF
5937
    if (diagnose && dwarf2 && no_frame)
5938
      dw2_track_push();
5939
#endif
5940
    return;
5941
  };
5942
 
5943
 
7 7u83 5944
  if (inmem(to)) {
5945
    mova(from, reg0);
5946
    move(slongsh, reg0, to);
2 7u83 5947
    return;
5948
  };
5949
 
7 7u83 5950
  if (!PIC_code && name(fe) == name_tag && isvar(son(fe)) &&
5951
      isglob(son(fe))) {
5952
    move(slongsh, from, to);
2 7u83 5953
    return;
5954
  };
5955
 
7 7u83 5956
  contop(from.where_exp, 0, to);
2 7u83 5957
 
7 7u83 5958
  if (name(fe) == name_tag && !isvar(son(fe)) && ptno(son(fe)) == reg_pl)
2 7u83 5959
    add(slongsh, mw(fe, 0), mw(zeroe, from.where_off/8), to);
5960
  else
7 7u83 5961
    ins2(leal,  32,  32, from, to);
2 7u83 5962
 
7 7u83 5963
  invalidate_dest(to);
5964
  end_contop();
2 7u83 5965
  son(fe) = holdfe;
5966
  return;
5967
}
5968
 
5969
int   adjust_pos
7 7u83 5970
(exp e, int nbits)
2 7u83 5971
{
5972
  int   pos;
5973
  UNUSED(nbits);
7 7u83 5974
  pos = no(e)% 8;
5975
  no(e) -= pos;
5976
  return(pos);
2 7u83 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
7 7u83 5983
(exp e, int nbits)
2 7u83 5984
{
7 7u83 5985
  if (name(e) == reff_tag ||
5986
      name(e) == name_tag)
5987
    return(adjust_pos(e, nbits));
2 7u83 5988
 
7 7u83 5989
  if (name(e) == ident_tag) {
5990
    if (name(bro(son(e))) == reff_tag)
5991
      return(adjust_pos(bro(son(e)), nbits));
2 7u83 5992
 
7 7u83 5993
    if (name(bro(son(e))) == ident_tag)
5994
      return bit_pos_cont(bro(son(e)), nbits);
2 7u83 5995
 
7 7u83 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));
2 7u83 6000
 
7 7u83 6001
    if (name(son(e)) == name_tag)
6002
      return(adjust_pos(son(e), nbits));
2 7u83 6003
 
7 7u83 6004
    return(0);
2 7u83 6005
  };
6006
 
7 7u83 6007
  failer(BAD_BIT_OPND);
6008
  return(0);
2 7u83 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
7 7u83 6018
(exp e, int nbits)
2 7u83 6019
{
7 7u83 6020
  if (name(e) == name_tag)
6021
    return(adjust_pos(e, nbits));
2 7u83 6022
 
7 7u83 6023
  if (name(e) == cont_tag || name(e) == ass_tag)
6024
    return(bit_pos_cont(son(e), nbits));
2 7u83 6025
 
7 7u83 6026
  if (name(e) == ident_tag)
6027
    return(0);
2 7u83 6028
 
7 7u83 6029
  failer(BAD_BIT_OPND);
6030
  return(0);
2 7u83 6031
}
6032
 
6033
void mem_to_bits
7 7u83 6034
(exp e, shape sha, where dest, ash stack)
2 7u83 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
 
7 7u83 6046
  dsh = (is_signed(sha))? slongsh : ulongsh;
2 7u83 6047
 
6048
  pos = bit_pos(e, nbits);
6049
 
6050
  lsn = 32 - nbits - pos;
7 7u83 6051
  rs = (is_signed(sha))? sarl : shrl;
2 7u83 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)
7 7u83 6088
      ins2(shll,  32,  32, mw(zeroe, lsn), dest);
6089
    invalidate_dest(dest);
2 7u83 6090
    /* shift it left to remove unwanted bits */
6091
    if (nbits != 32)
7 7u83 6092
      ins2(rs,  32,  32, mw(zeroe, 32 - nbits), dest);
2 7u83 6093
    /* shift it right to remove unwanted bits and propagate sign if
6094
       necessary */
7 7u83 6095
    invalidate_dest(dest);
2 7u83 6096
    return;
6097
  };
6098
 
6099
  move (move_sh, mw (e, 0), reg0);/* move e to reg0 */
6100
  if (lsn != 0)
7 7u83 6101
    ins2(shll,  32,  32, mw(zeroe, lsn), reg0);
6102
  invalidate_dest(reg0);
2 7u83 6103
  /* shift it left to remove unwanted bits */
6104
  if (nbits != 32)
7 7u83 6105
    ins2(rs,  32,  32, mw(zeroe, 32 - nbits), reg0);
2 7u83 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
7 7u83 6113
(exp e, exp d, ash stack)
2 7u83 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
 
7 7u83 6125
  pos = bit_pos(d, nbits);
2 7u83 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
 
7 7u83 6141
  if (name(e) == int_to_bitf_tag && name(son(e)) == val_tag) {
6142
    if (no(son(e)) == lsmask[nbits]) {
2 7u83 6143
      /* if we are assigning all ones, just or them in */
7 7u83 6144
      or(move_sh, mw(zeroe, k), dest, dest);
2 7u83 6145
      return;
6146
    };
7 7u83 6147
    if (no(son(e)) == 0) {
2 7u83 6148
      /* if we are assigning all ones, just or them in */
6149
      k = ~k;
6150
      if ((pos+nbits) <= 8)
6151
        k &= 0xff;
7 7u83 6152
      and(move_sh, mw(zeroe, k), dest, dest);
2 7u83 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));
7 7u83 6171
         move(osh, reg0, dest);
2 7u83 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);
7 7u83 6185
    and(slongsh, mw(zeroe, lsmask[nbits]), reg0, reg0);
2 7u83 6186
    /* mask it to the right size */
6187
    if (pos != 0)
7 7u83 6188
      ins2(shll,  32,  32, mw(zeroe, pos), reg0);
6189
    invalidate_dest(reg0);
2 7u83 6190
    /* shift it into position */
6191
    keep_short = 0;	/* stop use of reg0 by and */
7 7u83 6192
    and(move_sh, mw(zeroe, mask), dest, dest);
2 7u83 6193
    add (move_sh, reg0, dest, dest);/* and add it into the dest */
6194
    return;
6195
  }
6196
  else {
7 7u83 6197
    k = (no(e) & lsmask[nbits]) << pos;
2 7u83 6198
    /* constant bits we are assigning */
6199
    if (k == 0)
6200
      return;			/* if we are assigning zero we don't need
6201
				   anything more */
7 7u83 6202
    move(slongsh, mw(zeroe, k), reg0);
2 7u83 6203
    /* we don't need this move to reg0 since add looks after this better
6204
    */
6205
    keep_short = 0;
7 7u83 6206
    and(move_sh, mw(zeroe, mask), dest, dest);
2 7u83 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
7 7u83 6219
(shape sha, unsigned char op, int rev, where wh)
2 7u83 6220
{
6221
  exp hold = son(wh.where_exp);
7 7u83 6222
  contop(wh.where_exp, 0, reg0);
2 7u83 6223
  if (name (sha) == shrealhd) {	/* floats */
6224
    switch (op) {
6225
      case fplus_tag:
7 7u83 6226
	ins1(fadds,  32, wh);
6227
	end_contop();
2 7u83 6228
	son(wh.where_exp) = hold;
6229
	return;
6230
      case fminus_tag:
6231
	if (rev)
7 7u83 6232
	  ins1(fsubrs,  32, wh);
2 7u83 6233
	else
7 7u83 6234
	  ins1(fsubs,  32, wh);
6235
	end_contop();
2 7u83 6236
	son(wh.where_exp) = hold;
6237
	return;
6238
      case fmult_tag:
7 7u83 6239
	ins1(fmuls,  32, wh);
6240
	end_contop();
2 7u83 6241
	son(wh.where_exp) = hold;
6242
	return;
6243
      case fdiv_tag:
6244
	if (rev)
7 7u83 6245
	  ins1(fdivrs,  32, wh);
2 7u83 6246
	else
7 7u83 6247
	  ins1(fdivs,  32, wh);
6248
	end_contop();
2 7u83 6249
	son(wh.where_exp) = hold;
6250
	return;
6251
      default:
7 7u83 6252
	failer(BAD_FLOP);
6253
	end_contop();
2 7u83 6254
	son(wh.where_exp) = hold;
6255
	return;
6256
    };
6257
  };
6258
 
6259
  switch (op) {			/* doubles */
6260
    case fplus_tag:
7 7u83 6261
      ins1(faddl,  64, wh);
6262
      end_contop();
2 7u83 6263
      son(wh.where_exp) = hold;
6264
      return;
6265
    case fminus_tag:
6266
      if (rev)
7 7u83 6267
	ins1(fsubrl,  64, wh);
2 7u83 6268
      else
7 7u83 6269
	ins1(fsubl,  64, wh);
6270
      end_contop();
2 7u83 6271
      son(wh.where_exp) = hold;
6272
      return;
6273
    case fmult_tag:
7 7u83 6274
      ins1(fmull,  64, wh);
6275
      end_contop();
2 7u83 6276
      son(wh.where_exp) = hold;
6277
      return;
6278
    case fdiv_tag:
6279
      if (rev)
7 7u83 6280
	ins1(fdivrl,  64, wh);
2 7u83 6281
      else
7 7u83 6282
	ins1(fdivl,  64, wh);
6283
      end_contop();
2 7u83 6284
      son(wh.where_exp) = hold;
6285
      return;
6286
    default:
7 7u83 6287
      failer(BAD_FLOP);
6288
      end_contop();
2 7u83 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
7 7u83 6300
(unsigned char op, int rev, where wh, where d, int and_pop)
2 7u83 6301
{
6302
  switch (op) {
6303
    case fplus_tag:
6304
      if (and_pop) {
7 7u83 6305
	ins2(faddp, 0, 0, wh, d);
2 7u83 6306
	pop_fl;
6307
      }
6308
      else
7 7u83 6309
	ins2(fadd, 0, 0, wh, d);
2 7u83 6310
      break;
6311
    case fminus_tag:
6312
      if (rev) {
6313
	if (and_pop) {
7 7u83 6314
	  ins2(fsubrp, 0, 0, wh, d);
2 7u83 6315
	  pop_fl;
6316
	}
6317
	else
7 7u83 6318
	  ins2(fsubr, 0, 0, wh, d);
2 7u83 6319
      }
6320
      else {
6321
	if (and_pop) {
7 7u83 6322
	  ins2(fsubp, 0, 0, wh, d);
2 7u83 6323
	  pop_fl;
6324
	}
6325
	else
7 7u83 6326
	  ins2(fsub, 0, 0, wh, d);
2 7u83 6327
      };
6328
      break;
6329
    case fmult_tag:
6330
      if (and_pop) {
7 7u83 6331
	ins2(fmulp, 0, 0, wh, d);
2 7u83 6332
	pop_fl;
6333
      }
6334
      else
7 7u83 6335
	ins2(fmul, 0, 0, wh, d);
2 7u83 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:
7 7u83 6356
      failer(BAD_FLOP);
2 7u83 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
7 7u83 6368
(unsigned char op, shape sha, where arg1, where arg2, where dest, exp last_arg)
2 7u83 6369
{
7 7u83 6370
  int   m1 = flinmem(arg1);
6371
  int   m2 = flinmem(arg2);
6372
  int   m3 = flinmem(dest);
2 7u83 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:
7 7u83 6398
      move(sha, arg2, flstack);
6399
      fopm(sha, op, 0, arg1);
2 7u83 6400
 
7 7u83 6401
      move(sha, flstack, dest);
2 7u83 6402
      return;
6403
    case 4:
7 7u83 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);
2 7u83 6408
 
6409
	  return;
6410
	};
7 7u83 6411
	move(sha, arg1, flstack);
2 7u83 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
 
7 7u83 6419
      if (use_pop(last_arg, arg2.where_exp) == 2) {
6420
	fopm(sha, op, 0, arg1);
2 7u83 6421
 
7 7u83 6422
	move(sha, flstack, dest);
2 7u83 6423
	return;
6424
      };
6425
 
7 7u83 6426
      move(sha, arg1, flstack);
2 7u83 6427
      fopr (op, 1, arg2, flstack, 0); /* 2: fdivr st(2),st */
6428
 
7 7u83 6429
      move(sha, flstack, dest);
2 7u83 6430
      return;
6431
    case 2:
7 7u83 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);
2 7u83 6436
 
6437
	  return;
6438
	};
7 7u83 6439
	move(sha, arg2, flstack);
2 7u83 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:
7 7u83 6446
      if (use_pop(last_arg, arg1.where_exp) == 2) {
6447
	fopm(sha, op, 1, arg2);
2 7u83 6448
 
7 7u83 6449
	move(sha, flstack, dest);
2 7u83 6450
	return;
6451
      };
6452
 
7 7u83 6453
      move(sha, arg2, flstack);
2 7u83 6454
      fopr (op, 0, arg1, flstack, 0); /* 4: fdiv st(2),st */
6455
 
7 7u83 6456
      move(sha, flstack, dest);
2 7u83 6457
      return;
6458
    case 0:
6459
    case 1:
6460
      {
6461
	int   up1;
6462
	int   up2;
7 7u83 6463
	up1 = use_pop_ass(last_arg, arg1.where_exp);
6464
	up2 = use_pop_ass(last_arg, arg2.where_exp);
2 7u83 6465
 
6466
	if (tst == 0) {
7 7u83 6467
	  int  fd1 = get_reg_no(in_fl_reg(arg1.where_exp));
6468
	  int  fd2 = get_reg_no(in_fl_reg(arg2.where_exp));
2 7u83 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;
7 7u83 6483
	    fd2 = in_fl_reg(arg2.where_exp);
6484
	    if (get_reg_no(fd2)!= fstack_pos) {
2 7u83 6485
	      if (tst == 0) {
6486
	        fopr (op, 1, arg2, flstack, 0); /* 9: fdivr st(1),st */
7 7u83 6487
	        move(sha, flstack, dest);
2 7u83 6488
	        return;
6489
	      }
6490
	      else
6491
	      if (up2 == 1) {
6492
	        fopr (op, 1, flstack, arg2, 1); /* 7: divrp st,st(1) */
7 7u83 6493
	        move(sha, flstack, dest);
2 7u83 6494
	        return;
6495
	      };
6496
	    };
6497
	  };
6498
 
6499
	  if (up2 == 2) {
6500
	    int  fd1;
7 7u83 6501
	    fd1 = in_fl_reg(arg1.where_exp);
6502
	    if (get_reg_no(fd1)!= fstack_pos) {
2 7u83 6503
	      if (tst == 0) {
6504
	        fopr (op, 0, arg1, flstack, 0); /* 10: fdiv st(2), st */
7 7u83 6505
	        move(sha, flstack, dest);
2 7u83 6506
	        return;
6507
	      }
6508
	      else
6509
	      if (up1 == 1) {
6510
	        fopr (op, 0, flstack, arg1, 1); /* untested */
7 7u83 6511
	        move(sha, flstack, dest);
2 7u83 6512
	        return;
6513
	      }
6514
	      else {
6515
		fopr(op, 0, arg1, flstack, 0); /* 6: fdiv st(2),st */
7 7u83 6516
		move(sha, flstack, dest);
2 7u83 6517
		return;
6518
	      };
6519
	    };
6520
	  };
6521
	};
6522
 
6523
 
7 7u83 6524
	move(sha, arg2, flstack);
2 7u83 6525
	fopr (op, 0, arg1, flstack, 0); /* 5: fdiv st(2),st */
6526
 
7 7u83 6527
	move(sha, flstack, dest);
2 7u83 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
7 7u83 6540
(unsigned char op, shape sha, exp arglist, where dest)
2 7u83 6541
{
6542
  exp arg1 = arglist;
6543
  exp arg2 = bro(arg1);
6544
  if (last (arg1)) {	/* only one arg, so just move to dest */
7 7u83 6545
    move(sha, mw(arg1, 0), dest);
2 7u83 6546
    return;
6547
  }
6548
  if (last (arg2)) {	/* two args */
7 7u83 6549
    fl_binop(op, sha, mw(arg1, 0), mw(arg2, 0), dest, arg2);
2 7u83 6550
    return;
6551
  }
7 7u83 6552
  move(sha, mw(arg1, 0), flstack);
2 7u83 6553
  for (;;) {
7 7u83 6554
    move(sha, mw(arg2, 0), flstack);
2 7u83 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:
7 7u83 6562
	   failer(BAD_FLOP); break;
2 7u83 6563
      };
6564
    pop_fl;
7 7u83 6565
    if (last(arg2))break;
2 7u83 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
7 7u83 6584
(int mode, int ul, int sz)
2 7u83 6585
{
6586
  if (mode == 0 || mode == 4) {
7 7u83 6587
    sub(slongsh, mw(zeroe, sz/8), sp, sp);
2 7u83 6588
    extra_stack += sz;
6589
    check_stack_max;
6590
  }
6591
  else {
7 7u83 6592
    sub(slongsh, mw(zeroe,(sz+32) /8), sp, sp);
2 7u83 6593
    extra_stack += (sz+32);
6594
    check_stack_max;
7 7u83 6595
    ins1(fstcw, size16, mw(ind_sp.where_exp,(- (sz+32))));
2 7u83 6596
    if (ul && mode ==3) {	/* round toward zero unsigned */
6597
      int labpos = next_lab();
6598
      int labend = next_lab();
7 7u83 6599
      ins0(ftst);
6600
      ins1(fnstsw, 16, reg0);
2 7u83 6601
      testah(flpt_test_no[f_less_than]);
7 7u83 6602
      move(swordsh, mw(ind_sp.where_exp,(- (sz+32))), reg0);
6603
      simple_branch(jpe, labpos);
2 7u83 6604
      or (swordsh, mw (zeroe, (mode << 10)), reg0, reg0);  /* neg, round toward zero */
7 7u83 6605
      simple_branch(jmp, labend);
6606
      simplest_set_lab(labpos);
2 7u83 6607
      or (swordsh, mw (zeroe, (1 << 10)), reg0, reg0);  /* pos, round down */
7 7u83 6608
      simplest_set_lab(labend);
2 7u83 6609
    }
6610
    else {
7 7u83 6611
      move(swordsh, mw(ind_sp.where_exp,(- (sz+32))), reg0);
6612
      or(swordsh, mw(zeroe,(mode << 10)), reg0, reg0);
2 7u83 6613
    };
7 7u83 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))));
2 7u83 6617
  };
6618
  if (ul) {
6619
    if (sz == 64) {
7 7u83 6620
      move(doublesh, mw(sllmaxe, 0), flstack);
2 7u83 6621
      ins0("fsubrp %st,%st(1)");
6622
      pop_fl;
6623
    }
6624
    else
7 7u83 6625
      ins1(fsubl, size64, mw(smaxe, 0));
2 7u83 6626
  };
7 7u83 6627
  ins0(frndint);
6628
  ins1((sz == 64 ? fistpll : fistpl), sz, mw(ind_sp.where_exp,(-sz)));
2 7u83 6629
  if (mode != 0 && mode != 4) {
7 7u83 6630
    ins1(fldcw, size16, mw(ind_sp.where_exp,(- (sz+32))));
6631
    add(slongsh, mw(zeroe, 4), sp, sp);
2 7u83 6632
    extra_stack -= 32;
6633
  };
6634
  invalidate_dest(ind_sp);
6635
  return;
6636
}
6637
 
6638
 
6639
static  void roundit
7 7u83 6640
(shape sha, where from, where to, int mode)
2 7u83 6641
{
7 7u83 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;
2 7u83 6645
 
6646
  cond1_set = 0;
6647
  cond2_set = 0;
6648
 
7 7u83 6649
  move(shfrom, from, flstack);
2 7u83 6650
 
7 7u83 6651
  round_code(mode, ul, sz);
2 7u83 6652
  if (ul) {
7 7u83 6653
    xor(ulongsh, mw(ind_sp.where_exp, -32), mw(zeroe,(int)((unsigned int)1<<31)),
2 7u83 6654
	mw(ind_sp.where_exp, -32));
6655
  }
6656
  pop_fl;
7 7u83 6657
  if (flinmem(to)) {
6658
    move(sha, mw(ind_sp.where_exp, -sz), reg0);
2 7u83 6659
    invalidate_dest(reg0);
7 7u83 6660
    add(slongsh, mw(zeroe, sz/8), sp, sp);
2 7u83 6661
    extra_stack -= sz;
7 7u83 6662
    move(sha, reg0, to);
2 7u83 6663
  }
6664
  else
6665
   {
7 7u83 6666
    move(sha, mw(ind_sp.where_exp, -sz), to);
6667
    add(slongsh, mw(zeroe, sz/8), sp, sp);
2 7u83 6668
    extra_stack -= sz;
6669
   };
6670
  return;
6671
}
6672
 
6673
 
6674
/* floating point round */
6675
void frnd0
7 7u83 6676
(shape sha, where from, where to)
2 7u83 6677
{
7 7u83 6678
  roundit(sha, from, to, 0);
2 7u83 6679
  return;
6680
}
6681
 
6682
/* floating point round */
6683
void frnd1
7 7u83 6684
(shape sha, where from, where to)
2 7u83 6685
{
7 7u83 6686
  roundit(sha, from, to, 1);
2 7u83 6687
  return;
6688
}
6689
 
6690
/* floating point round */
6691
void frnd2
7 7u83 6692
(shape sha, where from, where to)
2 7u83 6693
{
7 7u83 6694
  roundit(sha, from, to, 2);
2 7u83 6695
  return;
6696
}
6697
 
6698
/* floating point round */
6699
void frnd3
7 7u83 6700
(shape sha, where from, where to)
2 7u83 6701
{
7 7u83 6702
  roundit(sha, from, to, 3);
2 7u83 6703
  return;
6704
}
6705
 
6706
/* floating point round */
6707
void frnd4
7 7u83 6708
(shape sha, where from, where to)
2 7u83 6709
{
7 7u83 6710
  roundit(sha, from, to, 4);
2 7u83 6711
  return;
6712
}
6713
 
6714
/* float the integer from, result to */
6715
void floater
7 7u83 6716
(shape sha, where from, where to)
2 7u83 6717
{
7 7u83 6718
  shape shfrom = sh(from.where_exp);
2 7u83 6719
  int  szf;
6720
  int im;
6721
  exp holdfe;
6722
  szf = shape_size(shfrom);
7 7u83 6723
  im = inmem(from);
2 7u83 6724
 
6725
 
6726
  if (!im || szf < 32) {
6727
    if (szf < 32) {
7 7u83 6728
      change_var(slongsh, from, reg0);
6729
      ins1(pushl,  32, reg0);
2 7u83 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) {
7 7u83 6738
	ins0(pushedx);
2 7u83 6739
#ifdef NEWDWARF
6740
	if (diagnose && dwarf2 && no_frame)
6741
	  dw2_track_push();
6742
#endif
7 7u83 6743
	ins0(pusheax);
2 7u83 6744
#ifdef NEWDWARF
6745
	if (diagnose && dwarf2 && no_frame)
6746
	  dw2_track_push();
6747
#endif
6748
      }
6749
      else {
7 7u83 6750
	ins1(pushl, szf, from);
2 7u83 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);
7 7u83 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);
2 7u83 6767
    if (szf == 64) {
7 7u83 6768
      move(doublesh, mw(sllmaxe, 0), flstack);
2 7u83 6769
      ins0("faddp %st,%st(1)");
6770
    }
6771
    else
7 7u83 6772
      ins1(faddl, size64, mw(dlongmaxe, 0));
6773
    simple_set_label(lab);
2 7u83 6774
  };
7 7u83 6775
  end_contop();
2 7u83 6776
 
6777
  if (!im || szf < 32) {
7 7u83 6778
    ins2(addl,  32,  32, mw(zeroe,(szf == 64 ? 8 : 4)), sp);
2 7u83 6779
  };
6780
  push_fl;
7 7u83 6781
  move(sha, flstack, to);
2 7u83 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
7 7u83 6790
(shape sha, where from, where to)
2 7u83 6791
{
7 7u83 6792
  shape shfrom = sh(from.where_exp);
2 7u83 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 */
7 7u83 6800
  move(shfrom, from, flstack);
6801
  move(sha, flstack, to);
2 7u83 6802
  return;
6803
}
6804
 
6805
/* floating point negate */
6806
void fl_neg
7 7u83 6807
(shape sha, where from, where to)
2 7u83 6808
{
7 7u83 6809
  int  f1 = in_fl_reg(from.where_exp);
6810
  int  f2 = in_fl_reg(to.where_exp);
2 7u83 6811
 
6812
 
6813
  if (f1 != 0 && f2 != 0 &&
7 7u83 6814
      get_reg_no(f1) == fstack_pos &&
6815
      get_reg_no(f2) == fstack_pos) {
6816
    ins0(fchs);
2 7u83 6817
    return;
6818
  };
7 7u83 6819
  move(sha, from, flstack);
6820
  ins0(fchs);
6821
  move(sha, flstack, to);
2 7u83 6822
  return;
6823
}
6824
 
6825
/* floating point abs */
6826
void fl_abs
7 7u83 6827
(shape sha, where from, where to)
2 7u83 6828
{
7 7u83 6829
  int  f1 = in_fl_reg(from.where_exp);
6830
  int  f2 = in_fl_reg(to.where_exp);
2 7u83 6831
 
6832
 
6833
  if (f1 != 0 && f2 != 0 &&
7 7u83 6834
      get_reg_no(f1) == fstack_pos &&
6835
      get_reg_no(f2) == fstack_pos) {
6836
    ins0(fabs);
2 7u83 6837
    return;
6838
  };
7 7u83 6839
  move(sha, from, flstack);
6840
  ins0(fabs);
6841
  move(sha, flstack, to);
2 7u83 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
7 7u83 6861
(shape sha, where pos, where neg, exp e)
2 7u83 6862
{
6863
				/* can improve this to use other
6864
				   comparison instructions */
6865
  cond1_set = 0;
6866
  cond2_set = 0;
7 7u83 6867
  move(sha, neg, flstack);
6868
  move(sha, pos, flstack);
6869
  ins0(fcompp);
2 7u83 6870
 
7 7u83 6871
  ins1(fnstsw,  16, reg0);
2 7u83 6872
 
6873
  testah(flpt_test_no[test_number(e)]);
6874
 
7 7u83 6875
  invalidate_dest(reg0);
2 7u83 6876
  pop_fl;
6877
  pop_fl;
6878
  return;
6879
}
6880
 
6881
/* use test instruction */
6882
void test
7 7u83 6883
(shape sha, where a, where b)
2 7u83 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
 
7 7u83 6905
  if (inmem(a) && inmem(b)) {
2 7u83 6906
    hold = son(b.where_exp);
7 7u83 6907
    move(sha, a, reg0);
6908
    contop(b.where_exp, 1, reg0);
6909
    ins2(t, sz, sz, reg0, b);
6910
    end_contop();
2 7u83 6911
    son(b.where_exp) = hold;
6912
    return;
6913
  };
7 7u83 6914
  if (!inmem(b) && name(a.where_exp)!= val_tag) {
2 7u83 6915
    hold = son(a.where_exp);
7 7u83 6916
    contop(a.where_exp, (eq_where(reg0, a) || eq_where(reg0, b)),
2 7u83 6917
	reg0);
7 7u83 6918
    ins2(t, sz, sz, b, a);
6919
    end_contop();
2 7u83 6920
    son(a.where_exp) = hold;
6921
    return;
6922
  };
6923
  hold = son(b.where_exp);
7 7u83 6924
  contop(b.where_exp, (eq_where(reg0, a) || eq_where(reg0, b)),
2 7u83 6925
      reg0);
7 7u83 6926
  ins2(t, sz, sz, a, b);
6927
  end_contop();
2 7u83 6928
  son(b.where_exp) = hold;
6929
  return;
6930
}
6931
 
6932
 
6933
/* decrease the stack */
6934
void decstack
7 7u83 6935
(int longs)
2 7u83 6936
{
6937
 
7 7u83 6938
  ins2(subl,  32,  32, mw(zeroe,(longs / 8)), sp);
2 7u83 6939
  return;
6940
}
6941
 
6942
void long_jump
7 7u83 6943
(exp e)
2 7u83 6944
{
6945
  ins0(popebp);
6946
  ins0(ret);
6947
  return;
6948
}
6949
 
6950
 
6951
 
6952
static int fp_clear = 0;
6953
 
6954
void reset_fpucon
7 7u83 6955
(void)
2 7u83 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;
7 7u83 6966
  ins1(fldcw, 16, mw(ferrmem,0));
2 7u83 6967
  fpucon = normal_fpucon;
6968
}
6969
 
6970
static void set_fpucon
7 7u83 6971
(int mask, int val)
2 7u83 6972
{
6973
  if ((fpucon & mask) == val)
6974
    return;
6975
  fpucon = ((~mask & fpucon) | val);
6976
  if (ferrsize < 32)
6977
    ferrsize = 32;
7 7u83 6978
  move(uwordsh, mw(zeroe, fpucon), mw(ferrmem, 16));
6979
  ins1(fldcw, 16, mw(ferrmem,16));
2 7u83 6980
}
6981
 
6982
void setup_fl_ovfl
7 7u83 6983
(exp e)
2 7u83 6984
{
6985
  int traps = 0xd;
6986
  int ival;
6987
  int eprmask = 0x300;
6988
  if (errhandle(e) == 0) {
6989
    if (name(sh(e)) == doublehd)
7 7u83 6990
      set_fpucon(eprmask, eprmask);
2 7u83 6991
    return;
6992
  }
6993
  if (!fp_clear && !optop(e)) {
6994
    ins0(fclex);
6995
    fp_clear = 1;
6996
  }
7 7u83 6997
  ival = (istrap(e)? 0 : traps);
2 7u83 6998
  if (name(sh(e)) == doublehd || name(sh(e)) == s64hd || name(sh(e)) == u64hd)
7 7u83 6999
    set_fpucon((eprmask | traps), (eprmask | ival));
2 7u83 7000
  else
7 7u83 7001
    set_fpucon(traps, ival);
2 7u83 7002
  return;
7003
}
7004
 
7005
void test_fl_ovfl
7 7u83 7006
(exp e, where dest)
2 7u83 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)
7 7u83 7022
	ins1(fstl, 64, m);
2 7u83 7023
      else
7 7u83 7024
	ins1(fsts, 32, m);
2 7u83 7025
    }
7026
    else {
7 7u83 7027
      move(sh(e), dest, m);
2 7u83 7028
      if (optop(e))		/* replace by suitable value */
7 7u83 7029
	move(sh(e), m, dest);
2 7u83 7030
    }
7031
  }
7032
  if (optop(e)) {
7033
    fp_clear = 0;
7034
    return;
7035
  }
7 7u83 7036
  if (isov(e)) {
7037
    if (eq_where(dest, reg0)) {
2 7u83 7038
      ins0(pusheax);
7039
#ifdef NEWDWARF
7040
      if (diagnose && dwarf2 && no_frame)
7041
	dw2_track_push();
7042
#endif
7043
    }
7 7u83 7044
    ins1(fstsw,  16, reg0);
2 7u83 7045
    ins2(testb, 8, 8, mw(zeroe, 13), reg0);
7046
		/* Overflow, Zero divide or Invalid  */
7 7u83 7047
    if (eq_where(dest, reg0)) {
2 7u83 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
7 7u83 7061
(void)
2 7u83 7062
{
7 7u83 7063
  return(make_extn("__trans386_stack_limit", ulongsh, 1));
2 7u83 7064
}
7065
 
7066
void checkalloc_stack
7 7u83 7067
(where sz, int b)
2 7u83 7068
{
7069
  /* uses reg1 */
7 7u83 7070
  int erlab = next_lab();
7071
  int cnlab = next_lab();
2 7u83 7072
  if (cont_stacklimit == nilexp) {
7 7u83 7073
    cont_stacklimit = make_extn("__trans386_stack_limit", ulongsh, 1);
2 7u83 7074
    if (!PIC_code)
7 7u83 7075
      cont_stacklimit = getexp(ulongsh, nilexp, 1, cont_stacklimit, nilexp, 0, 0, cont_tag);
2 7u83 7076
  }
7 7u83 7077
  ins2(movl, 32, 32, sp, reg1);
7078
  ins2(subl, 32, 32, sz, reg1);
7079
  simple_branch(jb, erlab);
2 7u83 7080
  if (PIC_code) {
7 7u83 7081
    ins2(movl, 32, 32, mw(cont_stacklimit, 0), reg0);
7082
    ins2(cmpl, 32, 32, ind_reg0, reg1);
7083
    simple_branch(ja, cnlab);
2 7u83 7084
  }
7085
  else {
7 7u83 7086
    ins2(cmpl, 32, 32, mw(cont_stacklimit, 0), reg1);
7087
    simple_branch(ja, cnlab);
2 7u83 7088
  }
7 7u83 7089
  simple_set_label(erlab);
7090
  trap_ins(f_stack_overflow);
7091
  simple_set_label(cnlab);
2 7u83 7092
  if (b)
7 7u83 7093
    ins2(movl, 32, 32, reg1, sp);
2 7u83 7094
}
7095
 
7096
/* Builtin functions. All args are operands */
7097
void special_ins
7 7u83 7098
(char * id, exp arg, where dest)
2 7u83 7099
{
7 7u83 7100
  if (!strcmp(id, "__trans386_special") && name(arg) == val_tag) {
2 7u83 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
  }
7 7u83 7115
  failer(BADOP);
2 7u83 7116
}
7117
 
7118
void save_stack
7 7u83 7119
(void)
2 7u83 7120
{
7121
  if (extra_stack || stack_dec)
7 7u83 7122
    failer("unclean stack");
7123
  ins2(movl, 32, 32, sp, firstlocal);
2 7u83 7124
}
7125
 
7126
void restore_stack
7 7u83 7127
(void)
2 7u83 7128
{
7129
  if (extra_stack || stack_dec)
7 7u83 7130
    failer("unclean stack");
7131
  ins2(movl, 32, 32, firstlocal, sp);
2 7u83 7132
}
7133
 
7134
void start_asm
7 7u83 7135
(void)
2 7u83 7136
{
7 7u83 7137
  outnl();
2 7u83 7138
#ifdef as_comment_symbol
7 7u83 7139
  outc('\t'); outc(as_comment_symbol);
7140
  outs(" ASM sequence start");
7141
  outnl();
2 7u83 7142
#endif
7143
  return;
7144
}
7145
 
7146
void end_asm
7 7u83 7147
(void)
2 7u83 7148
{
7149
#ifdef as_comment_symbol
7 7u83 7150
  outc('\t'); outc(as_comment_symbol);
7151
  outs(" ASM sequence ends");
7152
  outnl();
2 7u83 7153
#endif
7 7u83 7154
  outnl();
2 7u83 7155
  return;
7156
}
7157
 
7158
void asm_ins
7 7u83 7159
(exp e)
2 7u83 7160
{
7161
  if (name(son(e)) == string_tag)
7 7u83 7162
    outs(nostr(son(e)));
2 7u83 7163
  else {
7164
    int prev_use_bp = must_use_bp;
7165
    must_use_bp = 1;	/* scan2 must ensure !no_frame */
7 7u83 7166
    operand(shape_size(son(e)), mw(son(e), 0), 1, 0);
2 7u83 7167
    must_use_bp = prev_use_bp;
7168
  }
7169
  return;
7170
}