Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/* 80x86/scan2.c */
32
 
33
/**********************************************************************
34
$Author: release $
35
$Date: 1998/01/17 15:55:52 $
36
$Revision: 1.1.1.1 $
37
$Log: scan2.c,v $
38
 * Revision 1.1.1.1  1998/01/17  15:55:52  release
39
 * First version to be checked into rolling release.
40
 *
41
 * Revision 1.31  1997/12/04  20:01:12  pwe
42
 * ANDF-DE V1.9
43
 *
44
 * Revision 1.30  1997/10/10  18:25:26  pwe
45
 * prep ANDF-DE revision
46
 *
47
 * Revision 1.29  1997/02/18  11:43:05  pwe
48
 * NEWDIAGS for debugging optimised code
49
 *
50
 * Revision 1.28  1996/12/10  15:11:49  pwe
51
 * prep NEWDIAGS
52
 *
53
 * Revision 1.27  1996/07/09  16:57:36  pwe
54
 * cont_arg offset from global const
55
 *
56
 * Revision 1.26  1996/07/09  09:43:56  pwe
57
 * caller env_offset if callees present, and tidy
58
 *
59
 * Revision 1.25  1996/05/20  14:30:42  pwe
60
 * improved 64-bit handling
61
 *
62
 * Revision 1.24  1996/05/13  12:52:07  pwe
63
 * undo premature commit
64
 *
65
 * Revision 1.22  1996/02/01  09:34:39  pwe
66
 * PIC oddities for AVS
67
 *
68
 * Revision 1.21  1996/01/31  12:24:26  pwe
69
 * is_crc v is_opnd  &  end_contop must not preceed move_reg
70
 *
71
 * Revision 1.20  1996/01/22  14:31:09  pwe
72
 * PIC const*const, contop top_tag & linux 64-bit ints
73
 *
74
 * Revision 1.19  1996/01/17  11:24:38  pwe
75
 * resurrect performance
76
 *
77
 * Revision 1.18  1995/12/19  13:34:11  pwe
78
 * PIC global idents, and static vars
79
 *
80
 * Revision 1.17  1995/12/01  10:48:37  pwe
81
 * PIC static variables
82
 *
83
 * Revision 1.16  1995/11/01  18:41:29  pwe
84
 * PIC tail_call and exception handling
85
 *
86
 * Revision 1.15  1995/10/25  17:41:22  pwe
87
 * PIC_code current_env and callees
88
 *
89
 * Revision 1.14  1995/10/16  17:45:50  pwe
90
 * frame alignments
91
 *
92
 * Revision 1.13  1995/09/13  14:25:23  pwe
93
 * tidy for gcc
94
 *
95
 * Revision 1.12  1995/09/05  16:25:08  pwe
96
 * specials and exception changes
97
 *
98
 * Revision 1.11  1995/08/30  16:06:54  pwe
99
 * prepare exception trapping
100
 *
101
 * Revision 1.10  1995/08/23  09:43:01  pwe
102
 * track fpu control word for trap etc
103
 *
104
 * Revision 1.9  1995/08/14  13:54:05  pwe
105
 * several corrections, tail calls and error jumps
106
 *
107
 * Revision 1.8  1995/08/04  08:29:44  pwe
108
 * 4.0 general procs implemented
109
 *
110
 * Revision 1.7  1995/03/10  18:11:58  pwe
111
 * offset_div_by_int chvar to 32 bit
112
 *
113
 * Revision 1.6  1995/03/02  17:46:04  pwe
114
 * revise conditions for calling make_bitfield_offset
115
 *
116
 * Revision 1.5  1995/02/24  16:11:14  pwe
117
 * dynamic offsets, including mixed bit/byte representations
118
 *
119
 * Revision 1.4  1995/02/02  15:17:26  pwe
120
 * implement offset_max as max
121
 *
122
 * Revision 1.3  1995/02/01  18:51:18  pwe
123
 * correct empty make_nof
124
 *
125
 * Revision 1.2  1995/01/30  12:56:46  pwe
126
 * Ownership -> PWE, tidy banners
127
 *
128
 * Revision 1.1  1994/10/27  14:15:22  jmf
129
 * Initial revision
130
 *
131
 * Revision 1.1  1994/07/12  14:40:36  jmf
132
 * Initial revision
133
 *
134
**********************************************************************/
135
 
136
 
137
/**********************************************************************
138
                            scan2.c
139
     Defines the scan through a program which
140
     reorganises it so that all arguments of
141
     operations are 80386 operands.
142
     80386 specific.
143
 
144
     These procedures use a pair of a boolean and and exp (eg sto and to)
145
     instead of a pointer to an exp. The boolean is true if the exp
146
     being referred to is the son of the given exp, and false if it is
147
     the brother. This is to allow exps to be represented by indices
148
     into arrays and to allow the arrays to be realloced, which
149
     invalidates the use of &son(to) and &bro(to).
150
 
151
**********************************************************************/
152
 
153
 
154
#include "config.h"
155
#include "common_types.h"
156
#include "exp.h"
157
#include "expmacs.h"
158
#include "tags.h"
159
#include "shapemacs.h"
160
#include "flags.h"
161
#include "label_ops.h"
162
#include "install_fns.h"
163
#include "externs.h"
164
#include "coder.h"
165
#include "instr386.h"
166
#include "scan2.h"
167
#include "basicread.h"
168
 
