Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
6 7u83 1
/*
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
32
    		 Crown Copyright (c) 1997
33
 
34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
42
 
43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
45
 
46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
49
 
50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
53
 
54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
/* 80x86/codec.c */
62
 
63
/**********************************************************************
64
$Author: release $
65
$Date: 1998/01/17 15:55:51 $
66
$Revision: 1.1.1.1 $
67
$Log: codec.c,v $
68
 * Revision 1.1.1.1  1998/01/17  15:55:51  release
69
 * First version to be checked into rolling release.
70
 *
71
 * Revision 1.28  1997/08/23  13:45:19  pwe
72
 * initial ANDF-DE
73
 *
74
 * Revision 1.27  1996/10/07  13:30:54  pwe
75
 * push make_value, and env_offset v id out_of_line
76
 *
77
 * Revision 1.26  1996/05/20  14:30:00  pwe
78
 * improved 64-bit handling
79
 *
80
 * Revision 1.25  1996/05/13  12:51:44  pwe
81
 * undo premature commit
82
 *
83
 * Revision 1.23  1996/02/01  09:34:31  pwe
84
 * PIC oddities for AVS
85
 *
86
 * Revision 1.22  1996/01/31  12:24:11  pwe
87
 * is_crc v is_opnd  &  end_contop must not preceed move_reg
88
 *
89
 * Revision 1.21  1995/12/01  10:48:31  pwe
90
 * PIC static variables
91
 *
92
 * Revision 1.20  1995/10/11  17:16:08  pwe
93
 * error treatment for remainder
94
 *
95
 * Revision 1.19  1995/09/19  15:42:41  pwe
96
 * round, fp overflow etc
97
 *
98
 * Revision 1.18  1995/09/13  14:25:04  pwe
99
 * tidy for gcc
100
 *
101
 * Revision 1.17  1995/08/30  16:06:12  pwe
102
 * prepare exception trapping
103
 *
104
 * Revision 1.16  1995/08/23  09:42:21  pwe
105
 * track fpu control word for trap etc
106
 *
107
 * Revision 1.15  1995/08/14  13:53:15  pwe
108
 * several corrections, tail calls and error jumps
109
 *
110
 * Revision 1.14  1995/08/04  08:28:53  pwe
111
 * 4.0 general procs implemented
112
 *
113
 * Revision 1.13  1995/03/07  14:00:12  pwe
114
 * offset_pad byte->bit conversion
115
 *
116
 * Revision 1.12  1995/02/24  16:11:03  pwe
117
 * dynamic offsets, including mixed bit/byte representations
118
 *
119
 * Revision 1.11  1995/02/23  11:05:26  pwe
120
 * offset_div change variety after 32_bit division
121
 *
122
 * Revision 1.10  1995/02/13  11:16:56  pwe
123
 * REM etc should ignore overflow flag
124
 *
125
 * Revision 1.9  1995/02/10  14:36:39  pwe
126
 * consequence of correct test(reff,..) etc
127
 *
128
 * Revision 1.8  1995/02/10  12:58:11  pwe
129
 * correct test(reff,..) etc
130
 *
131
 * Revision 1.7  1995/02/08  17:21:03  pwe
132
 * remove incorrect overflow test after div
133
 *
134
 * Revision 1.6  1995/02/06  15:15:18  pwe
135
 * correct fp overflow check
136
 *
137
 * Revision 1.5  1995/02/02  15:17:21  pwe
138
 * implement offset_max as max
139
 *
140
 * Revision 1.4  1995/01/30  12:55:57  pwe
141
 * Ownership -> PWE, tidy banners
142
 *
143
 * Revision 1.3  1994/11/24  14:11:50  jmf
144
 * Cleared cond1_set after retcells
145
 *
146
 * Revision 1.2  1994/11/08  10:06:58  jmf
147
 * Added power not implemented
148
 *
149
 * Revision 1.1  1994/10/27  14:15:22  jmf
150
 * Initial revision
151
 *
152
 * Revision 1.1  1994/07/12  14:26:39  jmf
153
 * Initial revision
154
 *
155
**********************************************************************/
156
 
157
 
158
/**********************************************************************
159
 
160
                            codec.c
161
 
162
   codec produces code for operations which produce values.
163
   e is the operation and dest is where the result is to be put.
164
 
165
**********************************************************************/
166
 
167
#include "config.h"
168
#include "common_types.h"
169
 
