Subversion Repositories tendra.SVN

Rev

Rev 6 | Details | Compare with Previous | 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/operand.c */
62
 
63
/**********************************************************************
64
$Author: pwe $
65
$Date: 1998/02/18 11:22:05 $
66
$Revision: 1.2 $
67
$Log: operand.c,v $
68
 * Revision 1.2  1998/02/18  11:22:05  pwe
69
 * test corrections
70
 *
71
 * Revision 1.1.1.1  1998/01/17  15:55:52  release
72
 * First version to be checked into rolling release.
73
 *
74
 * Revision 1.12  1996/04/19  16:14:05  pwe
75
 * simplified use of global id = id, correcting linux call problem
76
 *
77
 * Revision 1.11  1995/08/30  16:06:50  pwe
78
 * prepare exception trapping
79
 *
80
 * Revision 1.10  1995/08/23  09:42:58  pwe
81
 * track fpu control word for trap etc
82
 *
83
 * Revision 1.9  1995/08/04  08:29:41  pwe
84
 * 4.0 general procs implemented
85
 *
86
 * Revision 1.8  1995/04/05  12:35:18  pwe
87
 * operator precedence in eq_where_exp
88
 *
89
 * Revision 1.7  1995/04/03  08:30:24  pwe
90
 * invalidate regs if overlap, eg if bitfield on byte boundaries
91
 *
92
 * Revision 1.6  1995/03/24  09:21:39  pwe
93
 * global proc renaming avoided for SCO
94
 *
95
 * Revision 1.5  1995/03/03  10:12:36  pwe
96
 * makeval is legal but arbitrary operand (for C)
97
 *
98
 * Revision 1.4  1995/02/24  16:11:12  pwe
99
 * dynamic offsets, including mixed bit/byte representations
100
 *
101
 * Revision 1.3  1995/02/21  11:47:59  pwe
102
 * Corrected move(offset) for movecont
103
 *
104
 * Revision 1.2  1995/01/30  12:56:36  pwe
105
 * Ownership -> PWE, tidy banners
106
 *
107
 * Revision 1.1  1994/10/27  14:15:22  jmf
108
 * Initial revision
109
 *
110
 * Revision 1.1  1994/07/12  14:38:12  jmf
111
 * Initial revision
112
 *
113
**********************************************************************/
114
 
115
 
116
/*********************************************************************
117
                              operand.c
118
 
119
  operand outputs a 80386 operand, given a "where" and the number of
120
  bits the operand occupies.
121
 
122
 
123
 
124
*********************************************************************/
125
 
126
 
127
#include "config.h"
128
#include "common_types.h"
129
#include "tags.h"
130
#include "basicread.h"
131
#include "expmacs.h"
132
#include "exp.h"
133
#include "shapemacs.h"
134
#include "flpt.h"
135
#include "coder.h"
136
#include "instr.h"
137
#include "out.h"
138
#include "check.h"
139
#include "codermacs.h"
140
#include "externs.h"
141
#include "install_fns.h"
142
#include "table_fns.h"
143
#include "flags.h"
144
#include "instr386.h"
145
#include "machine.h"
146
#include "localflags.h"
147
#include "assembler.h"
148
#include "messages_8.h"
149
#include "diag_fns.h"
150
#include "operand.h"
151
 
152
 
153
/* VARIABLES */
154
/* All variables initialised */
155
 
156
int  crt_proc_id;	/* init by cproc */
157
int  stack_dec;		/* init by cproc */
158
			/* current stack decrement */
159
exp const_list;		/* init by init_all */
160
			/* list of constants belonging to current
161
				   procedure */
162
 
163
/* PROCEDURES */
164
 
165
/* turns an exp and an offset (in bits)
166
   into a where */
167
where mw
168
(exp e, int off)
169
{
170
  where w;
171
  w.where_exp = e;
172
  w.where_off = off;
173
  return(w);
174
}
175
 
176
/* compares wheres for equality of operand.
177
   This is also used by equiv_reg to detect
178
   invalidity of register copy, in which case
179
   we need to detect overlaps, this case
180
   determined by 'overlap' */