169
/* MACROS */
170
 
171
#define assexp(isson, p, v) if (isson) setson(p, v); else setbro(p, v)
172
#define contexp(isson, p) ((isson) ? son(p) : bro(p))
173
 
174
/* PROCEDURES */
175
 
176
/* inserts an identity declaration of x at
177
   to, and replaces x by a use of the
178
   identifier */
179
static void cca
180
    PROTO_N ( (sto, to, sx, x) )
181
    PROTO_T ( int sto X exp to X int sx X exp x )
182
{
183
  exp def, ato, id, tg;
184
  def = contexp (sx, x);
185
  if (name(def)==caller_tag) {	/* position sensitive */
186
    cca (sto, to, 1, def);
187
    return;
188
  }
189
  ato = contexp (sto, to);
190
  id = getexp (sh (ato), bro (ato), (int)(last (ato)), def, nilexp,
191
      0, 1, ident_tag);
192
  tg = getexp (sh (def), bro (def), (int)(last (def)), id, nilexp,
193
      0, 0, name_tag);
194
  pt (id) = tg;
195
  clearlast (def);
196
  if (def != ato) {
197
    bro (def) = ato;
198
    bro (ato) = id;
199
    setlast (ato);
200
    assexp (sto, to, id);
201
    assexp (sx, x, tg);
202
  }
203
  else {
204
    bro (def) = tg;
205
    bro (tg) = id;
206
    setlast (tg);
207
    clearlast (def);
208
    assexp (sto, to, id);
209
  };
210
#ifdef NEWDIAGS
211
  if (diagnose) {
212
    dgf(id) = dgf(bro(son(id)));
213
    dgf(bro(son(id))) = nildiag;
214
  }
215
#endif
216
  return;
217
}
218
 
219
/* keeping the same to, scans along the
220
   bro list e, applying cca to introduce
221
   an identity declaration when doit is 1.
222
   Keeps count as the index position along
223
   the list in order to pass it to doit.
224
   If it uses cca it scans the resulting
225
   declaration, using the same to. If it
226
   doesnt use cca, it scans the list
227
   element, still using the same to. This
228
   keeps all operations in the same order.
229
   Result of cc is true if the operands
230
   are all of 80386 form. some operations
231
   are allowed to have not more than one
232
   operand not of 80386 form; this is then
233
   precomputed in reg0 before the
234
   operations. This boolean result is used
235
   to ensure that not more than one
236
   operand is so treated */
237
static int cc
238
    PROTO_N ( (sto, to, se, e, doit, count, usereg0) )
239
    PROTO_T ( int sto X exp to X int se X exp e X
240
	      int (*doit) PROTO_S ((exp, int, int )) X
241
	      int count X int usereg0 )
242
{
243
  int unused = usereg0;	/* can still use reg0 */
244
  exp ec = contexp (se, e);
245
  if (last (ec)) {
246
    if (doit (ec, count, unused)) {
247
      cca (sto, to, se, e);
248
      ec = contexp (sto, to);
249
      return (scan2 (1, ec, son (ec), unused));
250
    }
251
    else {
252
      if (unused)
253
	return (scan2 (se, e, ec, 1));
254
      return (scan2 (sto, to, ec, unused));
255
    }
256
  }
257
  else {
258
    unused = cc (sto, to, 0, ec, doit, count + 1, unused);
259
    /* can we still use reg0? */
260
    ec = contexp (se, e);
261
    if (doit (ec, count, unused)) {
262
      cca (sto, to, se, e);
263
      ec = contexp (sto, to);
264
      return (scan2 (1, ec, son (ec), unused));
265
    }
266
    else {
267
      if (unused)
268
	return (scan2 (sto, to, ec, 1));
269
      return (scan2 (sto, to, ec, unused));
270
    };
271
  };
272
}
273
 
274
/* keeping the same to, scans along the
275
   bro list e, applying cca to introduce
276
   an identity declaration when doit is 1.
277
   Keeps count as the index position along
278
   the list in order to pass it to doit.
279
   If it uses cca it scans the resulting
280
   declaration, using the same to. If it
281
   doesnt use cca, it scans the list
282
   element, still using the same to. This
283
   keeps all operations in the same order.
284
   The difference in detail from cc supports
285
   the asymmetry of div etc */
286
static void cc1
287
    PROTO_N ( (sto, to, se, e, doit, count, usereg0) )
288
    PROTO_T ( int sto X exp to X int se X exp e X
289
	      int (*doit) PROTO_S ((exp, int, int)) X
290
	      int count X int usereg0 )