170
#include "expmacs.h"
171
#include "exp.h"
172
#include "instr386.h"
173
#include "tags.h"
174
#include "operand.h"
175
#include "shapemacs.h"
176
#include "instrmacs.h"
177
#include "basicread.h"
178
#include "flags.h"
179
#include "coder.h"
180
#include "install_fns.h"
181
#include "codermacs.h"
182
#include "instr.h"
183
#include "flpt.h"
184
#include "messages_8.h"
185
#include "reg_record.h"
186
#include "readglob.h"
187
#include "externs.h"
188
 
189
#include "codec.h"
190
 
191
 
192
/* PROCEDURES */
193
 
194
/* returns true if is_o(e) but not a possible 80386 operand */
195
int
196
is_crc(exp e)
197
{
198
	/* make sure (is_o && is_crc->!is_opnd) */
199
	if (name(e) == name_tag) {
200
		if (isvar(son(e))) {
201
			return(!isglob(son(e)) || PIC_code);
202
		}
203
		/* else */
204
		return(son(son(e)) == nilexp ||
205
		       (isglob(son(e)) && PIC_code &&
206
			name(sh(son(e))) == prokhd &&
207
			!(brog(son(e))->dec_u.dec_val.extnamed)) ||
208
		       (name(son(son(e))) == ident_tag &&
209
			isparam(son(son(e)))));
210
	}
211
 
212
	if (name(e) == reff_tag || name(e) == field_tag) {
213
		return 1;
214
	}
215
 
216
	if (name(e) != cont_tag) {
217
		return 0;
218
	}
219
 
220
	if (name(son(e)) == cont_tag) {
221
		return 1;
222
	}
223
 
224
	return name(son(e)) == reff_tag && name(son(son(e))) == cont_tag;
225
}
226
 
227
 
228
/* op is a procedure for encoding a unary operation. If a is a possible 80386
229
   operand, uop applies this operator to produce the code for a, leaving the
230
   result in dest. sha gives the shape for the operation. If a is not a
231
   possible 80386 operand, then uop produces code for a to put it into eax
232
   (reg0) and then applies op to eax, putting the result into dest. */
233
void
234
uop(void(*op)(shape, where, where), shape sha, exp a, where dest, ash stack)
235
{
236
	if (!is_o(name(a)) || is_crc(a)) {
237
		where qw;
238
		if (!inmem(dest)) {
239
			qw.where_exp = copyexp(dest.where_exp);
240
		} else {
241
			qw.where_exp = copyexp(reg0.where_exp);
242
		}
243
		sh(qw.where_exp) = sha;
244
		qw.where_off = 0;
245
		coder(qw, stack, a);
246
		(*op)(sha, qw, dest);
247
		retcell(qw.where_exp);
248
		cond1_set = 0;
249
		return;
250
	}
251
	(*op)(sha, mw(a, 0), dest);
252
	return;
253
}
254
 
255
 
256
static int
257
no_reg_needed(exp e)
258
{
259
	if (name(e) == val_tag) {
260
		return 1;
261
	}
262
	if (name(e) == cont_tag && name(son(e)) == name_tag &&
263
	    isvar(son(son(e))) && ptno(son(son(e))) != reg_pl) {
264
		return 1;
265
	}
266
	if (name(e) == name_tag && !isvar(son(e)) && ptno(son(e)) != reg_pl) {
267
		return 1;
268
	}
269
	return 0;
270
}
271
 
272
 
273
/* op is a procedure for encoding a binary operation. Not more than one of a
274
   and b will not be a possible 80386 operand.  This has been ensured by scan2.
275
   If a and b are both possible 80386 operands, bop applies this operator to
276
   produce the code, leaving the result in dest.  sha gives the shape for the
277
   operation.  If either a or b is not a possible 80386 operand, then bop
278
   produces code for it to put it into eax (reg0) and then applies op to eax
279
   and the other operand, putting the result into dest. */
280
void
281
bop(void(*op)(shape, where, where, where), shape sha, exp a, exp b, where dest,
282
    ash stack)
