Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
6 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/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
6 7u83 168
(exp e, int off)
2 7u83 169
{
170
  where w;
171
  w.where_exp = e;
172
  w.where_off = off;
6 7u83 173
  return(w);
2 7u83 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
6 7u83 182
(exp a, exp b, int first, int overlap)
2 7u83 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)
6 7u83 192
    return(1);
2 7u83 193
  if (na == nb) {		/* same kind of operation "equal names" */
194
    if (na == val_tag && !isbigval(a) && !isbigval(b))
6 7u83 195
      return(no(a) == no(b));
2 7u83 196
    if (na == ident_tag) {
6 7u83 197
      int good = son(a)!= nilexp && son(b)!= nilexp &&
198
          bro(son(a))!= nilexp && bro(son(b))!= nilexp;
2 7u83 199
      if (good) {
200
        exp bsa = bro(son(a));
201
        exp bsb = bro(son(b));
6 7u83 202
        if (name(bsa) == name_tag && son(bsa) == a &&
203
	    name(bsb) == name_tag && son(bsb) == b) {
2 7u83 204
	  a = son(a);
205
	  b = son(b);
206
	  first = 0;
207
	  goto rept;
208
        };
6 7u83 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) {
2 7u83 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;
6 7u83 224
      return(pt(a) == pt(b) &&
225
	     (overlap ?(no(a) & -32) == (no(b) & -32): no(a) == no(b)));
2 7u83 226
    };
227
    if (na == name_tag) {
6 7u83 228
      if ((overlap ?(no(a) & -32)!= (no(b) & -32): no(a)!= no(b)) ||
229
	 (isvar(son(a))!= isvar(son(b))))
230
	return(0);
2 7u83 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) {
6 7u83 243
      if (overlap ?(no(a) & -32)!= (no(b) & -32): no(a)!= no(b))
244
	return(0);
2 7u83 245
      a = son(a);
246
      b = son(b);
247
      first = 0;
248
      goto rept;
249
    };
6 7u83 250
    if (na == real_tag && name(sh(a)) == name(sh(b))) {
2 7u83 251
      flt fa, fb;
252
      int  i;
253
      int is_zero = 1;
6 7u83 254
      fa = flptnos[no(a)];
255
      fb = flptnos[no(b)];
2 7u83 256
 
257
      for (i = 0; i < MANT_SIZE && (fa.mant)[i] == (fb.mant)[i];
258
	  i++) {
6 7u83 259
	if ((fa.mant)[i]!= 0)
2 7u83 260
	  is_zero = 0;
261
      };
262
 
6 7u83 263
      return(i == MANT_SIZE &&
264
	 (is_zero || (fa.exp == fb.exp &&
2 7u83 265
	      fa.sign == fb.sign)));
266
 
267
    };
6 7u83 268
    return(0);
2 7u83 269
  };				/* end equal names */
270
 
271
 
272
  if (na == name_tag && nb == ident_tag && first) {
6 7u83 273
    if (overlap ?(no(a) & -32)!= 0 : no(a)!= 0)
274
      return(0);
2 7u83 275
    a = son(a);
276
    first = 0;
277
    goto rept;
278
  };
279
  if (na == ident_tag && nb == name_tag && first) {
6 7u83 280
    if (overlap ?(no(b) & -32)!= 0 : no(b)!= 0)
281
      return(0);
2 7u83 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) {
6 7u83 289
    if (overlap ?(no(son(a)) & -32)!= 0 : no(son(a))!= 0)
290
      return(0);
2 7u83 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) {
6 7u83 297
    if (overlap ?(no(son(b)) & -32)!= 0 : no(son(b))!= 0)
298
      return(0);
2 7u83 299
    b = son(b);
300
    first = 0;
301
    goto rept;
302
  };
303
 
304
  if ((na == cont_tag || na == ass_tag) &&
6 7u83 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);
2 7u83 311
    first = 0;
312
    goto rept;
313
  };
314
  if ((nb == cont_tag || nb == ass_tag) &&
6 7u83 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));
2 7u83 321
    first = 0;
322
    goto rept;
323
  };
324
  if ((na == ass_tag && nb == cont_tag) ||
6 7u83 325
     (nb == ass_tag && na == cont_tag)) {
2 7u83 326
    a = son(a);
327
    b = son(b);
328
    first = 0;
329
    goto rept;
330
  };
6 7u83 331
  return(0);
2 7u83 332
}
333
 