291
{
292
  int unused = ((count == 1) ? usereg0 : 0);
293
	/* can we still use reg0? */
294
  exp ec = contexp (se, e);
295
  if (last (ec)) {
296
    if (doit (ec, count, unused)) {
297
      cca (sto, to, se, e);
298
      ec = contexp (sto, to);
299
      IGNORE scan2 (1, ec, son (ec), unused);
300
      return;
301
    }
302
    else {
303
      if (unused)  {
304
	IGNORE scan2 (se, e, ec, 1);
305
        return;
306
      };
307
      IGNORE scan2 (sto, to, ec, unused);
308
      return;
309
    }
310
  }
311
  else {
312
    cc1 (sto, to, 0, ec, doit, count + 1, unused);
313
    /* can we still use reg0? */
314
    ec = contexp (se, e);
315
    if (doit (ec, count, unused)) {
316
      cca (sto, to, se, e);
317
      ec = contexp (sto, to);
318
      IGNORE scan2 (1, ec, son (ec), unused);
319
      return;
320
    }
321
    else {
322
      if (unused)  {
323
	IGNORE scan2 (se, e, ec, 1);
324
	return;
325
      };
326
      IGNORE scan2 (sto, to, ec, unused);
327
      return;
328
    };
329
  };
330
}
331
 
332
 
333
/* does cca and forces the declaration to use a register */
334
static void ccp
335
    PROTO_N ( (sto, to, sx, x) )
336
    PROTO_T ( int sto X exp to X int sx X exp x )
337
{
338
  exp toc;
339
  cca (sto, to, sx, x);
340
  toc = contexp (sto, to);
341
  setusereg (toc);
342
  IGNORE scan2 (1, toc, son (toc), 0);
343
  return;
344
}
345
 
346
/* is an operand */
347
static int is_opnd
348
    PROTO_N ( (e) )
349
    PROTO_T ( exp e )
350
{
351
				/* make sure (is_o && is_crc -> !is_opnd) */
352
  unsigned char  n = name (e);
353
  if (n == name_tag) {
354
    if (isvar(son(e)))
355
	return (isglob(son(e)) && !PIC_code);
356
    return (son(son(e)) != nilexp &&
357
	(!isglob(son(e)) || !PIC_code || name(sh(son(e))) != prokhd ||
358
				(brog(son(e)) -> dec_u.dec_val.extnamed)) &&
359
	(name(son(son(e))) != ident_tag || !isparam(son(son(e))) ));
360
  }
361
  return (
362
      n == val_tag || n == real_tag || n == env_size_tag ||
363
      n == cont_tag ||
364
      n == string_tag ||
365
      n == null_tag ||
366
      n == proc_tag || n == general_proc_tag);
367
}
368
 
369
 
370
 
371
 
372
/* This checks the integer argument of an
373
   addptr to make sure that it is of the
374
   right form, including the scale factor
375
   for the kind of operand. This
376
   introduces two declarations, only the
377
   inner one forces the use of a register.
378
   This guarantees that we only load the
379
   registers as close to the actual
380
   instruction as possible, since we are
381
   short of registers on the 80386 */
382
static void ap_argsc
383
    PROTO_N ( (sto, to, e) )
384
    PROTO_T ( int sto X exp to X exp e )
385
{
386
  exp p, a, q;
387
  int  k;
388
  int do1 = 1;
389
 
390
  if (name (son (e)) == reff_tag)
391
    q = son (son (e));
392
  else
393
    q = son (e);		/* q must be addptr - all addptrs processed here */
394
 
395
  if ((frame_al_of_ptr(sh(son(q))) & al_includes_vcallees) &&
396
	(frame_al1_of_offset(sh(bro(son(q)))) & al_includes_caller_args)) {
397
				/* env_offset to arg requires indirection from
398
				   frame pointer */
399
    shape pc_sh = f_pointer(f_callers_alignment(0));
400
    exp c = getexp (pc_sh, bro(son(q)), 0, nilexp, nilexp, 0, 0, cont_tag);
401
    exp r = getexp (pc_sh, c, 1, son(q), nilexp, 0, 64, reff_tag);
402
    setfather (r, son(q));
403
    son(c) = r;
404
    son(q) = c;
405
  }
406
 
407
  p = son (q);
408
  a = bro (p);
409
 
410
  if (name (p) == name_tag && isvar (son (p)) && isglob (son (p)))
411
    do1 = 0;
412
 
413
  if (do1)
414
    ccp (1, e, 1, q);
415
 
416
  if (name (a) == offset_mult_tag && name (bro (son (a))) == val_tag &&
417
      (k = no (bro (son (a))), k == 8 || k == 16 || k == 32 || k == 64))
418
    ccp (1, e, 1, bro (son (q)));
419
  else
420
    ccp (1, e, 0, son (q));
421
 
422
  if (do1) {
423
    cca (sto, to, 1, son (e));
424
    cca (sto, to, 1, bro (son (son (e))));
425
  }
426
  else
427
    cca (sto, to, 1, son (e));
428
 
429
  return;
430
 
431
}
432
 
433
 
434
 
435
/* checks that the argument of a cont or
436
   the destination of an assign has the
437
   right form for an operand, and
438
   introduces a declaration if not.
439
   Continues processing with the same to.
440
   These arguments can contain
441
   declarations, so that we can load
442
   addresses as close as possible to the
443
   instructions that use them, since we
444
   are short of registers in the 80386.
445
   This is done by contop in instr386, during
446
   the code production. */
447
static int cont_arg
448
    PROTO_N ( (sto, to, e, usereg0) )
449
    PROTO_T ( int sto X exp to X exp e X int usereg0 )