283
{
284
	where qw;
285
 
286
	if (!is_o(name(a)) || is_crc(a)) {
287
		if (!inmem(dest) && no_reg_needed(b)) {
288
			qw.where_exp = copyexp(dest.where_exp);
289
		} else {
290
			qw.where_exp = copyexp(reg0.where_exp);
291
		}
292
		sh(qw.where_exp) = sha;
293
		qw.where_off = 0;
294
		coder(qw, stack, a);
295
		(*op)(sha, qw, mw(b, 0), dest);
296
		retcell(qw.where_exp);
297
		cond1_set = 0;
298
		return;
299
	}
300
	if (!is_o(name(b)) || is_crc(b)) {
301
		if (!inmem(dest) && no_reg_needed(a)) {
302
			qw.where_exp = copyexp(dest.where_exp);
303
		} else {
304
			qw.where_exp = copyexp(reg0.where_exp);
305
		}
306
		sh(qw.where_exp) = sha;
307
		qw.where_off = 0;
308
		coder(qw, stack, b);
309
		(*op)(sha, mw(a, 0), qw, dest);
310
		retcell(qw.where_exp);
311
		cond1_set = 0;
312
		return;
313
	}
314
 
315
	(*op)(sha, mw(a, 0), mw(b, 0), dest);
316
	return;
317
}
318
 
319
 
320
/* process the binary logical operation exp. op is the compiling procedure for
321
   the operation. It is commutative and associative, the operation takes a
322
   variable number of arguments. It is therefore necessary to avoid the mistake
323
   of assigning to the destination (dest) inappropriately if its value is used
324
   in the expression. At most one of the arguments will not be a possible 80386
325
   operand. If there is such an argument, logop precomputes it, putting the
326
   value into reg0. */
327
static void
328
logop(void(*op)(shape, where, where, where), exp e, where dest, ash stack)
329
{
330
	exp arg1 = son(e);
331
	exp arg2 = bro(arg1);
332
	shape sha = sh(e);
333
	exp t, u;
334
	where qw;
335
 
336
	if (last(arg1)) {
337
		coder(dest, stack, arg1);
338
		return;
339
	}
340
 
341
	/* just two arguments. */
342
	if (last (arg2)) {
343
		bop(op, sha, arg1, arg2, dest, stack);
344
		return;
345
	}
346
	/* need to take care about overlap between dest and args or to avoid
347
	   extra push. So use reg0. */
348
	qw.where_exp = copyexp(reg0.where_exp);
349
	sh(qw.where_exp) = sha;
350
	qw.where_off = 0;
351
	t = arg1;
352
	/* now look for an argument which is not a possible 80386 operand */
353
	while (1) {
354
		if (!is_o(name(t)) || is_crc(t)) {
355
			break;
356
		}
357
		if (last(t)) {
358
			t = nilexp;
359
			break;
360
		}
361
		t = bro(t);
362
	}
363
 
364
	/* all arguments are possible 80386 operands */
365
	if (t == nilexp) {
366
		(*op)(sha, mw(arg1, 0), mw(arg2, 0), qw);
367
		t = bro(arg2);
368
		while (!last(t)) {
369
			/* encode operations in turn */
370
			(*op) (sha, mw (t, 0), qw, qw);
371
			t = bro(t);
372
		}
373
		/* encode final operation */
374
		(*op) (sha, mw (t, 0), qw, dest);
375
		retcell(qw.where_exp);
376
		cond1_set = 0;
377
		return;
378
	}
379
 
380
	/* encode the single argument which is not a possible 80386 operend */
381
	coder (qw, stack, t);
382
	u = arg1;
383
	/* now encode the remaining operations */
384
	while (1) {
385
		if (t != u) {
386
			if (last(u) || (bro(u) == t && last(bro(u)))) {
387
				(*op)(sha, mw(u, 0), qw, dest);
388
			} else {
389
				(*op)(sha, mw(u, 0), qw, qw);
390
			}
391
		}
392
		if (last(u)) {
393
			break;
394
		}
395
		u = bro(u);
396
	}
397
	retcell(qw.where_exp);
398
	cond1_set = 0;
399
	return;
400
}
401
 
402
 
403
/* process the multiply operation exp. op is the compiling procedure for
404
   the operation. It is commutative and associative, the operation takes a
405
   variable number of arguments. It is therefore necessary to avoid the mistake
406
   of assigning to the destination (dest) inappropriately if its value is used
407
   in the expression. At most one of the arguments will not be a possible 80386
408
   operand. If there is such an argument, it is precomputed, putting the value
409
   into reg0. */