181
int eq_where_exp
182
(exp a, exp b, int first, int overlap)
183
{
184
  unsigned char  na;
185
  unsigned char  nb;
186
 
187
rept:
188
  na = name(a);
189
  nb = name(b);
190
 
191
  if (a == b)
192
    return(1);
193
  if (na == nb) {		/* same kind of operation "equal names" */
194
    if (na == val_tag && !isbigval(a) && !isbigval(b))
195
      return(no(a) == no(b));
196
    if (na == ident_tag) {
197
      int good = son(a)!= nilexp && son(b)!= nilexp &&
198
          bro(son(a))!= nilexp && bro(son(b))!= nilexp;
199
      if (good) {
200
        exp bsa = bro(son(a));
201
        exp bsb = bro(son(b));
202
        if (name(bsa) == name_tag && son(bsa) == a &&
203
	    name(bsb) == name_tag && son(bsb) == b) {
204
	  a = son(a);
205
	  b = son(b);
206
	  first = 0;
207
	  goto rept;
208
        };
209
        if (name(bsa) == reff_tag &&
210
	    name(bsb) == reff_tag &&
211
	   (overlap ?(no(bsa) & -32) == (no(bsb) & -32): no(bsa) == no(bsb)) &&
212
	    name(son(bsa)) == name_tag &&
213
	    son(son(bsa)) == a &&
214
	    name(son(bsb)) == name_tag &&
215
	    son(son(bsb)) == b) {
216
	  a = son(a);
217
	  b = son(b);
218
	  first = 0;
219
	  goto rept;
220
        };
221
      };
222
      if (isglob(a) || isglob(b))
223
        return 0;
224
      return(pt(a) == pt(b) &&
225
	     (overlap ?(no(a) & -32) == (no(b) & -32): no(a) == no(b)));
226
    };
227
    if (na == name_tag) {
228
      if ((overlap ?(no(a) & -32)!= (no(b) & -32): no(a)!= no(b)) ||
229
	 (isvar(son(a))!= isvar(son(b))))
230
	return(0);
231
      a = son(a);
232
      b = son(b);
233
      first = 0;
234
      goto rept;
235
    };
236
    if (na == cont_tag || na == ass_tag) {
237
      a = son(a);
238
      b = son(b);
239
      first = 0;
240
      goto rept;
241
    };
242
    if (na == field_tag || na == reff_tag) {
243
      if (overlap ?(no(a) & -32)!= (no(b) & -32): no(a)!= no(b))
244
	return(0);
245
      a = son(a);
246
      b = son(b);
247
      first = 0;
248
      goto rept;
249
    };
250
    if (na == real_tag && name(sh(a)) == name(sh(b))) {
251
      flt fa, fb;
252
      int  i;
253
      int is_zero = 1;
254
      fa = flptnos[no(a)];
255
      fb = flptnos[no(b)];
256
 
257
      for (i = 0; i < MANT_SIZE && (fa.mant)[i] == (fb.mant)[i];
258
	  i++) {
259
	if ((fa.mant)[i]!= 0)
260
	  is_zero = 0;
261
      };
262
 
263
      return(i == MANT_SIZE &&
264
	 (is_zero || (fa.exp == fb.exp &&
265
	      fa.sign == fb.sign)));
266
 
267
    };
268
    return(0);
269
  };				/* end equal names */
270
 
271
 
272
  if (na == name_tag && nb == ident_tag && first) {
273
    if (overlap ?(no(a) & -32)!= 0 : no(a)!= 0)
274
      return(0);
275
    a = son(a);
276
    first = 0;
277
    goto rept;
278
  };
279
  if (na == ident_tag && nb == name_tag && first) {
280
    if (overlap ?(no(b) & -32)!= 0 : no(b)!= 0)
281
      return(0);
282
    b = son(b);
283
    first = 0;
284
    goto rept;
285
  };
286
 
287
  if (na == cont_tag && name(son(a)) == name_tag &&
288
         isvar(son(son(a))) && nb == ident_tag && first) {
289
    if (overlap ?(no(son(a)) & -32)!= 0 : no(son(a))!= 0)
290
      return(0);
291
    a = son(son(a));
292
    first = 0;
293
    goto rept;
294
  };
295
  if (na == ident_tag && nb == cont_tag && name(son(b)) == name_tag
296
            && isvar(son(son(b))) && first) {
297
    if (overlap ?(no(son(b)) & -32)!= 0 : no(son(b))!= 0)
298
      return(0);
299
    b = son(b);
300
    first = 0;
301
    goto rept;
302
  };
303
 
304
  if ((na == cont_tag || na == ass_tag) &&
305
      name(son(a)) == name_tag &&
306
      isvar(son(son(a))) && nb == name_tag && !isvar(son(b))) {
307
    if (overlap ?(no(son(a)) & -32)!= (no(b) & -32): no(son(a))!= no(b))
308
      return(0);
309
    a = son(son(a));
310
    b = son(b);
311
    first = 0;
312
    goto rept;
313
  };
314
  if ((nb == cont_tag || nb == ass_tag) &&
315
      name(son(b)) == name_tag &&
316
      isvar(son(son(b))) && na == name_tag && !isvar(son(a))) {
317
    if (overlap ?(no(son(b)) & -32)!= (no(a) & -32): no(son(b))!= no(a))
318
      return(0);
319
    a = son(a);
320
    b = son(son(b));
321
    first = 0;
322
    goto rept;
323
  };
324
  if ((na == ass_tag && nb == cont_tag) ||
325
     (nb == ass_tag && na == cont_tag)) {
326
    a = son(a);
327
    b = son(b);
328
    first = 0;
329
    goto rept;
330
  };
331
  return(0);
332
}
333
 