450
{
451
  unsigned char  n = name (son (e));
452
 
453
 
454
    if (n == name_tag && isvar (son (son (e))))
455
      return usereg0;
456
 
457
    if (n == cont_tag && usereg0 && shape_size(sh(e)) <= 32) {
458
      cont_arg(sto, to, son(e), 1);
459
      return 0;
460
    }
461
 
462
    if (n == reff_tag) {
463
      exp s = son (son (e));
464
      if (name (s) == name_tag)  {
465
	if (isusereg (son (s)))
466
          return 0;
467
        if (!PIC_code && isglob(son(s)) && isvar(son(s)))
468
          return 0;
469
      };
470
 
471
      if (name(s) == cont_tag && usereg0 && shape_size(sh(e)) <= 32) {
472
	cont_arg(sto, to, s, 1);
473
	return 0;
474
      }
475
 
476
      if (name (s) == addptr_tag) {
477
	ap_argsc (sto, to, e);
478
	return 0;
479
      }
480
    };
481
 
482
 
483
    if (n == addptr_tag) {
484
      ap_argsc (sto, to, e);
485
      return 0;
486
    };
487
 
488
  if (n == reff_tag)
489
    ccp (1, e, 1, son (e));
490
  else
491
    ccp (1, e, 1, e);
492
 
493
  cca (sto, to, 1, son (e));
494
 
495
  return 0;
496
}
497
 
498
 
499
/* is assignable */
500
static int is_assable
501
    PROTO_N ( (e) )
502
    PROTO_T ( exp e )
503
{
504
  return (is_a (name (e)) || name(e) == alloca_tag ||
505
	 ((name (e) == apply_tag || name (e) == apply_general_tag) &&
506
	(name (sh (e)) <= ulonghd || name (sh (e)) == ptrhd)));
507
}
508
 
509
/* doit routine, is not an operand */
510
static int notopnd
511
    PROTO_N ( (t, c, usereg0) )
512
    PROTO_T ( exp t X int c X int usereg0 )
513
{
514
  UNUSED(c);
515
  if (usereg0) {
516
    if (is_opnd (t))
517
      return (0);
518
    return (!is_assable (t));
519
  };
520
  return (!is_opnd (t));
521
}
522
 
523
static int scan_for_alloca PROTO_S ((exp));
524
 
525
static int scan_alloc_args
526
    PROTO_N ( (s) )
527
    PROTO_T ( exp s )
528
{
529
  if (scan_for_alloca(s))
530
    return 1;
531
  if (last(s))
532
    return 0;
533
  return scan_alloc_args(bro(s));
534
}
535
 
536
static int scan_for_alloca
537
    PROTO_N ( (t) )
538
    PROTO_T ( exp t )
539
{
540
  switch (name(t)) {
541
    case local_free_all_tag:
542
    case local_free_tag:
543
    case last_local_tag:
544
    case alloca_tag:
545
    case make_lv_tag:
546
      return 1;
547
    case case_tag:
548
      return scan_for_alloca(son(t));
549
    case labst_tag:
550
      return scan_for_alloca(bro(son(t)));
551
    case env_offset_tag:
552
    case string_tag:
553
    case name_tag:
554
      return 0;
555
    case apply_general_tag:
556
      if call_is_untidy(t)
557
	return 1;
558
      return scan_alloc_args(son(t));
559
    default:
560
      if (son(t) == nilexp)
561
        return 0;
562
      return scan_alloc_args(son(t));
563
  };
564
}
565
 
566
static int no_alloca
567
    PROTO_N ( (t, c, usereg0) )
568
    PROTO_T ( exp t X int c X int usereg0 )
569
{
570
  UNUSED(c); UNUSED(usereg0);
571
  return scan_for_alloca(t);
572
}
573
 
574
/* uses cc, requiring all to be operands */
575
static void all_opnd
576
    PROTO_N ( (sto, to, e, usereg0) )
577
    PROTO_T ( int sto X exp to X exp e X int usereg0 )
578
{
579
  IGNORE cc (sto, to, 1, e, notopnd, 1, usereg0);
580
  return;
581
}
582
 
583
/* doit routine, not assignable */
584
static int notass
585
    PROTO_N ( (t, i, usereg0) )
586
    PROTO_T ( exp t X int i X int usereg0 )
587
{
588
  UNUSED(i); UNUSED(usereg0);
589
  return (!is_assable (t));
590
}
591
 
592
/* uses cc, requiring all to be assignable */
593
static void all_assable
594
    PROTO_N ( (sto, to, e) )
595
    PROTO_T ( int sto X exp to X exp e )
596
{
597
  IGNORE cc (sto, to, 1, e, notass, 1, 1);
598
  return;
599
}
600
 
601
/* just used in the next routine */
602
static int is_direct
603
    PROTO_N ( (e) )
604
    PROTO_T ( exp e )
605
{
606
  unsigned char  s = name (e);
607
  return ((s == name_tag && !isglob (son (e)) && !isvar (son (e))) ||
608
      (s == cont_tag && name (son (e)) == name_tag &&
609
	!isglob (son (son (e))) && isvar (son (son (e)))));
610
}
611
 
612
/* is indirectly addressable */
613
static int is_indable
614
    PROTO_N ( (e) )
615
    PROTO_T ( exp e )