410
static void
411
multop(void(*op)(shape, where, where, where), exp e, where dest, ash stack)
412
{
413
	exp arg1 = son(e);
414
	exp arg2 = bro(arg1);
415
	exp t, u;
416
	where qw;
417
 
418
	if (last(arg1)) {
419
		coder(dest, stack, arg1);
420
		return;
421
	}
422
 
423
	/* just two arguments. */
424
	if (last (arg2)) {
425
		bop(op, sh(e), arg1, arg2, dest, stack);
426
		return;
427
	}
428
	/* need to take care about overlap between dest and args or to avoid
429
	   extra push. So use reg0. */
430
	qw.where_exp = copyexp(reg0.where_exp);
431
	sh(qw.where_exp) = sh(e);
432
	qw.where_off = 0;
433
	t = arg1;
434
	/* now look for an argument which is not a possible 80386 operand */
435
	while (1) {
436
		if (!is_o(name(t)) || is_crc(t)) {
437
			break;
438
		}
439
		if (last(t)) {
440
			t = nilexp;
441
			break;
442
		}
443
		t = bro(t);
444
	}
445
 
446
	/* all arguments are possible 80386 operands */
447
	if (t == nilexp) {
448
		(*op)(sh(e), mw(arg1, 0), mw(arg2, 0), qw);
449
		t = bro(arg2);
450
		while (!last(t)) {
451
			/* encode operations in turn */
452
			(*op) (sh (e), mw (t, 0), qw, qw);
453
			t = bro(t);
454
		}
455
		/* encode final operation */
456
		(*op) (sh (e), mw (t, 0), qw, dest);
457
		retcell(qw.where_exp);
458
		cond1_set = 0;
459
		return;
460
	}
461
 
462
	/* encode the single argument which is not a possible 80386 operend */
463
	coder (qw, stack, t);
464
	u = arg1;
465
	/* now encode the remaining operations */
466
	while (1) {
467
		if (t != u) {
468
			if (last(u) || (bro(u) == t && last(bro(u)))) {
469
				(*op)(sh(e), mw(u, 0), qw, dest);
470
			} else {
471
				(*op)(sh(e), mw(u, 0), qw, qw);
472
			}
473
		}
474
		if (last(u)) {
475
			break;
476
		}
477
		u = bro(u);
478
	}
479
	retcell(qw.where_exp);
480
	cond1_set = 0;
481
	return;
482
}
483
 
484
 
485
/* if a is a negation form b-son(a) otherwise b+a in dest */
486
static void
487
addsub(shape sha, where a, where b, where dest, exp e)
488
{
489
	UNUSED(e);
490
	if (name(a.where_exp) == neg_tag) {
491
		sub(sha, mw(son(a.where_exp), 0), b, dest);
492
	} else {
493
		add(sha, a, b, dest);
494
	}
495
	return;
496
}
497
 
498
 
499
/***********************************************************************
500
   codec outputs the code which evaulates e and puts the result into
501
   dest.
502
 ***********************************************************************/
503
 