334
/* compares wheres for equality of operand */
335
int eq_where
6 7u83 336
(where wa, where wb)
2 7u83 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)
6 7u83 343
    return(0);
344
  return eq_where_exp(a, b, 1, 0);
2 7u83 345
}
346
 
347
 
348
/* find the first register in the register bit pattern r */
349
frr first_reg
6 7u83 350
(int r)
2 7u83 351
{
352
  frr t;
353
  t.regno = 1;
354
  t.fr_no = 0;
355
  if (r == 0)
6 7u83 356
    failer(BAD_REGISTER);
2 7u83 357
  else {
358
    while (!(t.regno & r)) {
359
      t.regno = t.regno << 1;
360
      ++t.fr_no;
361
    }
362
  };
6 7u83 363
  return(t);
2 7u83 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
6 7u83 383
(int le, where wh, int b, int addr)
2 7u83 384
{
385
  exp w = wh.where_exp;
386
  int  off = wh.where_off;
6 7u83 387
  unsigned char  n = name(w);
2 7u83 388
 
389
  if (n == val_tag && !isbigval(w)) {		/* integer constant */
6 7u83 390
    int  k = no(w) + off;
391
    if (name(sh(w)) == offsethd && al2(sh(w))!= 1)
2 7u83 392
      k = k / 8;
6 7u83 393
    int_operand(k, le);
2 7u83 394
    return;
395
  };
396
 
397
  if (n == ident_tag || n == labst_tag) {/* can only be dest */
6 7u83 398
    switch (ptno(w)) {
2 7u83 399
      case local_pl: {
6 7u83 400
	  rel_sp((no(w) + off - stack_dec) / 8, b);
2 7u83 401
	  return;
402
	};
403
      case reg_pl: {
6 7u83 404
	  regn(no(w), off, w, le);
2 7u83 405
	  return;
406
	};
407
      default: {
6 7u83 408
	  failer(BAD_OPND);
2 7u83 409
	  return;
410
	};
411
    };
412
  };
413
 
414
  if (n == name_tag) {
6 7u83 415
    exp ident = son(w);
416
    int  noff = no(w) + off;
417
    int  ni = no(ident);
2 7u83 418
 
6 7u83 419
    if (isglob(ident)) {
2 7u83 420
      if (name (sh (w)) == prokhd)	/* special treatment for procedures */
421
        {
6 7u83 422
          const_extn(ident, noff);
2 7u83 423
          return;
424
        };
425
 
6 7u83 426
      if (isvar(ident))
427
	const_extn(ident, noff);
2 7u83 428
      else
6 7u83 429
	extn(ident, noff, b);
2 7u83 430
      return;
431
    };
432
 
6 7u83 433
    switch (ptno(ident)) {
2 7u83 434
      case local_pl: {		/* local so relative to stack pointer or fp */
6 7u83 435
	  rel_sp((ni + noff - stack_dec) / 8, b);
2 7u83 436
	  return;
437
	};
438
      case callstack_pl: {	/* caller arg so relative to stack pointer */
6 7u83 439
	  rel_cp((ni + noff - stack_dec) / 8, b);
2 7u83 440
	  return;
441
	};
442
      case par_pl: {		/* parameter so relative to fp */
6 7u83 443
	  rel_ap((ni + noff + 32) / 8, b);
2 7u83 444
	  return;
445
	};
446
      case reg_pl: {		/* in a register */
6 7u83 447
	  regn(ni, noff, w, le);
2 7u83 448
	  return;
449
	};
450
      case ferr_pl: {		/* relative to fp, depending on push space */
6 7u83 451
	  rel_ap1((ni + noff) / 8, b);
2 7u83 452
	  return;
453
	};
454
      default: {		/* doesnt happen */
6 7u83 455
	  failer(BAD_OPND);
2 7u83 456
	  return;
457
	};
458
    };
459
  };
460
 
461
  if (n == cont_tag || n == ass_tag) {
6 7u83 462
    exp ref = son(w);
463
    unsigned char  s = name(ref);
2 7u83 464
    if (addr) {
6 7u83 465
      operand(le, mw(son(w), 0), b, 0);
2 7u83 466
      return;
467
    };
468
    if (s == name_tag) {	/* content of id */
6 7u83 469
      if (!isvar(son(ref))) {
470
	exp ident = son(ref);
471
	if (ptno(ident)!= reg_pl && off != 0) {
472
	  failer(BAD_OPND);
2 7u83 473
	};
6 7u83 474
	if (isglob(ident)) {
475
	  if (name(sh(w))!= prokhd)
476
	    failer(BAD_OPND);
2 7u83 477
	  else
478
           {
479
	     if (PIC_code)
6 7u83 480
	       proc_extn(ident, no(ref));
2 7u83 481
             else
6 7u83 482
               extn(ident, no(ref), b);
2 7u83 483
           };
484
	  return;
485
	};
6 7u83 486
	switch (ptno(ident)) {
2 7u83 487
	  case reg_pl: {	/* indirect from register */
6 7u83 488
	      ind_reg(no(ident), no(ref), off, ref, b);
2 7u83 489
	      return;
490
	    };
491
	  default: {
6 7u83 492
	      failer(BAD_OPND);
2 7u83 493
	      return;
494
	    };
495
	};
496
      }
497
      else {			/* variable */
498
 
6 7u83 499
	exp ident = son(ref);
500
	int  noff = no(ref) + off;
501
	int  ni = no(ident);
2 7u83 502
 
6 7u83 503
	if (isglob(ident)) {
504
	  extn(ident, noff, b);
2 7u83 505
	  return;
506
	};
6 7u83 507
	switch (ptno(ident)) {
2 7u83 508
	  case local_pl: {
509
	      /* local so relative to stack pointer or fp */
6 7u83 510
	      rel_sp((ni + noff - stack_dec) / 8, b);
2 7u83 511
	      return;
512
	    };
513
	  case callstack_pl: {
514
	      /* caller arg so relative to stack pointer */
6 7u83 515
	      rel_cp((ni + noff - stack_dec) / 8, b);
2 7u83 516
	      return;
517
	    };
518
	  case par_pl: {	/* parameter so relative to fp */
6 7u83 519
	      rel_ap((ni + noff + 32) / 8, b);
2 7u83 520
	      return;
521
	    };
522
	  case reg_pl: {	/* in a register */
6 7u83 523
	      regn(ni, noff, ref, le);
2 7u83 524
	      return;
525
	    };
526
	  default: {		/* doesnt happen */
6 7u83 527
	      failer(BAD_OPND);
2 7u83 528
	      return;
529
	    };
530
	};
531
      };
532
    };				/* end of cont(name) */
533
 
6 7u83 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);
2 7u83 539
      };
6 7u83 540
      if (isglob(ident)) {
541
	if (name(sh(w))!= prokhd)
542
	  failer(BAD_OPND);
2 7u83 543
	else
6 7u83 544
	  extn(ident, no(son(ref)), b);
2 7u83 545
	return;
546
      };
6 7u83 547
      switch (ptno(ident)) {
2 7u83 548
	case reg_pl: {		/* indirect from register */
6 7u83 549
	    ind_reg(no(ident), no(son(ref)), off, ref, b);
2 7u83 550
	    return;
551
	  };
552
	default: {
6 7u83 553
	    failer(BAD_OPND);
2 7u83 554
	    return;
555
	  };
556
      };
557
    };				/* end of cont(cont(var)) */