616
{
617
  unsigned char  s = name (e);
618
  if (s == name_tag)
619
    return (1);
620
 
621
  if (s == cont_tag) {
622
    unsigned char  t = name (son (e));
623
    return ((t == name_tag && isvar (son (son (e)))) ||
624
	(t == cont_tag && name (son (son (e))) == name_tag &&
625
	  isvar (son (son (son (e))))) ||
626
	(t == reff_tag && is_direct (son (son (e)))));
627
  };
628
 
629
  return ((s == reff_tag && is_direct (son (e))) ||
630
 
631
      s == addptr_tag);
632
}
633
 
634
 
635
/* son must be indirectly addressable */
636
static void indable_son
637
    PROTO_N ( (sto, to, e) )
638
    PROTO_T ( int sto X exp to X exp e )
639
{
640
  if (!is_indable (son (e))) {
641
    exp ec;
642
    cca (sto, to, 1, e);
643
    ec = contexp (sto, to);
644
    IGNORE scan2 (1, ec, son (ec), 0);
645
  }
646
  else
647
    IGNORE scan2 (sto, to, son (e), 0);
648
  return;
649
}
650
 
651
 
652
 
653
/* apply scan2 to this bro list, moving "to" along it */
654
static void scanargs
655
    PROTO_N ( (st, e, usereg0) )
656
    PROTO_T ( int st X exp e X int usereg0 )
657
{
658
  exp t = e;
659
  exp temp;
660
 
661
  while (temp = contexp (st, t), IGNORE scan2 (st, t, temp, usereg0),
662
      temp = contexp (st, t), !last (temp)) {
663
    t = contexp (st, t);
664
    st = 0;
665
  };
666
  return;
667
}
668
 
669
 
670
 
671
/* doit routine for plus first arg cant be negate, others can */
672
static int plusdo
673
    PROTO_N ( (t, i, usereg0) )
674
    PROTO_T ( exp t X int i X int usereg0 )
675
{
676
  UNUSED(i);
677
  if (usereg0)
678
    return (0);
679
  if (name (t) == neg_tag)
680
    return (0);
681
  return (!is_opnd (t));
682
}
683
 
684
/* doit routine for mult */
685
static int multdo
686
    PROTO_N ( (t, i, usereg0) )
687
    PROTO_T ( exp t X int i X int usereg0 )
688
{
689
  UNUSED(i);
690
  return ((usereg0) ? 0 : !is_opnd (t));
691
}
692
 
693
/* doit routine for and */
694
static int anddo
695
    PROTO_N ( (t, i, usereg0) )
696
    PROTO_T ( exp t X int i X int usereg0 )
697
{
698
  UNUSED(i);
699
  return ((usereg0) ? 0 : !is_opnd (t));
700
}
701
 
702
/* doit routine for xor */
703
static int notado
704
    PROTO_N ( (t, i, usereg0) )
705
    PROTO_T ( exp t X int i X int usereg0 )
706
{
707
  UNUSED(i);
708
  return ((usereg0) ? 0 : !is_opnd (t));
709
}
710
 
711
/* change offset representation bytes to bits */
712
static void make_bitfield_offset
713
    PROTO_N ( (e, pe, spe, sha) )
714
    PROTO_T ( exp e X exp pe X int spe X shape sha )
715
{
716
  exp omul;
717
  exp val8;
718
  if (name(e) == val_tag)
719
    return;
720
  omul = getexp (sha, bro(e), (int)(last (e)), e, nilexp, 0, 0, offset_mult_tag);
721
  val8 = getexp (slongsh, omul, 1, nilexp, nilexp, 0, 8, val_tag);
722
  clearlast(e);
723
  setbro(e, val8);
724
  assexp(spe, pe, omul);
725
}
726
 
727
static void scan_apply_args
728
    PROTO_N ( (spto, pto, sato, ato) )
729
    PROTO_T ( int spto X exp pto X int sato X exp ato )
730
{
731
  if (scan_alloc_args (contexp (sato, ato)))
732
    IGNORE cc (spto, pto, sato, ato, no_alloca, 1, 0);
733
  else
734
    IGNORE scanargs(sato, ato, 1);
735
}
736
 
737
/* avoid registers corrupted by dynamic callees */
738
static void cca_for_cees
739
    PROTO_N ( (sto, to, e) )
740
    PROTO_T ( int sto X exp to X exp e )
741
{
742
  if (name(son(e)) == name_tag) {
743
    if (!isglob (son(son(e))))
744
      set_intnl_call (son(son(e)));
745
    return;
746
  }
747
  if (name(son(e)) == cont_tag && name(son(son(e))) == name_tag) {
748
    if (!isglob (son(son(son(e)))))
749
      set_intnl_call (son(son(son(e))));
750
    return;
751
  }
752
  cca (sto, to, 1, e);
753
  set_intnl_call (contexp (sto, to));
754
}
755
 
756
 
757
static int is_asm_opnd
758
    PROTO_N ( (e, ext) )
759
    PROTO_T ( exp e X int ext )
760
{
761
  unsigned char n = name (e);
762
  if (n == name_tag) {
763
    setvis (son(e));
764
    return 1;
765
  }
766
  if (n == cont_tag && name(son(e)) == name_tag && isvar(son(son(e)))) {
767
    setvis (son(son(e)));
768
    return 1;
769
  }
770
  return (n == val_tag || n == real_tag || n == null_tag ||
771
	(n == reff_tag && name(son(e)) == name_tag));
772
}
773
 