504
/* encode e, putting the result into dest.  stack is the current stack level */
505
void
506
codec(where dest, ash stack, exp e)
507
{
508
	switch (name(e)) {
509
	case plus_tag: {
510
		/* at most one of the arguments will not be a possible 80386
511
		 * operand */
512
		exp arg1 = son(e);
513
		exp arg2 = bro(arg1);
514
		exp t, u, v;
515
		where qw;
516
		exp old_overflow_e = overflow_e;
517
 
518
		if (last (arg1)) {
519
			/* there is only one argument */
520
			coder(dest, stack, arg1);
521
			return;
522
		}
523
 
524
		if (!optop(e)) {
525
			overflow_e = e;
526
		}
527
 
528
		if (last(arg2) && is_o(name(arg1)) && !is_crc(arg1) &&
529
		    ((is_o(name(arg2)) && !is_crc(arg2)) ||
530
		     (name(arg2) == neg_tag && !is_crc(son(arg2)) &&
531
		      is_o(name(son(arg2)))))) {
532
			/* just two arguments. */
533
			addsub(sh(e), mw(arg2, 0), mw(arg1, 0), dest, e);
534
			overflow_e = old_overflow_e;
535
			return;
536
		}
537
		/* need to take care about overlap between dest and
538
		 * args or to avoid extra push. So use reg0. */
539
		t = arg1;
540
		qw.where_exp = copyexp(reg0.where_exp);
541
		sh(qw.where_exp) = sh(e);
542
		qw.where_off = 0;
543
 
544
		/* now look for argument which is not a possible 80386
545
		 * operand */
546
		while (1) {
547
			if ((!is_o(name(t)) || is_crc(t)) &&
548
			    (name(t) != neg_tag || !is_o(name(son(t))) ||
549
			     is_crc(son(t)))) {
550
				break;
551
			}
552
			if (last(t)) {
553
				t = nilexp;
554
				break;
555
			}
556
			t = bro(t);
557
		}
558
 
559
		if (t == nilexp && name(arg1) == neg_tag &&
560
		    name(arg2) == neg_tag) {
561
			t = arg1;
562
		}
563
 
564
		/* all arguments are possible 80386 operands */
565
		if (t == nilexp) {
566
			t = bro(arg2);
567
			if (name(arg1) == neg_tag) {
568
				addsub(sh(e), mw(arg1, 0), mw(arg2, 0),
569
				       (t == e) ? dest : qw, e);
570
			} else {
571
				addsub(sh(e), mw(arg2, 0), mw(arg1, 0),
572
				       (t == e) ? dest : qw, e);
573
			}
574
			if (t == e) {
575
				overflow_e = old_overflow_e;
576
				return;
577
			}
578
			while (!last(t)) {
579
				u = bro(t);
580
				addsub(sh(e), mw(t, 0), qw, qw, e);
581
				t = u;
582
			}
583
			addsub(sh(e), mw(t, 0), qw, dest, e);
584
			overflow_e = old_overflow_e;
585
			return;
586
		}
587
 
588
		/* encode the argument which is not a possible 80386
589
		 * operand */
590
		coder (qw, stack, t);
591
		u = arg1;
592
		/* now encode the remaining operations */
593
		while (1) {
594
			v = bro(u);
595
			if (t != u) {
596
				if (last(u) || (v == t && last(v))) {
597
					addsub(sh(e), mw(u, 0), qw, dest, e);
598
				} else {
599
					addsub(sh(e), mw(u, 0), qw, qw, e);
600
				}
601
			}
602
			if (last(u)) {
603
				break;
604
			}
605
			u = v;
606
		}
607
		retcell(qw.where_exp);
608
		cond1_set = 0;
609
		overflow_e = old_overflow_e;
610
		return;
611
	}
612
	case addptr_tag:
613
		/* use index operation */
614
		mova(mw(e, 0), dest);
615
		return;
616
	case chvar_tag: {
617
		exp a = son(e);
618
		exp old_overflow_e = overflow_e;
619
		if (!optop(e)) {
620
			overflow_e = e;
621
		}
622
		if (!is_o(name(a)) || is_crc(a)) {
623
			/* argument is not a possible 80386 operand, so
624
			 * evaluate it in reg0 */
625
			if (inmem(dest) ||
626
			    (shape_size(sh(a)) == 8 && bad_from_reg(dest)) ||
627
			    shape_size(sh(a)) == 64) {
628
				where qw;
629
				qw.where_exp = copyexp(reg0.where_exp);
630
				sh(qw.where_exp) = sh(a);
631
				qw.where_off = 0;
632
				coder(qw, stack, a);
633
				change_var_check(sh(e), qw, dest);
634
				overflow_e = old_overflow_e;
635
				retcell(qw.where_exp);
636
				cond1_set = 0;
637
				return;
638
			}
639
			coder(dest, stack, a);
640
			if (name(sh(e)) > name(sh(a)))
641
				change_var_sh(sh(e), sh(a), dest, dest);
642
			overflow_e = old_overflow_e;
643
			return;
644
		}
645
		change_var_check(sh(e), mw(a, 0), dest);
646
		overflow_e = old_overflow_e;
647
		return;
648
	}
649
	case minus_tag: {
650
		exp old_overflow_e = overflow_e;
651
		if (!optop(e)) {
652
			overflow_e = e;
653
		}
654
		bop(sub, sh(e), bro(son(e)), son(e), dest, stack);
655
		overflow_e = old_overflow_e;
656
		return;
657
	}
658
	case subptr_tag:
659
	case minptr_tag:
660
	case make_stack_limit_tag:
661
		bop(sub, sh(e), bro(son(e)), son(e), dest, stack);
662
		return;
663
	case mult_tag: {
664
		if (!optop(e)) {
665
			exp old_overflow_e = overflow_e;
666
			overflow_e = e;
667
			multop(multiply, e, dest, stack);
668
			overflow_e = old_overflow_e;
669
		} else {
670
			multop(mult, e, dest, stack);
671
		}
672
		return;
673
	}
674
	case div2_tag: {
675
		exp old_overflow_e = overflow_e;
676
		if (errhandle(e)) {
677
			overflow_e = e;
678
		}
679
		bop(div2, sh(e), bro(son(e)), son(e), dest, stack);
680
		overflow_e = old_overflow_e;
681
		return;
682
	}
683
	case div1_tag: {
684
		exp old_overflow_e = overflow_e;
685
		if (errhandle(e)) {
686
			overflow_e = e;
687
		}
688
		bop(div1, sh(e), bro(son(e)), son(e), dest, stack);
689
		overflow_e = old_overflow_e;
690
		return;
691
	}
692
	case div0_tag: {
693
		exp old_overflow_e = overflow_e;
694
		if (errhandle(e)) {
695
			overflow_e = e;
696
		}
697
		bop(div0, sh(e), bro(son(e)), son(e), dest, stack);
698
		overflow_e = old_overflow_e;
699
		return;
700
	}
701
	case neg_tag: {
702
		exp old_overflow_e = overflow_e;
703
		if (!optop(e)) {
704
			overflow_e = e;
705
		}
706
		uop(negate, sh(e), son(e), dest, stack);
707
		overflow_e = old_overflow_e;
708
		return;
709
	}
710
	case shl_tag: {
711
		exp old_overflow_e = overflow_e;
712
		overflow_e = e;
713
		if (!optop(e)) {
714
			overflow_e = e;
715
		}
716
		bop(shiftl, sh(e), bro(son(e)), son(e), dest, stack);
717
		overflow_e = old_overflow_e;
718
		return;
719
	}
720
	case shr_tag:
721
		bop(shiftr, sh(e), bro(son(e)), son(e), dest, stack);
722
		return;
723
	case rotl_tag:
724
		bop(rotatel, sh(e), bro(son(e)), son(e), dest, stack);
725
		return;
726
	case rotr_tag:
727
		bop(rotater, sh(e), bro(son(e)), son(e), dest, stack);
728
		return;
729
	case mod_tag: {
730
		exp old_overflow_e = overflow_e;
731
		if (errhandle(e)) {
732
			overflow_e = e;
733
		}
734
		bop(mod, sh(e), bro(son(e)), son(e), dest, stack);
735
		overflow_e = old_overflow_e;
736
		return;
737
	}
738
	case rem2_tag: {
739
		exp old_overflow_e = overflow_e;
740
		if (errhandle(e)) {
741
			overflow_e = e;
742
		}
743
		bop(rem2, sh(e), bro(son(e)), son(e), dest, stack);
744
		overflow_e = old_overflow_e;
745
		return;
746
	}
747
	case rem0_tag: {
748
		exp old_overflow_e = overflow_e;
749
		if (errhandle(e)) {
750
			overflow_e = e;
751
		}
752
		bop(rem0, sh(e), bro(son(e)), son(e), dest, stack);
753
		overflow_e = old_overflow_e;
754
		return;
755
	}
756
	case round_tag: {
757
		shape s = sh(e);
758
		where d;
759
		d = dest;
760
		if (shape_size(s) < 32) {
761
			s = slongsh;
762
			if (inmem(dest)) {
763
				d = reg0;
764
			}
765
		}
766
		setup_fl_ovfl(e);
767
		switch (round_number(e)) {
768
		case 0:
769
			uop(frnd0, s, son(e), d, stack);
770
			break;
771
		case 1:
772
			uop(frnd1, s, son(e), d, stack);
773
			break;
774
		case 2:
775
			uop(frnd2, s, son(e), d, stack);
776
			break;
777
		case 3:
778
			uop(frnd3, s, son(e), d, stack);
779
			break;
780
		case 4:
781
			uop(frnd4, s, son(e), d, stack);
782
			break;
783
		}
784
		test_fl_ovfl(e, d);
785
		if (name(s) != name(sh(e))) {
786
			exp old_overflow_e = overflow_e;
787
			if (!optop(e)) {
788
				overflow_e = e;
789
			}
790
			change_var_sh(sh(e), s, d, dest);
791
			overflow_e = old_overflow_e;
792
		}
793
		return;
794
	}
795
	case fplus_tag:
796
		setup_fl_ovfl(e);
797
		fl_multop(fplus_tag, sh(e), son(e), dest);
798
		test_fl_ovfl(e, dest);
799
		return;
800
	case fmult_tag:
801
		setup_fl_ovfl(e);
802
		fl_multop(fmult_tag, sh(e), son(e), dest);
803
		test_fl_ovfl(e, dest);
804
		return;
805
	case fminus_tag:
806
		setup_fl_ovfl(e);
807
		fl_binop(fminus_tag, sh(e), mw(bro(son(e)), 0), mw(son(e), 0),
808
			 dest, bro(son(e)));
809
		test_fl_ovfl(e, dest);
810
		return;
811
	case fdiv_tag:
812
		setup_fl_ovfl(e);
813
		fl_binop(fdiv_tag, sh(e), mw(bro(son(e)), 0), mw(son(e), 0),
814
			 dest, bro(son(e)));
815
		test_fl_ovfl(e, dest);
816
		return;
817
	case fneg_tag:
818
		setup_fl_ovfl(e);
819
		fl_neg(sh(e), mw(son(e), 0), dest);
820
		test_fl_ovfl(e, dest);
821
		return;
822
	case fabs_tag:
823
		setup_fl_ovfl(e);
824
		fl_abs(sh(e), mw(son(e), 0), dest);
825
		test_fl_ovfl(e, dest);
826
		return;
827
	case float_tag:
828
		setup_fl_ovfl(e);
829
		floater(sh(e), mw(son(e), 0), dest);
830
		test_fl_ovfl(e, dest);
831
		return;
832
	case chfl_tag:
833
		if (name(sh(e)) < name(sh(son(e)))) {
834
			setup_fl_ovfl(e);
835
		}
836
		changefl(sh(e), mw(son(e), 0), dest);
837
		if (name(sh(e)) < name(sh(son(e)))) {
838
			test_fl_ovfl(e, dest);
839
		}
840
		return;
841
	case and_tag:
842
		logop(and, e, dest, stack);
843
		return;
844
	case or_tag:
845
		logop(or, e, dest, stack);
846
		return;
847
	case xor_tag:
848
		logop(xor, e, dest, stack);
849
		return;
850
	case not_tag:
851
		uop(not, sh(e), son(e), dest, stack);
852
		return;
853
	case offset_pad_tag:
854
		if (al2(sh(son(e))) >= al2(sh(e))) {
855
			if (al2(sh(e)) != 1 || al2(sh(son(e))) == 1) {
856
				coder(dest, stack, son(e));
857
			} else {
858
				coder(reg0, stack, son(e));
859
				shiftl(slongsh, mw(zeroe, 3), reg0, dest);
860
			}
861
		} else {
862
			int al = al2(sh(e)) /8;
863
			coder(reg0, stack, son(e));
864
			if (al2(sh(son(e))) == 1) {
865
				add(slongsh, mw(zeroe, al*8 -1), reg0, reg0);
866
				shiftr(slongsh, mw(zeroe, 3), reg0, reg0);
867
			} else {
868
				add(slongsh, mw(zeroe, al-1), reg0, reg0);
869
			}
870
			and(slongsh, mw(zeroe, -al), reg0, dest);
871
		}
872
		return;
873
	case offset_add_tag:
874
		bop(add, sh(e), son(e), bro(son(e)), dest, stack);
875
		return;
876
	case abs_tag: {
877
		exp old_overflow_e = overflow_e;
878
		if (!optop(e)) {
879
			overflow_e = e;
880
		}
881
		uop(absop, sh(e), son(e), dest, stack);
882
		overflow_e = old_overflow_e;
883
		return;
884
	}
885
	case offset_max_tag:
886
	case max_tag:
887
		bop(maxop, sh(e), son(e), bro(son(e)), dest, stack);
888
		return;
889
	case min_tag:
890
		bop(minop, sh(e), son(e), bro(son(e)), dest, stack);
891
		return;
892
	case offset_subtract_tag:
893
		bop(sub, sh(e), bro(son(e)), son(e), dest, stack);
894
		return;
895
	case offset_mult_tag:
896
		bop(mult, slongsh, son(e), bro(son(e)), dest, stack);
897
		return;
898
	case offset_negate_tag:
899
		uop(negate, sh(e), son(e), dest, stack);
900
		return;
901
	case offset_div_by_int_tag:
902
		bop(div0, sh(e), bro(son(e)), son(e), dest, stack);
903
		return;
904
	case offset_div_tag:
905
		if (shape_size(sh(e)) == 32) {
906
			bop(div0, sh(e), bro(son(e)), son(e), dest, stack);
907
		} else {
908
			if (inmem(dest)) {
909
				bop(div0, sh(son(e)), bro(son(e)), son(e), reg0,
910
				    stack);
911
				change_var(sh(e), reg0, dest);
912
			} else {
913
				bop(div0, sh(son(e)), bro(son(e)), son(e), dest,
914
				    stack);
915
				change_var(sh(e), dest, dest);
916
			}
917
			return;
918
		}
919
	case absbool_tag:
920
		failer(NO_SETCC);
921
		return;
922
	case int_to_bitf_tag: {
923
		int mask = lsmask[shape_size(sh(e))];
924
		move(slongsh, mw(son(e), 0), dest);
925
		and(slongsh, mw(zeroe, mask), dest, dest);
926
		return;
927
	}
928
	case bitf_to_int_tag:
929
		coder(reg0, stack, son(e));
930
		change_var_sh(sh(e), sh(son(e)), reg0, dest);
931
		return;
932
	case alloca_tag:
933
		coder(dest, stack, e);
934
		return;
935
	case power_tag:
936
		failer("integer power not implemented");
937
		return;
938
	case cont_tag:
939
		if (!newcode && name(sh(e)) == bitfhd) {
940
			mem_to_bits(e, sh(e), dest, stack);
941
			return;
942
		}
943
	/* deliberate fall through into default */
944
	default:
945
		/* e is not a possible 80386 operand, precompute it into reg0
946
		 * and move to dest */
947
		if (!is_o (name (e))) {
948
			where qw;
949
			qw.where_exp = copyexp(reg0.where_exp);
950
			sh(qw.where_exp) = sh(e);
951
			qw.where_off = 0;
952
			coder(qw, stack, e);
953
			move(sh(e), qw, dest);
954
			retcell(qw.where_exp);
955
			cond1_set = 0;
956
			return;
957
		}
958
 
959
		if (is_crc(e) && name(e) != name_tag && name(e) != reff_tag &&
960
		    name(e) != field_tag) {
961
			exp s = son(e);
962
			exp ss = son(s);
963
			exp sss = ss;
964
			exp * p = & son(e);
965
 
966
			if (name(s) == reff_tag) {
967
				sss = son(ss);
968
				p = & son(s);
969
			}
970
 
971
			if (name(sss) == name_tag && ptno(son(sss)) == reg_pl) {
972
				move(sh(e), mw(e, 0), dest);
973
				return;
974
			}
975
			else {
976
				exp temp = copyexp(reg0.where_exp);
977
				exp preserve = *p;
978
				coder(reg0, stack, *p);
979
				*p = temp;
980
				move(sh(e), mw(e, 0), dest);
981
				*p = preserve;	/* may still be needed for diags */
982
				return;
983
			}
984
		}
985
 
986
 
987
		if (name(e) == reff_tag &&
988
		    (name(son(e)) == name_tag ||
989
		     (name(son(e)) == cont_tag &&
990
		      name(son(son(e))) == name_tag))) {
991
			/* look for case when reff should be done by add */
992
			add(slongsh, mw(son(e), 0), mw(zeroe, no(e) / 8), dest);
993
			return;
994
		}
995
 
996
		if ((name(e) == name_tag && isvar(son(e))) ||
997
		    name(e) == reff_tag ||
998
		    (PIC_code && name(e) == name_tag && isglob(son(e)) &&
999
		     name(sh(son(e))) == prokhd &&
1000
		     !brog(son(e))->dec_u.dec_val.extnamed)) {
1001
			if (ptno(son(e)) != nowhere_pl) {
1002
				mova(mw(e, 0), dest);
1003
			}
1004
			return;
1005
		}
1006
 
1007
		if (name(e) == clear_tag) {
1008
			if ((name(sh(e)) >= shrealhd &&
1009
			     name(sh(e)) <= doublehd &&
1010
			     !inmem(dest)) ||
1011
			    name(dest.where_exp) == apply_tag) {
1012
				move(sh(e), fzero, dest);
1013
			}
1014
			return;
1015
		}
1016
 
1017
 
1018
		/* other values */
1019
 
1020
		if (name(e) != top_tag && name(e) != prof_tag) {
1021
			move(sh(e), mw(e, 0), dest);
1022
		} else {
1023
			top_regsinuse = regsinuse;
1024
		}
1025
		return;
1026
	}
1027
}