334
/* compares wheres for equality of operand */
335
int eq_where
336
(where wa, where wb)
337
{
338
  exp a = wa.where_exp;
339
  exp b = wb.where_exp;
340
  if (a == nilexp || b == nilexp)
341
     return 0;
342
  if (wa.where_off != wb.where_off)
343
    return(0);
344
  return eq_where_exp(a, b, 1, 0);
345
}
346
 
347
 
348
/* find the first register in the register bit pattern r */
349
frr first_reg
350
(int r)
351
{
352
  frr t;
353
  t.regno = 1;
354
  t.fr_no = 0;
355
  if (r == 0)
356
    failer(BAD_REGISTER);
357
  else {
358
    while (!(t.regno & r)) {
359
      t.regno = t.regno << 1;
360
      ++t.fr_no;
361
    }
362
  };
363
  return(t);
364
}
365
 
366
/* output operand,  wh is a where Note
367
   that the pt field of a declaration now
368
   hold a code for the position of the
369
   value (eg. reg_pl for in a register,
370
   local_pl for relative to sp etc.). The
371
   no field hold the location, bit pattern
372
   for register, offset (in bits) for
373
   local etc. stack_dec hold the amount
374
   the stack is decremented from its
375
   position at the start of the procedure
376
   (ie the place where no is measured
377
   from). This is to allow for push
378
   operations. b is passed to extn to
379
   control whether a bracket is output
380
   (index instructions). addr is true if
381
   we need a literal address. */