774
static int is_asm_var
775
    PROTO_N ( (e, ext) )
776
    PROTO_T ( exp e X int ext )
777
{
778
  unsigned char n = name (e);
779
  if (n == name_tag && isvar(son(e))) {
780
    setvis (son(e));
781
    return 1;
782
  }
783
  return 0;
784
}
785
 
786
void check_asm_seq
787
    PROTO_N ( (e, ext) )
788
    PROTO_T ( exp e X int ext )
789
{
790
  if (name(e) == asm_tag) {
791
    if ((asm_string(e) && name(son(e)) == string_tag) ||
792
	(asm_in(e) && is_asm_opnd(son(e), ext)) ||
793
	(asm_var(e) && is_asm_var(son(e), ext)) )
794
      return;
795
  }
796
  if (name(e) == seq_tag) {
797
    exp t = son(son(e));
798
    for (;;) {
799
      check_asm_seq (t, ext);
800
      if (last(t))
801
	break;
802
      t = bro(t);
803
    }
804
    check_asm_seq (bro(son(e)), ext);
805
  }
806
  else
807
  if (name(e) != top_tag)
808
    failer ("illegal ~asm");
809
  return;
810
}
811
 
812
 
813
 
814
/* main scan routine */
815
int scan2
816
    PROTO_N ( (sto, to, e, usereg0) )
817
    PROTO_T ( int sto X exp to X exp e X int usereg0 )