558
 
559
 
560
    if (s == reff_tag) {
6 7u83 561
      exp et = son(ref);
562
      unsigned char  t = name(et);
2 7u83 563
      if (t == name_tag) {
6 7u83 564
	if (isglob(son(et))) {
565
	  extn(son(et), no(ref), b);
2 7u83 566
	  return;
567
	};
6 7u83 568
	switch (ptno(son(et))) {
2 7u83 569
	  case reg_pl: {
6 7u83 570
	      ind_reg(no(son(et)), no(et), (no(ref) + off), et, b);
2 7u83 571
	      return;
572
	    };
573
	  default: {
6 7u83 574
	      failer(BAD_OPND);
2 7u83 575
	      return;
576
	    };
577
	};
578
      };			/* end of cont(reff(name)) */
579
 
580
      if (t == cont_tag) {
6 7u83 581
	switch (ptno(son(son(et)))) {
2 7u83 582
	  case reg_pl: {
6 7u83 583
	      ind_reg(no(son(son(et))), no(son(et)),
584
		 (no(ref) + off), son(et), b);
2 7u83 585
	      return;
586
	    };
587
	  default: {
6 7u83 588
	      failer(BAD_OPND);
2 7u83 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;
6 7u83 597
	new_w.where_off = off + no(ref);
598
	operand(le, new_w, b, 0);
2 7u83 599
	return;
600
      };			/* end of cont(reff(addptr())) */
6 7u83 601
      failer(BAD_OPND);
2 7u83 602
    };				/* end of cont(reff()) */
603
 
604
    if (s == addptr_tag) {
6 7u83 605
      exp u = bro(son(ref));
606
      exp c = getexp(f_bottom, nilexp, 0, son(ref), nilexp,
2 7u83 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;
6 7u83 613
      if (name(u) == name_tag || name(u) == cont_tag) {
614
	index_opnd(wc, wu, 1);
2 7u83 615
	return;
616
      };			/* end of cont(addptr(-, name)) */
617
 
6 7u83 618
      if (name(u) == offset_mult_tag) {
2 7u83 619
	int  k = no (bro (son (u)))/8;	/* cannot be bitfield */
6 7u83 620
	wu.where_exp = son(u);
621
	index_opnd(wc, wu, k);
2 7u83 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) {
6 7u83 631
    exp se = son(w);
632
    unsigned char  s = name(se);
2 7u83 633
    if (s == name_tag) {
6 7u83 634
      if (isglob(son(se))) {
635
	extn(son(se), no(w), b);
2 7u83 636
	return;
637
      };
6 7u83 638
      switch (ptno(son(se))) {
2 7u83 639
	case reg_pl: {
6 7u83 640
	    ind_reg(no(son(se)), no(son(se)), no(w), se, b);
2 7u83 641
	    return;
642
	  };
643
	default: {
6 7u83 644
	    failer(BAD_OPND);
2 7u83 645
	    return;
646
	  };
647
      };
648
    };				/* end of reff(name)  */
649
 
650
    if (s == cont_tag) {
6 7u83 651
      if (isglob(son(son(se)))) {
652
	extn(son(son(se)), no(w), b);
2 7u83 653
	return;
654
      };
6 7u83 655
      switch (ptno(son(son(se)))) {
2 7u83 656
	case reg_pl: {
6 7u83 657
	    ind_reg(no(son(son(se))), no(son(se)),
658
		no(w), son(se), b);
2 7u83 659
	    return;
660
	  };
661
	default: {
6 7u83 662
	    failer(BAD_OPND);
2 7u83 663
	    return;
664
	  };
665
      };
666
    };				/* end of reff(cont()) */
667
 
668
    if (s == addptr_tag) {
669
      where ww;
670
      ww.where_exp = se;
6 7u83 671
      ww.where_off = off + no(w);
672
      operand(le, ww, b, 0);
2 7u83 673
      return;
674
    };				/* end of reff(addptr()) */
675
  };				/* end of reff() */
676
 
677
  if (n == addptr_tag) {
6 7u83 678
    exp u = bro(son(w));
679
    exp c = getexp(f_bottom, nilexp, 0, son(w), nilexp, 0, 0, cont_tag);
2 7u83 680
    where wc, wu;
681
    wc.where_exp = c;
682
    wc.where_off = off;
683
    wu.where_exp = u;
684
    wu.where_off = 0;
6 7u83 685
    if (name(u) == name_tag || name(u) == cont_tag) {
686
      index_opnd(wc, wu, 1);
2 7u83 687
      return;
688
    };				/* end of addptr(-, name)  */
689
 
6 7u83 690
    if (name(u) == offset_mult_tag) {
2 7u83 691
      int  k = no (bro (son (u)))/8;	/* cannot be bitfield */
6 7u83 692
      wu.where_exp = son(u);
693
      index_opnd(wc, wu, k);
2 7u83 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) {
6 7u83 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);
2 7u83 705
      return;
706
    };
707
    /* assumes this is only used just after using the first part of the
708
       constant */
6 7u83 709
    const_intnl(0, no(const_list), off);
2 7u83 710
    return;
711
  };
712
 
713
  if (n == res_tag) {
6 7u83 714
    const_intnl(0, no(w), off);
2 7u83 715
    return;
716
  };
717
 
718
  if (n == null_tag) {
6 7u83 719
    int_operand(no(w), le);
2 7u83 720
    return;
721
  };
722
 
723
  if (n == field_tag) {
6 7u83 724
    operand(le, mw(son(w), off + no(w)), b, addr);
2 7u83 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 */
6 7u83 740
      int_operand(no(son(w)) /8, le);
2 7u83 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
 
6 7u83 778
  failer(BAD_OPND);
2 7u83 779
 
780
  return;
781
}
782