382
void operand
383
(int le, where wh, int b, int addr)
384
{
385
  exp w = wh.where_exp;
386
  int  off = wh.where_off;
387
  unsigned char  n = name(w);
388
 
389
  if (n == val_tag && !isbigval(w)) {		/* integer constant */
390
    int  k = no(w) + off;
391
    if (name(sh(w)) == offsethd && al2(sh(w))!= 1)
392
      k = k / 8;
393
    int_operand(k, le);
394
    return;
395
  };
396
 
397
  if (n == ident_tag || n == labst_tag) {/* can only be dest */
398
    switch (ptno(w)) {
399
      case local_pl: {
400
	  rel_sp((no(w) + off - stack_dec) / 8, b);
401
	  return;
402
	};
403
      case reg_pl: {
404
	  regn(no(w), off, w, le);
405
	  return;
406
	};
407
      default: {
408
	  failer(BAD_OPND);
409
	  return;
410
	};
411
    };
412
  };
413
 
414
  if (n == name_tag) {
415
    exp ident = son(w);
416
    int  noff = no(w) + off;
417
    int  ni = no(ident);
418
 
419
    if (isglob(ident)) {
420
      if (name (sh (w)) == prokhd)	/* special treatment for procedures */
421
        {
422
          const_extn(ident, noff);
423
          return;
424
        };
425
 
426
      if (isvar(ident))
427
	const_extn(ident, noff);
428
      else
429
	extn(ident, noff, b);
430
      return;
431
    };
432
 
433
    switch (ptno(ident)) {
434
      case local_pl: {		/* local so relative to stack pointer or fp */
435
	  rel_sp((ni + noff - stack_dec) / 8, b);
436
	  return;
437
	};
438
      case callstack_pl: {	/* caller arg so relative to stack pointer */
439
	  rel_cp((ni + noff - stack_dec) / 8, b);
440
	  return;
441
	};
442
      case par_pl: {		/* parameter so relative to fp */
443
	  rel_ap((ni + noff + 32) / 8, b);
444
	  return;
445
	};
446
      case reg_pl: {		/* in a register */
447
	  regn(ni, noff, w, le);
448
	  return;
449
	};
450
      case ferr_pl: {		/* relative to fp, depending on push space */
451
	  rel_ap1((ni + noff) / 8, b);
452
	  return;
453
	};
454
      default: {		/* doesnt happen */
455
	  failer(BAD_OPND);
456
	  return;
457
	};
458
    };
459
  };
460
 
461
  if (n == cont_tag || n == ass_tag) {
462
    exp ref = son(w);
463
    unsigned char  s = name(ref);
464
    if (addr) {
465
      operand(le, mw(son(w), 0), b, 0);
466
      return;
467
    };
468
    if (s == name_tag) {	/* content of id */
469
      if (!isvar(son(ref))) {
470
	exp ident = son(ref);
471
	if (ptno(ident)!= reg_pl && off != 0) {
472
	  failer(BAD_OPND);
473
	};
474
	if (isglob(ident)) {
475
	  if (name(sh(w))!= prokhd)
476
	    failer(BAD_OPND);
477
	  else
478
           {
479
	     if (PIC_code)
480
	       proc_extn(ident, no(ref));
481
             else
482
               extn(ident, no(ref), b);
483
           };
484
	  return;
485
	};
486
	switch (ptno(ident)) {
487
	  case reg_pl: {	/* indirect from register */
488
	      ind_reg(no(ident), no(ref), off, ref, b);
489
	      return;
490
	    };
491
	  default: {
492
	      failer(BAD_OPND);
493
	      return;
494
	    };
495
	};
496
      }
497
      else {			/* variable */
498
 
499
	exp ident = son(ref);
500
	int  noff = no(ref) + off;
501
	int  ni = no(ident);
502
 
503
	if (isglob(ident)) {
504
	  extn(ident, noff, b);
505
	  return;
506
	};
507
	switch (ptno(ident)) {
508
	  case local_pl: {
509
	      /* local so relative to stack pointer or fp */
510
	      rel_sp((ni + noff - stack_dec) / 8, b);
511
	      return;
512
	    };
513
	  case callstack_pl: {
514
	      /* caller arg so relative to stack pointer */
515
	      rel_cp((ni + noff - stack_dec) / 8, b);
516
	      return;
517
	    };
518
	  case par_pl: {	/* parameter so relative to fp */
519
	      rel_ap((ni + noff + 32) / 8, b);
520
	      return;
521
	    };
522
	  case reg_pl: {	/* in a register */
523
	      regn(ni, noff, ref, le);
524
	      return;
525
	    };
526
	  default: {		/* doesnt happen */
527
	      failer(BAD_OPND);
528
	      return;
529
	    };
530
	};
531
      };
532
    };				/* end of cont(name) */
533
 
534
    if (s == cont_tag && name(son(ref)) == name_tag &&
535
	isvar(son(son(ref)))) {
536
      exp ident = son(son(ref));
537
      if (ptno(ident)!= reg_pl && off != 0) {
538
	failer(BAD_OPND);
539
      };
540
      if (isglob(ident)) {
541
	if (name(sh(w))!= prokhd)
542
	  failer(BAD_OPND);
543
	else
544
	  extn(ident, no(son(ref)), b);
545
	return;
546
      };
547
      switch (ptno(ident)) {
548
	case reg_pl: {		/* indirect from register */
549
	    ind_reg(no(ident), no(son(ref)), off, ref, b);
550
	    return;
551
	  };
552
	default: {
553
	    failer(BAD_OPND);
554
	    return;
555
	  };
556
      };
557
    };				/* end of cont(cont(var)) */
558
 
559
 
560
    if (s == reff_tag) {
561
      exp et = son(ref);
562
      unsigned char  t = name(et);
563
      if (t == name_tag) {
564
	if (isglob(son(et))) {
565
	  extn(son(et), no(ref), b);
566
	  return;
567
	};
568
	switch (ptno(son(et))) {
569
	  case reg_pl: {
570
	      ind_reg(no(son(et)), no(et), (no(ref) + off), et, b);
571
	      return;
572
	    };
573
	  default: {
574
	      failer(BAD_OPND);
575
	      return;
576
	    };
577
	};
578
      };			/* end of cont(reff(name)) */
579
 
580
      if (t == cont_tag) {
581
	switch (ptno(son(son(et)))) {
582
	  case reg_pl: {
583
	      ind_reg(no(son(son(et))), no(son(et)),
584
		 (no(ref) + off), son(et), b);
585
	      return;
586
	    };
587
	  default: {
588
	      failer(BAD_OPND);
589
	      return;
590
	    };
591
	};
592
      };			/* end of cont(ref(cont())) */
593
 
594
      if (t == addptr_tag) {
595
	where new_w;
596
	new_w.where_exp = et;
597
	new_w.where_off = off + no(ref);
598
	operand(le, new_w, b, 0);
599
	return;
600
      };			/* end of cont(reff(addptr())) */
601
      failer(BAD_OPND);
602
    };				/* end of cont(reff()) */
603
 
604
    if (s == addptr_tag) {
605
      exp u = bro(son(ref));
606
      exp c = getexp(f_bottom, nilexp, 0, son(ref), nilexp,
607
	  0, 0, cont_tag);
608
      where wc, wu;
609
      wc.where_exp = c;
610
      wc.where_off = off;
611
      wu.where_exp = u;
612
      wu.where_off = 0;
613
      if (name(u) == name_tag || name(u) == cont_tag) {
614
	index_opnd(wc, wu, 1);
615
	return;
616
      };			/* end of cont(addptr(-, name)) */
617
 
618
      if (name(u) == offset_mult_tag) {
619
	int  k = no (bro (son (u)))/8;	/* cannot be bitfield */
620
	wu.where_exp = son(u);
621
	index_opnd(wc, wu, k);
622
	return;
623
      };			/* end of cont(addptr(-, mult)) */
624
    };				/* end of cont(addptr()) */
625
 
626
 
627
  };				/* end of cont */
628
 
629
 
630
  if (n == reff_tag) {
631
    exp se = son(w);
632
    unsigned char  s = name(se);
633
    if (s == name_tag) {
634
      if (isglob(son(se))) {
635
	extn(son(se), no(w), b);
636
	return;
637
      };
638
      switch (ptno(son(se))) {
639
	case reg_pl: {
640
	    ind_reg(no(son(se)), no(son(se)), no(w), se, b);
641
	    return;
642
	  };
643
	default: {
644
	    failer(BAD_OPND);
645
	    return;
646
	  };
647
      };
648
    };				/* end of reff(name)  */
649
 
650
    if (s == cont_tag) {
651
      if (isglob(son(son(se)))) {
652
	extn(son(son(se)), no(w), b);
653
	return;
654
      };
655
      switch (ptno(son(son(se)))) {
656
	case reg_pl: {
657
	    ind_reg(no(son(son(se))), no(son(se)),
658
		no(w), son(se), b);
659
	    return;
660
	  };
661
	default: {
662
	    failer(BAD_OPND);
663
	    return;
664
	  };
665
      };
666
    };				/* end of reff(cont()) */
667
 
668
    if (s == addptr_tag) {
669
      where ww;
670
      ww.where_exp = se;
671
      ww.where_off = off + no(w);
672
      operand(le, ww, b, 0);
673
      return;
674
    };				/* end of reff(addptr()) */
675
  };				/* end of reff() */
676
 
677
  if (n == addptr_tag) {
678
    exp u = bro(son(w));
679
    exp c = getexp(f_bottom, nilexp, 0, son(w), nilexp, 0, 0, cont_tag);
680
    where wc, wu;
681
    wc.where_exp = c;
682
    wc.where_off = off;
683
    wu.where_exp = u;
684
    wu.where_off = 0;
685
    if (name(u) == name_tag || name(u) == cont_tag) {
686
      index_opnd(wc, wu, 1);
687
      return;
688
    };				/* end of addptr(-, name)  */
689
 
690
    if (name(u) == offset_mult_tag) {
691
      int  k = no (bro (son (u)))/8;	/* cannot be bitfield */
692
      wu.where_exp = son(u);
693
      index_opnd(wc, wu, k);
694
      return;
695
    };				/* end of addptr(-, mult) */
696
  };				/* end of addptr() */
697
 
698
  if (n == real_tag || n == val_tag || n == string_tag ||
699
	n == proc_tag || n == general_proc_tag) {
700
    int  ln;
701
    if (off == 0 || addr) {
702
      ln = next_lab();
703
      const_list = getexp(f_bottom, const_list, 0, w, nilexp, 0, ln, 0);
704
      const_intnl((addr || n == proc_tag || n == general_proc_tag), ln, 0);
705
      return;
706
    };
707
    /* assumes this is only used just after using the first part of the
708
       constant */
709
    const_intnl(0, no(const_list), off);
710
    return;
711
  };
712
 
713
  if (n == res_tag) {
714
    const_intnl(0, no(w), off);
715
    return;
716
  };
717
 
718
  if (n == null_tag) {
719
    int_operand(no(w), le);
720
    return;
721
  };
722
 
723
  if (n == field_tag) {
724
    operand(le, mw(son(w), off + no(w)), b, addr);
725
    return;
726
  };
727
 
728
  if (n == make_lv_tag) {
729
    label_operand(w);
730
    return;
731
  };
732
 
733
  if (n == current_env_tag) {
734
    outbp();
735
    return;
736
  };
737
 
738
  if (n == env_offset_tag) {
739
    if (name(son(w))==0) {	/* must be caller arg with var_callees */
740
      int_operand(no(son(w)) /8, le);
741
      return;
742
    }
743
    outs("$");
744
    envoff_operand(son(w), no(w));
745
    return;
746
  };
747
 
748
  if (n == env_size_tag) {
749
    outs("$");
750
    envsize_operand(son(son(w)));
751
    return;
752
  };
753
 
754
  if (n == local_free_all_tag) {
755
    ldisp();
756
    return;
757
  };
758
 
759
  if (n == clear_tag) {
760
	/* any legal operand will do! */
761
    if (name(sh(w)) >= shrealhd && name(sh(w)) <= doublehd) {
762
      outs("%st");
763
      return;
764
    }
765
    switch (shape_size(sh(w))) {
766
      case 8:
767
	outs("%al");
768
	return;
769
      case 16:
770
	outs("%ax");
771
	return;
772
      default:
773
	outs("%eax");
774
	return;
775
    };
776
  };
777
 
778
  failer(BAD_OPND);
779
 
780
  return;
781
}
782