818
{
819
  switch (name (e)) {
820
    case prof_tag:
821
	return 0;
822
    case cond_tag:
823
    case rep_tag:
824
    case compound_tag:
825
    case solve_tag:
826
    case nof_tag:
827
    case concatnof_tag:
828
    case ncopies_tag:
829
#ifndef NEWDIAGS
830
    case diagnose_tag:
831
#endif
832
    case caller_tag:
833
      {
834
	if (son(e) == nilexp) /* empty make_nof */
835
	  return (0);
836
	scanargs (1, e, 1);
837
	return (0);
838
      };
839
 
840
    case labst_tag:
841
      {
842
	IGNORE scan2 (0, son (e), bro (son (e)), 1);
843
	return (0);
844
      };
845
    case ident_tag:
846
      {
847
	IGNORE scan2 (0, son (e), bro (son (e)), 0);
848
	IGNORE scan2 (1, e, son (e), 0);
849
	return (0);
850
      };
851
    case seq_tag:
852
      {
853
	scanargs (1, son (e), 1);
854
	IGNORE scan2 (0, son (e), bro (son (e)), 1);
855
	return (0);
856
      };
857
 
858
    case local_free_tag:
859
    case long_jump_tag:
860
    case return_to_label_tag:
861
      {
862
	all_assable (sto, to, e);
863
	return (0);
864
      };
865
 
866
    case offset_add_tag:
867
    case offset_subtract_tag:
868
      {
869
	if (al2(sh(son(e))) == 1 && al2(sh(bro(son(e)))) != 1)
870
	  make_bitfield_offset (bro(son(e)), son(e), 0, sh(e));
871
	if (al2(sh(son(e))) != 1 && al2(sh(bro(son(e)))) == 1)
872
	  make_bitfield_offset (son(e), e, 1, sh(e));
873
	IGNORE all_opnd (sto, to, e, usereg0);
874
	return 0;
875
	/* all arguments except possibly one must be operands */
876
      };
877
 
878
    case offset_mult_tag:
879
    case alloca_tag:
880
    case minus_tag:
881
    case neg_tag:
882
    case not_tag:
883
    case offset_pad_tag:
884
    case offset_negate_tag:
885
    case offset_max_tag:
886
    case int_to_bitf_tag:
887
    case testbit_tag:
888
    case bitf_to_int_tag:
889
    case max_tag:
890
    case min_tag:
891
    case abs_tag:
892
      {
893
	IGNORE all_opnd (sto, to, e, usereg0);
894
	return 0;
895
	/* all arguments except possibly one must be operands */
896
      };
897
    case subptr_tag:
898
    case minptr_tag:
899
    case make_stack_limit_tag:
900
      {
901
	IGNORE all_opnd (sto, to, e, 0);
902
	return 0;
903
      };
904
    case set_stack_limit_tag:
905
      {
906
	exp lim = find_stlim_var();
907
	setbro (lim, son(e));
908
	setson (e, lim);
909
	setname (e, ass_tag);
910
	return scan2 (sto, to, e, usereg0);
911
      };
912
    case chvar_tag:
913
      {
914
	int ur = usereg0 && name(son(e)) != cont_tag;
915
	IGNORE all_opnd (sto, to, e, ur);
916
	return 0;
917
      };
918
 
919
    case test_tag:
920
    case absbool_tag:
921
      {
922
	if ((name (sh (son (e))) >= shrealhd &&
923
	      name (sh (son (e))) <= doublehd))
924
	  IGNORE all_opnd (sto, to, e, 0);/* all arguments must be operands */
925
	else
926
	  IGNORE all_opnd (sto, to, e, usereg0);
927
	/* all arguments except possibly one must be operands */
928
	return 0;
929
      };
930
 
931
    case mod_tag:
932
    case rem2_tag:
933
    case rem0_tag:
934
    case div1_tag:
935
    case div2_tag:
936
    case div0_tag:
937
      {
938
	if (name (sh (e)) == u64hd) {
939
	  exp * bottom = &bro(son(e));
940
	  if (name(*bottom) == chvar_tag && shape_size (sh (son(*bottom))) <= 32 &&
941
		name (son(*bottom)) != val_tag && !is_signed (sh (son(*bottom))) ) {
942
	    if (shape_size (sh (son(*bottom))) == 32) {
943
	      setbro (son(*bottom), bro(*bottom));
944
	      *bottom = son(*bottom);
945
	    }
946
	    else
947
	      setsh (son(*bottom), ulongsh);
948
	  }
949
	}
950
	cc1 (sto, to, 1, e, notopnd, 1, usereg0);
951
	return 0;
952
	/* all arguments except possibly the first must be operands */
953
      };
954
 
955
    case shl_tag:
956
    case shr_tag:
957
    case rotl_tag:
958
    case rotr_tag:
959
    case offset_div_tag:
960
      {
961
	cc1 (sto, to, 1, e, notopnd, 1, usereg0);
962
	return 0;
963
	/* all arguments except possibly the first must be operands */
964
      };
965
 
966
    case offset_div_by_int_tag:
967
      {
968
	if (name(sh(bro(son(e)))) != slonghd &&  name(sh(bro(son(e)))) != ulonghd) {
969
	  exp ch = getexp ((name(sh(bro(son(e))))&1 ? slongsh : ulongsh),
970
		e, 1, bro(son(e)), nilexp, 0, 0, chvar_tag);
971
	  setbro(bro(son(e)), ch);
972
	  setbro(son(e), ch);
973
	};
974
	cc1 (sto, to, 1, e, notopnd, 1, usereg0);
975
	return 0;
976
	/* all arguments except possibly the first must be operands */
977
      };
978
 
979
    case fplus_tag:
980
    case fminus_tag:
981
    case fmult_tag:
982
    case fdiv_tag:
983
    case fneg_tag:
984
    case fabs_tag:
985
    case chfl_tag:
986
    case float_tag:
987
    case round_tag:
988
    case movecont_tag:
989
      {
990
	IGNORE all_opnd (sto, to, e, 0);/* all arguments must be operands */
991
	return 0;
992
      };
993
    case ass_tag:
994
    case assvol_tag:
995
      {
996
	exp toc;
997
	if (name (e) == assvol_tag)/* change assvol to assign */
998
	  setname (e, ass_tag);
999
	IGNORE cont_arg (sto, to, e, 0);
1000
	/* special check for references */
1001
	if (!is_assable (bro (son (e)))) {
1002
	  /* second argument must be assignable */
1003
	  cca (sto, to, 0, son (e));
1004
	  toc = contexp (sto, to);
1005
	  IGNORE scan2 (1, toc, son (toc), 1);
1006
	}
1007
	else
1008
	  IGNORE scan2 (sto, to, bro (son (e)), 1);
1009
	return (0);
1010
      };
1011
    case apply_tag:
1012
      {
1013
	if (builtinproc(e)) {	/* son must be named global */
1014
	  if (!last(son(e)))
1015
	    IGNORE cc (sto, to, 0, son(e), notopnd, 1, 0);
1016
	  return 0;
1017
	}
1018
        if (!last(son(e)))
1019
	  scan_apply_args (sto, to, 0, son(e));
1020
	indable_son (sto, to, e);
1021
	return (0);
1022
      };
1023
    case apply_general_tag:
1024
      {
1025
	exp cees = bro(bro(son(e)));
1026
	exp p_post = cees;	/* bro(p_post) is postlude */
1027
	while (name(bro(p_post)) == ident_tag && name(son(bro(p_post))) == caller_name_tag)
1028
	  p_post = son(bro(p_post));
1029
	scan2 (0, p_post, bro(p_post), 1);
1030
	if (son(cees) != nilexp)
1031
	  scan_apply_args (sto, to, 1, cees);
1032
	if (no(bro(son(e))) != 0)
1033
	  scan_apply_args (sto, to, 1, bro(son(e)));
1034
	indable_son (sto, to, e);
1035
	if ((name(cees) == make_dynamic_callee_tag && name(bro(son(cees))) != val_tag)
1036
		|| (name(cees) == same_callees_tag && callee_size < 0))
1037
	  has_dy_callees = 1;
1038
	if (name(cees) == same_callees_tag)
1039
	  has_same_callees = 1;
1040
	if (name(cees) == make_dynamic_callee_tag || name(cees) == same_callees_tag)
1041
	  cca_for_cees (sto, to, e);
1042
	return (0);
1043
      };
1044
    case tail_call_tag:
1045
      {
1046
	exp cees = bro(son(e));
1047
	has_tail_call = 1;
1048
	if (son(cees) != nilexp)
1049
	  IGNORE cc (sto, to, 1, cees, no_alloca, 1, 0);
1050
	indable_son (sto, to, e);
1051
	if (name(cees) == make_dynamic_callee_tag && name(bro(son(cees))) != val_tag)
1052
	  has_dy_callees = 1;
1053
	if (name(cees) == same_callees_tag)
1054
	  has_same_callees = 1;
1055
	if (name(cees) == make_dynamic_callee_tag)
1056
	  cca_for_cees (sto, to, e);
1057
	return (0);
1058
      };
1059
    case goto_lv_tag:
1060
      {
1061
	indable_son (sto, to, e);
1062
	return (0);
1063
      };
1064
    case res_tag:
1065
    case untidy_return_tag:
1066
      {
1067
	if ((name(sh(son(e))) == cpdhd) &&
1068
	     (name(son(e)) != cont_tag ||
1069
	      name(son(son(e))) != name_tag ||
1070
	      !isvar(son(son(son(e)))))) { /* gcc compatibility */
1071
	  exp ec;
1072
	  cca (sto, to, 1, e);
1073
	  ec = contexp (sto, to);
1074
	  IGNORE scan2 (1, ec, son (ec), 0);
1075
	  return 0;
1076
	}
1077
	else  {
1078
	  IGNORE (scan2 (sto, to, son (e), 1));
1079
	  return 0;
1080
	};
1081
      };
1082
    case case_tag:
1083
      {
1084
	exp toc;
1085
	if (name (son (e)) != name_tag &&
1086
	    (name (son (e)) != cont_tag ||
1087
	      name (son (son (e))) != name_tag)) {
1088
	  cca (sto, to, 1, e);
1089
	  toc = contexp (sto, to);
1090
	  IGNORE scan2 (1, toc, son (toc), 0);
1091
	}
1092
	else
1093
	  IGNORE scan2 (sto, to, son (e), 0);
1094
	return (0);
1095
      };
1096
    case plus_tag:
1097
      {
1098
	IGNORE cc (sto, to, 1, e, plusdo, 1, usereg0);
1099
	return 0;
1100
      };
1101
    case addptr_tag:
1102
      {
1103
	exp f = father (e);
1104
	exp new_r = getexp (sh (e), bro (e), (int)(last (e)),
1105
                             e, nilexp, 0,
1106
	    0, reff_tag);
1107
	exp * ref = refto (f, e);
1108
	setlast (e);
1109
	bro (e) = new_r;
1110
	*ref = new_r;
1111
	ap_argsc (sto, to, new_r);
1112
	return (0);
1113
      };
1114
    case mult_tag:
1115
      {
1116
	if (shape_size (sh (e)) == 64 && optop(e)) {
1117
	  exp * arglist = &son(e);
1118
	  for (;;) {
1119
	    if (name(*arglist) == chvar_tag && shape_size (sh (son(*arglist))) <= 32 &&
1120
		(is_signed (sh (e)) || !is_signed (sh (son(*arglist)))) ) {
1121
	      if (shape_size (sh (son(*arglist))) == 32) {
1122
		setbro (son(*arglist), bro(*arglist));
1123
		if (last(*arglist))
1124
		  setlast (son(*arglist));
1125
		else
1126
		  clearlast (son(*arglist));
1127
		*arglist = son(*arglist);
1128
	      }
1129
	      else
1130
		setsh (son(*arglist), (is_signed (sh (e)) ? slongsh : ulongsh));
1131
	    }
1132
	    if (last(*arglist))
1133
	      break;
1134
	    arglist = &bro(*arglist);
1135
	  }
1136
	}
1137
	IGNORE cc (sto, to, 1, e, multdo, 1, usereg0);
1138
	return 0;
1139
      };
1140
    case and_tag:
1141
      {
1142
	IGNORE cc (sto, to, 1, e, anddo, 1, usereg0);
1143
	return 0;
1144
      };
1145
    case or_tag:
1146
    case xor_tag:
1147
      {
1148
	IGNORE cc (sto, to, 1, e, notado, 1, usereg0);
1149
	return 0;
1150
      };
1151
    case cont_tag:
1152
    case contvol_tag:
1153
      {
1154
	if (name (e) == contvol_tag)
1155
	  setname (e, cont_tag);
1156
	return cont_arg (sto, to, e, usereg0);
1157
      };
1158
    case field_tag:
1159
      {
1160
	if (!is_o (name (son (e))) || name (e) == cont_tag) {
1161
	  exp temp;
1162
	  cca (sto, to, 1, e);
1163
	  temp = contexp (sto, to);
1164
	  return (scan2 (1, temp, son (temp), usereg0));
1165
	}
1166
	else
1167
	  return (scan2 (sto, to, son (e), usereg0));
1168
      };
1169
    case reff_tag:
1170
      {
1171
	if (name (son (e)) == addptr_tag) {
1172
	  ap_argsc (sto, to, e);
1173
	  return (0);
1174
	};
1175
 
1176
	ccp (sto, to, 1, e);
1177
	return (0);
1178
      };
1179
    case proc_tag:
1180
    case general_proc_tag:
1181
      {
1182
	IGNORE scan2 (1, e, son (e), 1);
1183
	return (0);
1184
      };
1185
    case asm_tag:
1186
      {
1187
	if (props(e) != 0)
1188
	  failer ("~asm not in ~asm_sequence");
1189
	check_asm_seq (son(e), 0);
1190
	proc_has_asm = 1;
1191
	return (0);
1192
      };
1193
 
1194
    case name_tag:
1195
      if (!is_opnd (e)) {
1196
	return 0;
1197
      }
1198
 
1199
	/* DELIBERATE FALL THROUGH */
1200
    default:
1201
      return (usereg0);
1202
  };
1203
}