Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | 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
/**********************************************************************
32
$Author: release $
33
$Date: 1998/01/17 15:56:06 $
34
$Revision: 1.1.1.1 $
35
$Log: new_code.c,v $
36
 * Revision 1.1.1.1  1998/01/17  15:56:06  release
37
 * First version to be checked into rolling release.
38
 *
39
 * Revision 1.39  1996/11/12  10:37:36  currie
40
 * cases with big unsigned
41
 *
42
Revision 1.38  1996/03/28 11:36:27  currie
43
minus unsigned with et
44
 
45
 * Revision 1.37  1996/03/14  17:09:02  currie
46
 * empty callers with postlude
47
 *
48
 * Revision 1.36  1996/01/30  12:36:31  currie
49
 * leaf vcallees with current_env
50
 *
51
 * Revision 1.35  1996/01/17  10:25:02  currie
52
 * tidy transformed idents of idents
53
 *
54
 * Revision 1.34  1996/01/10  17:59:28  currie
55
 * postlude uses in callees
56
 *
57
 * Revision 1.33  1996/01/09  12:00:48  currie
58
 * var callee par in reg
59
 *
60
 * Revision 1.32  1996/01/08  17:05:27  currie
61
 * current_env in depends_on
62
 *
63
 * Revision 1.31  1996/01/02  15:00:57  currie
64
 * return 64-bit const
65
 *
66
 * Revision 1.30  1995/12/08  11:20:06  currie
67
 * Constant offsets + allocaerr_lab
68
 *
69
 * Revision 1.29  1995/11/23  13:17:25  currie
70
 * Cache real consts + get text file name right in diags
71
 *
72
 * Revision 1.28  1995/10/31  17:46:10  currie
73
 * max-min register error
74
 *
75
 * Revision 1.27  1995/10/31  15:04:55  currie
76
 * div1 error
77
 *
78
 * Revision 1.26  1995/10/25  13:48:23  currie
79
 * change to position of .glob
80
 *
81
 * Revision 1.25  1995/10/23  11:18:25  currie
82
 * put in gpword for switches in PIC-code
83
 *
84
 * Revision 1.24  1995/10/20  10:48:01  currie
85
 * avs -slow + attempts to cheat buggy scheduler
86
 *
87
 * Revision 1.23  1995/10/06  14:46:26  currie
88
 * nops in round
89
 *
90
 * Revision 1.22  1995/09/26  09:00:54  currie
91
 * tail call errors in sieve
92
 *
93
 * Revision 1.21  1995/09/21  15:42:51  currie
94
 * silly reordering by as again
95
 *
96
 * Revision 1.20  1995/09/20  14:23:02  currie
97
 * callee-list blunder + fix for silliness in ultrix assembler
98
 *
99
 * Revision 1.19  1995/09/12  10:59:39  currie
100
 * gcc pedanttry
101
 *
102
 * Revision 1.18  1995/08/21  16:13:23  currie
103
 * var pars
104
 *
105
 * Revision 1.17  1995/08/16  16:06:58  currie
106
 * Shortened some .h names
107
 *
108
 * Revision 1.16  1995/08/15  12:20:24  currie
109
 * Dynamic callees!??
110
 *
111
 * Revision 1.15  1995/08/15  10:47:29  currie
112
 * Dynamic callees - protect parregs & link
113
 *
114
 * Revision 1.14  1995/08/15  09:19:29  currie
115
 * Dynamic callees + trap_tag
116
 *
117
 * Revision 1.13  1995/08/10  08:49:40  currie
118
 * var callee tail call
119
 *
120
 * Revision 1.12  1995/08/09  10:53:42  currie
121
 * apply_general bug
122
 *
123
 * Revision 1.11  1995/07/06  17:12:28  currie
124
 * tail call again
125
 *
126
 * Revision 1.10  1995/07/05  11:44:32  currie
127
 * Postlude names in bits!
128
 *
129
 * Revision 1.9  1995/07/05  08:42:40  currie
130
 * Various tail call bugs
131
 *
132
 * Revision 1.7  1995/07/03  15:31:55  currie
133
 * untidy call
134
 *
135
 * Revision 1.6  1995/07/03  10:09:32  currie
136
 * untidy return
137
 *
138
 * Revision 1.5  1995/06/29  16:30:19  currie
139
 * Tail call errors
140
 *
141
 * Revision 1.4  1995/06/28  12:15:24  currie
142
 * New make_stack_limit etc
143
 *
144
 * Revision 1.3  1995/05/05  08:13:01  currie
145
 * initial_value + signtures
146
 *
147
 * Revision 1.2  1995/04/19  16:10:37  currie
148
 * Unset variables - purify
149
 *
150
 * Revision 1.1  1995/04/13  09:08:06  currie
151
 * Initial revision
152
 *
153
***********************************************************************/
154
/* new_code.c
155
	This is the principal code producing module
156
****************************************************************/
157
 
158
#include "config.h"
159
#include "common_types.h"
160
#include "addrtypes.h"
161
#include "tags.h"
162
#include "expmacs.h"
163
#include "exp.h"
164
#include "exptypes.h"
165
#include "externs.h"
166
#include "loc_signal.h"
167
#include "maxminmacs.h"
168
#include "shapemacs.h"
169
#include "basicread.h"
170
#include "procrectypes.h"
171
#include "eval.h"
172
#include "move.h"
173
#include "operators.h"
174
#include "psu_ops.h"
175
#include "getregs.h"
176
#include "guard.h"
177
#include "locate.h"
178
#include "code_here.h"
179
#include "inst_fmt.h"
180
#include "mips_ins.h"
181
#include "handle_sregs.h"
182
#include "bitsmacs.h"
183
#include "labels.h"
184
#include "regexps.h"
185
#include "special.h"
186
#include "new_tags.h"
187
#include "out_ba.h"
188
#include "ibinasm.h"
189
#include "syms.h"
190
#include "flags.h"
191
#include "main.h"
192
#include "dump_distr.h"
193
#include "extratags.h"
194
#include "mipsdiags.h"
195
#include "frames.h"
196
#include "f64.h"
197
#include "regable.h"
198
#include "diag_fns.h"
199
#include "flpt.h"
200
#include "new_code.h"
201
 
202
extern  FILE * as_file;
203
extern int current_symno;
204
extern  procrec * procrecs;
205
 
206
long  fscopefile;
207
 
208
ans procans;
209
int   rscope_level;
210
int   rscope_label;
211
int   result_label = 0;
212
int   currentnop;
213
long max_args;
214
 
215
where nowhere;
216
 
217
static exp crt_proc;
218
 
219
bool NONEGSHIFTS = 1;
220
 
221
long aritherr_lab = 0;
222
long stackerr_lab = 0;
223
long allocaerr_lab = 0;
224
 
225
extern exp find_named_tg PROTO_S ((char *, shape));
226
extern shape f_pointer PROTO_S ((alignment));
227
extern alignment f_alignment PROTO_S ((shape));
228
extern shape f_proc;
229
 
230
typedef struct{int dble; r2l r; instore ad;} rcache;
231
static rcache rca[16];
232
static int nca = 0;
233
 
234
void do_exception
235
    PROTO_N ( (e) )
236
    PROTO_T ( int e )
237
{
238
	baseoff b;
239
	b.base = 0; b.offset = e;
240
	ls_ins(i_li, 4,  b);
241
	b = boff(find_named_tg("__TDFhandler", f_pointer(f_alignment(f_proc))));
242
	ls_ins(i_lw, 25, b);
243
	br_ins(i_j, 25);
244
}
245
 
246
long trap_label
247
    PROTO_N ( (e) )
248
    PROTO_T ( exp e )
249
{
250
	if ((errhandle(e)&3)==3) {
251
          	if (aritherr_lab==0) aritherr_lab = new_label();
252
          	return aritherr_lab;
253
        }
254
        else return no (son (pt (e)));
255
}
256
 
257
void dump_gp
258
    PROTO_Z ()
259
{
260
	baseoff b;
261
	b.base = 29; b.offset = locals_offset>>3;
262
	ls_ins(i_sw, 28, b);
263
}
264
 
265
void reset_gp
266
    PROTO_Z ()
267
{
268
	baseoff b;
269
	if (Has_vcallees) {
270
		b.base = local_reg;
271
		b.offset = (locals_offset - frame_size)>>3;
272
	}
273
	else
274
	if (Has_fp) {
275
		b.base = 30;
276
		b.offset = (locals_offset - frame_size - callee_size)>>3;
277
	}
278
	else {
279
		b.base = 29;
280
		b.offset = locals_offset>>3;
281
        }
282
	ls_ins(i_lw, 28, b);
283
}
284
 
285
bool unsafe
286
    PROTO_N ( (e) )
287
    PROTO_T ( exp e )
288
{		/*  usages of parameters which might be
289
				   vararg */
290
/*
291
  if (last (e))
292
    return (name (bro (e)) != cont_tag && name (bro (e)) != par_tag);
293
  if (last (bro (e)) && name (bro (bro (e))) == ass_tag)
294
    return 0;
295
  if (name (father (e)) == par_tag)
296
    return 0;
297
  if (last (bro (e)) && name (bro (bro (e))) == ident_tag) {
298
    exp u;
299
    if (isvar (bro (bro (e))))
300
      return 1;
301
    for (u = pt (bro (bro (e))); u != nilexp; u = pt (u)) {
302
      if (unsafe (u))
303
	return 1;
304
    }
305
    return 0;
306
  }
307
  return 1;
308
*/ failer("unsafe");
309
   return 1;
310
}
311
 
312
 
313
 
314
void checknan
315
    PROTO_N ( (e, sp) )
316
    PROTO_T ( exp e X space sp )
317
{
318
           long trap = trap_label(e);
319
           int r1 = getreg(sp.fixed);
320
           int r2 = getreg(guardreg(r1, sp).fixed);
321
           cop_ins(i_cfc1, r1, 31);
322
	   rri_ins(i_and, r2, r1, 0x70); /* not including underflo - my choice */
323
	   rrr_ins(i_xor, r1, r1, r2);
324
	   cop_ins(i_ctc1, r1, 31);
325
	   condri_ins(i_bne, r2, 0, trap);
326
}
327
/*
328
char *usbranches (i)
329
	int i;
330
{
331
  switch (i) {
332
    case  1:
333
            return i_bleu;
334
    case 2:
335
      return i_bltu;
336
    case 3:
337
      return i_bgeu;
338
    case 4:
339
      return i_bgtu;
340
    case 5:
341
      return i_bne;
342
    case 6:
343
      return i_beq;
344
  }
345
}
346
*/
347
 
348
void testsigned
349
    PROTO_N ( (r, lower, upper, lab) )
350
    PROTO_T ( int r X long lower X long upper X long lab )
351
{
352
	condri_ins(i_blt, r, lower, lab);
353
	condri_ins(i_bgt, r, upper, lab);
354
}
355
 
356
void testusigned
357
    PROTO_N ( (r, maxval, lab) )
358
    PROTO_T ( int r X long maxval X long lab )
359
{
360
     	condri_ins(i_bgtu, r, maxval, lab);
361
}
362
 
363
/*
364
char *sbranches(i)
365
	int i;
366
{
367
  switch (i) {
368
    case  1:
369
            return i_ble;
370
    case 2:
371
      return i_blt;
372
    case 3:
373
      return i_bge;
374
    case 4:
375
      return i_bgt;
376
    case 5:
377
      return i_bne;
378
    case 6:
379
      return i_beq;
380
  }
381
}
382
*/
383
 
384
char * branches
385
    PROTO_N ( (s, i) )
386
    PROTO_T ( shape s X int i )
387
{
388
	int n = name(s);
389
	if (n == scharhd || n == swordhd || n == slonghd
390
		|| n == offsethd) {
391
          switch (i) {
392
            case  1:
393
                    return i_ble;
394
            case 2:
395
              return i_blt;
396
            case 3:
397
              return i_bge;
398
            case 4:
399
              return i_bgt;
400
            case 5:
401
              return i_bne;
402
            case 6:
403
              return i_beq;
404
          }
405
        }
406
        else {
407
  		switch (i) {
408
		    case  1:
409
		            return i_bleu;
410
		    case 2:
411
		      return i_bltu;
412
		    case 3:
413
		      return i_bgeu;
414
		    case 4:
415
		      return i_bgtu;
416
		    case 5:
417
		      return i_bne;
418
		    case 6:
419
		      return i_beq;
420
		  }
421
	}
422
	return i_beq;
423
}
424
 
425
/*
426
char *ussets
427
    PROTO_N ( (i) )
428
    PROTO_T ( int i )
429
{
430
  switch (i) {
431
    case  1:
432
      return i_sgtu;
433
    case 2:
434
      return i_sgeu;
435
    case 3:
436
      return i_sltu;
437
    case 4:
438
      return i_sleu;
439
    case 5:
440
      return i_seq;
441
    case 6:
442
      return i_sne;
443
  }
444
}
445
 
446
char *ssets
447
    PROTO_N ( (i) )
448
    PROTO_T ( int i )
449
{
450
  switch (i) {
451
    case  1:
452
            return i_sgt;
453
    case 2:
454
      return i_sge;
455
    case 3:
456
      return i_slt;
457
    case 4:
458
      return i_sle;
459
    case 5:
460
      return i_seq;
461
    case 6:
462
      return i_sne;
463
  }
464
}
465
*/
466
 
467
char * sets
468
    PROTO_N ( (s, i) )
469
    PROTO_T ( shape s X int i )
470
{
471
	int n = name(s);
472
	if (n == scharhd || n == swordhd || n == slonghd
473
		|| n == offsethd) {
474
		  switch (i) {
475
		    case  1:
476
		            return i_sgt;
477
		    case 2:
478
		      return i_sge;
479
		    case 3:
480
		      return i_slt;
481
		    case 4:
482
		      return i_sle;
483
		    case 5:
484
		      return i_seq;
485
		    case 6:
486
		      return i_sne;
487
		  }
488
	}
489
	else {
490
		  switch (i) {
491
		    case  1:
492
		            return i_sgtu;
493
		    case 2:
494
		      return i_sgeu;
495
		    case 3:
496
		      return i_sltu;
497
		    case 4:
498
		      return i_sleu;
499
		    case 5:
500
		      return i_seq;
501
		    case 6:
502
		      return i_sne;
503
		  }
504
	}
505
	return i_seq;
506
}
507
 
508
char *fbranches
509
    PROTO_N ( (i) )
510
    PROTO_T ( int i )
511
{
512
  switch (i) {
513
    case  1:
514
            return i_c_le_s;
515
    case 2:
516
      return i_c_lt_s;
517
    case 3:
518
      return i_c_lt_s;
519
    case 4:
520
      return i_c_le_s;
521
    case 5:
522
      return i_c_eq_s;
523
    case 6:
524
      return i_c_eq_s;
525
  }
526
  return i_c_eq_s;
527
}
528
 
529
char *fdbranches
530
    PROTO_N ( (i) )
531
    PROTO_T ( int i )
532
{
533
  switch (i) {
534
    case  1:
535
            return i_c_le_d;
536
    case 2:
537
      return i_c_lt_d;
538
    case 3:
539
      return i_c_lt_d;
540
    case 4:
541
      return i_c_le_d;
542
    case 5:
543
      return i_c_eq_d;
544
    case 6:
545
      return i_c_eq_d;
546
  }
547
  return i_c_eq_d;
548
}
549
 
550
long  notbranch[6] = {
551
  4, 3, 2, 1, 6, 5
552
};
553
 /* used to invert TDF tests */
554
 
555
int   bitsin
556
    PROTO_N ( (b) )
557
    PROTO_T ( long b )
558
{		/* counts the bits in b */
559
  int   n = 0;
560
  long  mask = 1;
561
  for (; b != 0;) {
562
    n += ((b & mask) != 0) ? 1 : 0;
563
    b &= ~mask;
564
    mask = mask << 1;
565
  }
566
  return n;
567
}
568
 
569
void move_dlts
570
    PROTO_N ( (dr, sr, szr, mr, bytemove) )
571
    PROTO_T ( int dr X int sr X int szr X int mr X int bytemove )
572
{
573
	/* move szr bytes to dr from sr (use mr)- either nooverlap or dr<=sr */
574
	baseoff b;
575
	int lin = new_label();
576
 
577
	b.offset =0;
578
 	set_label(lin);
579
 	b.base = sr;
580
 	ls_ins((bytemove)?i_lb:i_lw, mr, b);
581
 	rri_ins(i_addu, sr, sr, (bytemove)?1:4);
582
 	b.base = dr;
583
 	ls_ins((bytemove)?i_sb:i_sw, mr, b);
584
 	rri_ins(i_addu, dr, dr, (bytemove)?1:4);
585
 	rri_ins(i_subu, szr, szr, (bytemove)?1:4);
586
 	condrr_ins(i_bne, szr, 0, lin);
587
}
588
 
589
void move_dgts
590
    PROTO_N ( (dr, sr, szr, mr, bytemove) )
591
    PROTO_T ( int dr X int sr X int szr X int mr X int bytemove )
592
{
593
	/* move szr bytes to dr from sr (use mr) with overlap and dr>sr */
594
	baseoff b;
595
	int lin = new_label();
596
 
597
	b.offset = (bytemove)?-1:-4;
598
 
599
	rrr_ins(i_addu, dr,dr, szr);
600
	rrr_ins(i_addu, sr,sr, szr);
601
 	set_label(lin);
602
 	b.base = sr;
603
 	ls_ins((bytemove)?i_lb:i_lw, mr, b);
604
 	rri_ins(i_subu, sr, sr, (bytemove)?1:4);
605
 	b.base = dr;
606
 	ls_ins((bytemove)?i_sb:i_sw, mr, b);
607
 	rri_ins(i_subu, dr, dr, (bytemove)?1:4);
608
 	rri_ins(i_subu, szr, szr, (bytemove)?1:4);
609
 	condrr_ins(i_bne, szr, 0, lin);
610
}
611
 
612
void reset_tos
613
    PROTO_Z ()
614
{
615
    	if (Has_tos) {
616
    		baseoff b;
617
    		b.base = 30;
618
    		b.offset = -8;
619
    		ls_ins(i_sw, 29, b);
620
    	}
621
}
622
 
623
exp testlast
624
    PROTO_N ( (e, second) )
625
    PROTO_T ( exp e X exp second )
626
{
627
  /* finds the last test in sequence e which is a branch to second, if
628
     any, otherwise nil */
629
  if (name (e) == test_tag && pt (e) == second) {
630
    return (e);
631
  }
632
  if (name (e) == seq_tag) {
633
    if (name (bro (son (e))) == test_tag && pt (bro (son (e))) == second) {
634
      return bro (son (e));
635
    }
636
    else
637
      if (name (bro (son (e))) == top_tag) {
638
	exp list = son (son (e));
639
	for (;;) {
640
	  if (last (list)) {
641
	    if (name (list) == test_tag && pt (list) == second) {
642
	      return list;
643
	    }
644
	    else {
645
	      return 0;
646
	    }
647
	  }
648
	  else {
649
	    list = bro (list);
650
	  }
651
	}
652
      }
653
  }
654
  return 0;
655
}
656
 
657
 
658
 
659
bool last_param
660
    PROTO_N ( (e) )
661
    PROTO_T ( exp e )
662
{
663
	if (!isparam(e)) return 0;
664
	e = bro(son(e));
665
    aa:	if (name(e)==ident_tag && isparam(e)
666
		&& name(son(e)) != formal_callee_tag
667
		) return 0;
668
	if (name(e) == diagnose_tag) {
669
	    e = son(e); goto aa;
670
	}
671
	return 1;
672
}
673
 
674
int regfrmdest
675
    PROTO_N ( (dest, sp) )
676
    PROTO_T ( where * dest X space sp )
677
{
678
 	switch (dest->answhere.discrim) {
679
	  case inreg:
680
	    {
681
	      int r = regalt (dest->answhere);
682
	      if (r!=0) return r;
683
 
684
	    }
685
	  default:
686
	    {
687
	      return getreg (sp.fixed);
688
	    }
689
	}
690
}
691
 
692
space do_callers
693
    PROTO_N ( (list,sp) )
694
    PROTO_T ( exp list X space sp )
695
{	int   disp =0;
696
	int   spar = 4;
697
	int   fpar = 6;
698
	bool hadfixed = 0;
699
 
700
	  for (;;) {		/* evaluate parameters in turn */
701
	    int   hd = name (sh (list));
702
	    instore is;
703
	    where w;
704
	    ash ap;
705
	    int paral;
706
	    int parsize;
707
	    exp par;
708
	    par = (name(list)==caller_tag)?son(list):list;
709
	    ap = ashof (sh (list));
710
	    paral = (ap.ashalign < 32)?32:ap.ashalign;
711
	    parsize = ap.ashsize;
712
	    w.ashwhere = ap;
713
	    disp = rounder(disp,paral);
714
	    spar = 4+ (disp>>5);
715
	    is.b.base = 29;
716
	    is.b.offset = disp >> 3;
717
	    is.adval = 1;
718
	    if (disp>96) {spar =8; fpar = 8; }
719
 
720
	    if (is_floating(hd) && disp+parsize <= 128) {
721
	      freg frg;
722
	      ans ansfr;
723
	      frg.fr = fpar++;
724
	      frg.dble = (hd != shrealhd) ? 1 : 0;
725
	      setfregalt (ansfr, frg);
726
	      w.answhere = ansfr;
727
	      code_here (par, sp, w);
728
	      /* eval parameter into floating parameter register */
729
	      sp = guardfreg(frg.fr, sp);
730
	      if (hadfixed) {
731
		  setregalt (w.answhere, spar);
732
		  move (ansfr, w, sp, 1);
733
		  sp = guardreg(spar, sp);
734
		  if (hd != shrealhd) { sp = guardreg(spar+1, sp); }
735
	      }
736
	    }
737
	    else
738
	    if (valregable (sh (list)) && disp+parsize <=128) {
739
		ans ansr;
740
		setregalt (ansr, spar);
741
		w.answhere = ansr;
742
		hadfixed = 1;
743
		code_here (par, sp, w);
744
		/* eval parameter into fixed parameter register */
745
		sp = guardreg (spar, sp);
746
	    }
747
	    else {
748
		setinsalt (w.answhere, is);
749
		code_here (par, sp, w);
750
		hadfixed = 1;
751
		/* eval parameter into argument space on stack */
752
		while (spar <= 7 && ap.ashsize >0) {
753
			/* copy (parts of) any struct results into parregs */
754
			ls_ins(i_lw, spar, is.b);
755
			sp =guardreg(spar++, sp);
756
			is.b.offset +=4;
757
			ap.ashsize-=32;
758
		}
759
	   }
760
 
761
	   if(name(list)== caller_tag) { no(list) = disp; }
762
 
763
	   disp+=parsize;
764
	   disp = rounder(disp, 32);
765
 
766
 
767
	   if (last (list)) return sp;
768
	   list = bro (list);
769
	  }			/* end for */
770
 
771
}
772
 
773
 
774
 
775
void load_reg
776
    PROTO_N ( (e, r, sp) )
777
    PROTO_T ( exp e X int r X space sp )
778
{
779
	where w;
780
	w.ashwhere = ashof(sh(e));
781
	setregalt(w.answhere, r);
782
	code_here(e, sp, w);
783
}
784
 
785
static int diagPIClab;
786
 
787
typedef struct postl_ {exp pl; struct postl_ * outer; } postl_chain;
788
static postl_chain * old_pls;
789
 
790
void update_plc
791
    PROTO_N ( (ch, ma) )
792
    PROTO_T ( postl_chain * ch X int ma )
793
{
794
	while (ch != (postl_chain*)0) {
795
	  exp pl= ch->pl;
796
	  while (name(pl)==ident_tag && name(son(pl))==caller_name_tag) {
797
		no(pl)+= (ma<<1);
798
		pl = bro(son(pl));
799
	  }
800
	  ch = ch->outer;
801
	}
802
}
803
 
804
void do_callee_list
805
    PROTO_N ( (e, sp) )
806
    PROTO_T ( exp e X space sp )
807
{
808
    	long x = ((no(e)>>3)+23) & ~7;
809
    	exp list = son(e);
810
    	instore is;
811
    	where w;
812
    	baseoff b;
813
    	long disp;
814
    	ash ap;
815
    	disp = 0;
816
    	rri_ins(i_subu, 29, 29, x);
817
    	b.base = 29; b.offset = x-4;
818
    	ls_ins(i_sw, 30, b);
819
 
820
	update_plc(old_pls, x<<3);
821
 
822
    	if (no(e)!= 0) {
823
    		for(;;) {
824
    			ap = ashof(sh(list));
825
    			disp = rounder(disp, ap.ashalign);
826
    			is.b.offset = disp>>3;
827
    			is.b.base = 29; is.adval = 1;
828
    			w.ashwhere = ap;
829
    			setinsalt(w.answhere, is);
830
    			code_here(list, sp, w);
831
    			disp = rounder(disp+ap.ashsize, 32);
832
    			if (last(list)) break;
833
    			list = bro(list);
834
    		}
835
    	}
836
	update_plc(old_pls, -(x<<3));
837
}
838
 
839
exp find_ote
840
    PROTO_N ( (e, n) )
841
    PROTO_T ( exp e X int n )
842
{
843
	exp d = father(e);
844
	while (name(d)!=apply_general_tag) d = father(d);
845
	d = son(bro(son(d))); /* list otagexps */
846
	while(n !=0) { d = bro(d); n--;}
847
	Assert(name(d)==caller_tag);
848
	return d;
849
}
850
 
851
makeans make_code
852
    PROTO_N ( (e, sp, dest, exitlab) )
853
    PROTO_T ( exp e X space sp X where dest X int exitlab )
854
{
855
  /* produce code for expression e, putting its result in dest using
856
     t-regs given by sp. If non-zero, exitlab is the label of where the
857
     code is to continue */
858
  long  constval;
859
  makeans mka;
860
tailrecurse:
861
  mka.lab = exitlab;
862
  mka.regmove = NOREG;
863
 
864
 
865
 
866
  switch (name (e)) {
867
    case ident_tag:
868
      {
869
	where placew;
870
	int   r = NOREG;
871
	bool remember = 0;
872
 
873
 
874
 
875
 
876
	if (props (e) & defer_bit) {/* the tag of this declaration is
877
				   transparently identified with its
878
				   definition, without reserving more
879
				   space */
880
	  e = bro (son (e));
881
	  goto tailrecurse;
882
 
883
	}
884
 
885
 
886
 
887
	if (son (e) == nilexp) {/* I think this is historical - unused
888
				   tags are now removed cleanly */
889
	  placew = nowhere;
890
	}
891
        else
892
	if (name(son(e)) == caller_name_tag) {
893
		exp ote = find_ote(e,no(son(e)));
894
		long disp = no(ote);
895
		no(e) = (disp<<1)+29;
896
		placew = nowhere;
897
	}
898
	else {
899
	  ash a;
900
	  int   n = no (e);
901
	  a = ashof (sh (son (e)));
902
	  if ((props (e) & inreg_bits) != 0) {
903
	    /* tag in some fixed pt reg */
904
	    if (n == 0) {	/* if it hasn't been already allocated
905
				   into a s-reg (or r2) allocate tag into
906
				   fixed t-reg ... */
907
	      int   s = sp.fixed;
908
	      if (props (e) & notparreg)/* ... but not a parameter reg */
909
		s |= 0xf0;
910
	      n = getreg (s);
911
	      no (e) = n;
912
	    }
913
	    setregalt (placew.answhere, n);
914
	  }
915
	  else
916
	    if ((props (e) & infreg_bits) != 0) {
917
	      /* tag in some float reg */
918
	      freg frg;
919
	      if (n == 0) {	/* if it hasn't been already allocated
920
				   into a s-reg (or r0) allocate tag into
921
				   float-reg ... */
922
		int   s = sp.flt;
923
		if (props (e) & notparreg)
924
		  s |= 0xc0;
925
		n = getfreg (s);
926
		no (e) = n;
927
	      }
928
	      else
929
	      if (n == 16) {	/* result reg */
930
		  n = 0;
931
		  no (e) = 0;
932
	      }
933
 
934
 
935
	      frg.fr = n;
936
	      frg.dble = (a.ashsize == 64) ? 1 : 0;
937
	      setfregalt (placew.answhere, frg);
938
	    }
939
	    else
940
	    if (isparam(e) ) {
941
	      if(name(son(e))!=formal_callee_tag) {
942
	    	long n = (no(son(e)) + frame_size +callee_size)>>3 ; /* byte disp of params */
943
		instore is;
944
		is.adval =1;
945
		no(e) = ((no(son(e))+frame_size+callee_size-locals_offset)<<1)+29+Has_fp;
946
		if ((!Has_no_vcallers ||
947
			(isvis(e) && props(son(e)) != 0)) && last_param(e) ){
948
		        /* vararg in reg ? */
949
			int r = rounder(no(son(e))+shape_size(sh(son(e))), 32);
950
			while(r<=96) {
951
				is.b.offset = (r+((Has_fp)?0
952
						:frame_size+callee_size))>>3;
953
				is.b.base = 29+Has_fp;
954
				ls_ins(i_sw, 4+(r>>5), is.b);
955
				r+=32;
956
		        }
957
		}
958
		if (shape_size(sh(son(e)))==0) {
959
			/* vararg ... param */
960
			e = bro(son(e));
961
			goto tailrecurse;
962
		}
963
		is.b.offset = (Has_fp)? (no(son(e))>>3):n;
964
		is.b.base = 29 + Has_fp;
965
		if (BIGEND && props(son(e)) != 0 && shape_size(sh(son(e)))<32) {
966
			is.b.offset += (shape_size(sh(son(e)))==8)?3:2;
967
			/* short promotions */
968
		}
969
		setinsalt(placew.answhere, is);
970
		remember =1;
971
	      }
972
	      else {
973
	      	no(e) = ( ( no(son(e)) +frame_size - locals_offset)<<1)
974
	      	        + ((Has_vcallees)?local_reg:30);
975
		placew = nowhere;
976
	      }
977
	    }
978
	    else {		/* allocate on stack */
979
	      int   base = n & 0x3f;
980
	      instore is;
981
	      is.b.base = base;
982
	      is.b.offset = (n - base) >> 4;
983
	      is.adval = 1;
984
	      if (base == 29 ) {
985
		is.b.offset += locals_offset >> 3;
986
	      }
987
	      else
988
	      if ((base==30 && Has_fp) ) {
989
		is.b.offset += ((locals_offset-frame_size-callee_size) >> 3);
990
	      }
991
	      else
992
	      if ( (base == local_reg && Has_vcallees)) {
993
		is.b.offset += ((locals_offset -frame_size) >> 3);
994
	      }
995
	      setinsalt (placew.answhere, is);
996
	      remember = 1;
997
	    }
998
	  placew.ashwhere = a;
999
	}
1000
        if (isparam(e)
1001
        	&& name(son(e))!=formal_callee_tag) {
1002
          exp se = son(e);
1003
          exp d = e;
1004
	   /* parameter fiddles */
1005
           if (props(se) == 0 && (props(d) & inanyreg) !=0) {
1006
                /* not originally in required reg */
1007
                ans a;
1008
                instore is;
1009
		is.b.base = 29 + Has_fp;
1010
		is.b.offset = (no(se) +
1011
                               ((Has_fp)?0:(frame_size+callee_size)))>>3;
1012
                is.adval = 0;
1013
		if (BIGEND && shape_size(sh(son(e)))<32) {
1014
			is.b.offset += (shape_size(sh(son(e)))==8)?3:2;
1015
			/* short promotions */
1016
		}
1017
                setinsalt(a, is);
1018
                IGNORE move(a, placew, sp, is_signed(sh(se)));
1019
           }
1020
           else
1021
           if (props(se) !=0 && (props(d) & inanyreg) ==0) {
1022
                /* originally in reg and required in store */
1023
                ans a;
1024
                if (is_floating(name(sh(se))) ) {
1025
                   freg fr;
1026
                   fr.fr = props(se);
1027
                   fr.dble = (name(sh(se)) != shrealhd);
1028
                   setfregalt(a, fr);
1029
                }
1030
                else { setregalt(a, props(se)); }
1031
                r = move(a, placew, sp, 0);
1032
           }
1033
           else
1034
           if (props(se) !=0 && props(se) != no(d) ) {
1035
                /* in wrong register */
1036
                int sr = no(d);
1037
                int tr = props(se);
1038
                if (is_floating(name(sh(se))) ) {
1039
                   if ((fltdone & (3<<(sr<<1))) != 0) {
1040
                        rrfp_ins( (name(sh(se)) != shrealhd) ? i_mov_d: i_mov_s,
1041
                                no(d)<<1, props(se)<<1 );
1042
                   }
1043
                   else {
1044
                       props(se) = sr; no(d)= tr;
1045
                       sp = guardfreg(tr, sp);
1046
                       /* !? swopped and moved in  dump_tag !? */
1047
                   }
1048
                }
1049
                else {
1050
                   if ( (fixdone & (1<<sr)) !=0 ) {
1051
                        mon_ins(i_move, no(d), props(se) );
1052
                   }
1053
                   else {
1054
                       props(se) = sr; no(d)= tr;
1055
                       sp = guardreg(tr,sp);
1056
                        /* !? swopped for dump_tag !? */
1057
                   }
1058
                }
1059
           }
1060
           /* maybe more about promotions */
1061
 
1062
        }
1063
        else
1064
        if (isparam(e) && name(son(e))==formal_callee_tag) {
1065
                exp se = son(e);
1066
          	exp d = e;
1067
        	if ((props(d) & inanyreg) != 0) {
1068
        		/* callee parameter assigned to reg */
1069
        	ans a;
1070
                instore is;
1071
		if (Has_vcallees) {
1072
			is.b.base = local_reg;
1073
			is.b.offset = (no(se))>>3;
1074
		}
1075
		else {
1076
			is.b.base = 30;
1077
                	is.b.offset = (no(se) - callee_size)>>3;
1078
		}
1079
                is.adval = 0;
1080
                setinsalt(a, is);
1081
                IGNORE move(a, placew, sp, is_signed(sh(se)));
1082
               }
1083
        }
1084
        else
1085
	  r = code_here (son (e), sp, placew);
1086
		/* evaluate the initialisation of tag, putting it into place
1087
	   		allocated ... */
1088
 
1089
	if (remember && r != NOREG && pt (e) != nilexp && no(pt(e))==0
1090
	    && eq_sze (sh (son (e)), sh (pt (e)))) {
1091
	  /* ...if it was temporarily in a register, remember it */
1092
	  if (isvar (e)) {
1093
	    keepcont (pt (e), r);
1094
	  }
1095
	  else {
1096
	    keepreg (pt (e), r);
1097
	  }
1098
	}
1099
 
1100
 
1101
	sp =  guard (placew, sp);
1102
        e = bro (son (e));
1103
        goto tailrecurse;
1104
	/* and evaluate the body of the declaration */
1105
      }				/* end ident */
1106
 
1107
    case clear_tag: {
1108
 
1109
	return mka;
1110
      }
1111
 
1112
 
1113
 
1114
 
1115
 
1116
    case seq_tag:
1117
      {
1118
	exp t = son (son (e));
1119
	for (;;) {
1120
	  exp next = (last (t)) ? (bro (son (e))) : bro (t);
1121
	  if (name (next) == goto_tag) {/* gotos end sequences */
1122
	    make_code (t, sp, nowhere, no (son (pt (next))));
1123
	  }
1124
	  else {
1125
	    code_here (t, sp, nowhere);
1126
	  }
1127
	  if (last (t)) {
1128
	    e = bro (son (e));
1129
	    goto tailrecurse;
1130
	  }
1131
	  t = bro (t);
1132
	}
1133
      }				/* end seq */
1134
 
1135
    case cond_tag:
1136
      {
1137
	exp first = son (e);
1138
	exp second = bro (son (e));
1139
	exp test;
1140
 
1141
	if (dest.answhere.discrim == insomereg) {
1142
	  /* must make choice of register to contain answer to cond */
1143
	  int  *sr = someregalt (dest.answhere);
1144
	  if (*sr != -1) {
1145
	    failer ("Somereg *2");
1146
	  }
1147
	  *sr = getreg (sp.fixed);
1148
	  setregalt (dest.answhere, *sr);
1149
	}
1150
	else
1151
	if (dest.answhere.discrim == insomefreg) {
1152
	       somefreg sfr;
1153
	       freg fr;
1154
   	       sfr = somefregalt(dest.answhere);
1155
	       if (*sfr.fr != -1) { failer ("Somefreg *2"); }
1156
	       *sfr.fr = getfreg(sp.flt);
1157
	       fr.fr = *sfr.fr;
1158
	       fr.dble = sfr.dble;
1159
	       setfregalt(dest.answhere, fr);
1160
	}
1161
 
1162
	if (name (first) == goto_tag && pt (first) == second) {
1163
	  /* first is goto second */
1164
	  no (son (second)) = 0;
1165
	  return make_code (second, sp, dest, exitlab);
1166
	}
1167
	else
1168
	    if (name (second) == labst_tag &&
1169
		name (bro (son (second))) == top_tag) {
1170
	      /* second is empty */
1171
	      int   endl = (exitlab == 0) ? new_label () : exitlab;
1172
	      no (son (second)) = endl;
1173
	      make_code (first, sp, dest, endl);
1174
	      mka.lab = endl;
1175
	      return mka;
1176
	    }
1177
	    else
1178
	      if (name (second) == labst_tag &&
1179
		  name (bro (son (second))) == goto_tag) {
1180
		/* second is goto */
1181
		exp g = bro (son (second));
1182
		no (son (second)) = no (son (pt (g)));
1183
		return make_code (first, sp, dest, exitlab);
1184
	      }
1185
	if (test = testlast (first, second) /* I mean it */ ) {
1186
	  /* effectively an empty then part */
1187
	  int   l = (exitlab != 0) ? exitlab : new_label ();
1188
	  bool rev = IsRev(test);
1189
	  ptno(test) = -l;	/* make test jump to exitlab - see
1190
				   test_tag: */
1191
	  props (test) = notbranch[(props (test)&127) - 1];
1192
	   if (rev) { SetRev(test); }
1193
	  /* ... with inverse test */
1194
	  no (son (second)) = new_label ();
1195
	  make_code (first, sp, dest, l);
1196
	  make_code (second, sp, dest, l);
1197
	  mka.lab = l;
1198
	  return mka;
1199
	}
1200
	else {
1201
	  int   fl;
1202
	  no (son (second)) = new_label ();
1203
	  fl = make_code (first, sp, dest, exitlab).lab;
1204
 
1205
	  {
1206
	    int   l = (fl != 0) ? fl : ((exitlab != 0) ? exitlab : new_label ());
1207
/* Alteration 4 */
1208
	    if (name(sh(first))!= bothd || l == rscope_label) uncond_ins (i_b, l);
1209
	    make_code (second, sp, dest, l);
1210
	    clear_all ();
1211
	    mka.lab = l;
1212
	    return mka;
1213
	  }
1214
	}
1215
      }				/* end cond */
1216
 
1217
    case labst_tag:
1218
      {
1219
	if (no (son (e)) != 0) {
1220
	   set_label (no (son (e)));
1221
	}
1222
	if (is_loaded_lv(e) && No_S) { /* can be target of long_jump; reset sp */
1223
		baseoff b;
1224
		b.base = 30;
1225
		if (Has_vcallees) {
1226
			b.offset = -12;
1227
			ls_ins(i_lw, local_reg, b);
1228
		}
1229
		if (Has_tos) {
1230
			b.offset = -8;
1231
			ls_ins(i_lw, 29, b);
1232
		}
1233
		else {
1234
			rri_ins(i_subu, 29, 30, (frame_size+callee_size)>>3);
1235
		}
1236
	}
1237
	e = bro (son (e));
1238
	goto tailrecurse;
1239
 
1240
      }				/* end labst */
1241
 
1242
    case rep_tag:
1243
      {
1244
	exp first = son (e);
1245
	exp second = bro (first);
1246
/* Alteration 1: adds this line :- */
1247
	code_here(first, sp, nowhere);
1248
	no (son (second)) = new_label ();
1249
	e = second;
1250
	goto tailrecurse;
1251
 
1252
      }				/* end rep */
1253
 
1254
    case goto_tag:
1255
      {
1256
	exp gotodest = pt(e);
1257
	int   lab = no (son (gotodest));
1258
	clear_all ();
1259
	if (!last(e) || name(bro(e))!=seq_tag || !last(bro(e)) ||
1260
	      last(bro(bro(e))) || bro(bro(bro(e))) != gotodest) {
1261
	  uncond_ins (i_b, lab);
1262
	} /* dest is next in sequence */
1263
 
1264
	return mka;
1265
      }				/* end goto */
1266
 
1267
    case make_lv_tag: {
1268
    	int r = regfrmdest(&dest,sp);
1269
    	ans aa;
1270
    	condr_ins(i_la, r, no(son(pt(e))) ); /*???? */
1271
    	setregalt(aa,r);
1272
    	move(aa,dest, guardreg(r,sp), 0);
1273
    	mka.regmove = r;
1274
    	return mka;
1275
    }
1276
 
1277
    case long_jump_tag: {
1278
    	int fp = reg_operand(son(e), sp);
1279
    	int labval = reg_operand(bro(son(e)), sp);
1280
    	mon_ins(i_move, 30, fp);
1281
    	br_ins(i_j, labval);
1282
    	return mka;
1283
    }
1284
 
1285
    case max_tag: case min_tag: case offset_max_tag:
1286
      {
1287
	exp l = son (e);
1288
	exp r = bro (l);
1289
	shape shl = sh(l);
1290
	int a1, a2, d;
1291
	ans aa;
1292
	space nsp;
1293
	char * setins = sets(shl,3);
1294
	int lab = new_label();
1295
 
1296
	a1 = reg_operand(l, nsp);
1297
	nsp = guardreg(a1, sp);
1298
	d = regfrmdest(&dest, nsp);
1299
	if (d==a1) d = getreg(nsp.fixed);
1300
	nsp = guardreg(d, nsp);
1301
	if (name(r)== val_tag) {
1302
		 rri_ins (setins, d, a1, no (r));
1303
	}
1304
	else {
1305
	  	a2 = reg_operand (r, nsp);
1306
		if (d==a2) d = getreg(guardreg(a2,nsp).fixed);
1307
		rrr_ins (setins, d, a1, a2);
1308
	}
1309
 
1310
	setnoreorder();
1311
	condri_ins((name(e)!=min_tag)?i_beq:i_bne, d, 0, lab);
1312
	rrr_ins(i_addu, d, a1, 0);
1313
	if (name(r)==val_tag) {
1314
		baseoff b;
1315
		b.base = 0;
1316
		b.offset = no(r);
1317
		ls_ins(i_li, d, b);
1318
	}
1319
	else rrr_ins(i_addu,d,a2, 0);
1320
	set_label_no_clear(lab);
1321
	setreorder();
1322
 
1323
	setregalt (aa, d);
1324
        move (aa, dest, guardreg (d, sp), 0);
1325
        mka.regmove = d;
1326
        return mka;
1327
 
1328
 
1329
      }
1330
 
1331
 
1332
    case absbool_tag: case maxlike_tag: case minlike_tag: case abslike_tag:
1333
      {
1334
	exp l = son (son (e));
1335
	exp r = bro (l);
1336
	shape shl = sh (l);
1337
	char *setins;
1338
	int   n = props (son (e));
1339
	int   d;
1340
	int   a1;
1341
	int   a2;
1342
	bool xlike = (name(e) != absbool_tag);
1343
	ans aa;
1344
 
1345
	if (!xlike && name (l) == val_tag) {/* put literal operand on right */
1346
	  exp temp = l;
1347
	  l = r;
1348
	  r = temp;
1349
	  if (n <= 2) {
1350
	    n += 2;
1351
	  }
1352
	  else
1353
	    if (n <= 4) {
1354
	      n -= 2;
1355
	    }
1356
	}
1357
 
1358
	setins = sets(shl, n);
1359
	/* chose set instruction from test and shape */
1360
 
1361
	d = regfrmdest(&dest, sp);
1362
 
1363
	/* reg d will contain result of set (eventually) */
1364
 
1365
	a1 = reg_operand (l, sp);
1366
	if (xlike && a1==d) {
1367
		sp = guardreg(a1, sp);
1368
		d = getreg(sp.fixed);
1369
	}
1370
	if (name (r) == val_tag) {
1371
	  rri_ins (setins, d, a1, no (r));
1372
	}
1373
	else {
1374
	  space nsp;
1375
	  nsp = guardreg (a1, sp);
1376
	  a2 = reg_operand (r, nsp);
1377
	  if (xlike && a2==d) {
1378
	  	nsp = guardreg(a2, nsp);
1379
	  	d = getreg(nsp.fixed);
1380
	  }
1381
	  rrr_ins (setins, d, a1, a2);
1382
	}
1383
	if (name(e)==maxlike_tag || name(e)==minlike_tag) {
1384
		int l = new_label();
1385
		setnoreorder();
1386
		condri_ins((name(e)==maxlike_tag)?i_bne:i_beq, d, 0, l);
1387
		rrr_ins(i_addu, d, a1, 0);
1388
		if (name(r)==val_tag) {
1389
			baseoff b;
1390
			b.base = 0;
1391
			b.offset = no(r);
1392
			ls_ins(i_li, d, b);
1393
		}
1394
		else rrr_ins(i_addu,d,a2, 0);
1395
		set_label_no_clear(l);
1396
		setreorder();
1397
	}
1398
	else
1399
	if (name(e)==abslike_tag) {
1400
		int l = new_label();
1401
		setnoreorder();
1402
		condri_ins(i_bne, d, 0, l);
1403
		rrr_ins(i_addu, d, a1, 0);
1404
		rrr_ins(i_subu, d, 0, a1);
1405
		set_label_no_clear(l);
1406
		setreorder();
1407
	}
1408
 
1409
 
1410
 
1411
        setregalt (aa, d);
1412
        move (aa, dest, guardreg (d, sp), 0);
1413
        mka.regmove = d;
1414
        return mka;
1415
 
1416
 
1417
      }				/* end absbool */
1418
 
1419
 
1420
    case test_tag:
1421
      {
1422
	exp l = son (e);
1423
	exp r = bro (l);
1424
	int   lab = (ptno (e) < 0) ? -ptno (e) : no (son (pt (e)));
1425
	/* see frig in cond_tag */
1426
	shape shl = sh (l);
1427
	char *branch;
1428
	int   n = (props (e)) & 127; /* could have Rev bit in props*/
1429
 
1430
	if (is_floating (name (sh (l)))) {
1431
	  bool dble = (name (shl) != shrealhd) ? 1 : 0;
1432
	  int   a1;
1433
	  char *branch = (n <= 2 || n == 6) ? i_bc1t : i_bc1f;
1434
	  char *compare = (dble) ? fdbranches (n) : fbranches (n);
1435
	  /* choose branch and compare instructions */
1436
	  int   a2;
1437
	  space nsp;
1438
	  if (IsRev(e)) {
1439
		a2 = freg_operand(r, sp);
1440
		nsp = guardfreg(a2, sp);
1441
		a1 = freg_operand(l, nsp);
1442
	  }
1443
	  else {
1444
		a1 = freg_operand(l, sp);
1445
		nsp = guardfreg(a1, sp);
1446
		a2 = freg_operand(r, nsp);
1447
	  }
1448
 
1449
	  rrfpcond_ins (compare, a1 << 1, a2 << 1);
1450
	  br_ins (branch, lab);
1451
	  return mka;
1452
	}			/* end float test */
1453
	else {
1454
	  int   a1;
1455
	  int   a2;
1456
	  if (name (l) == val_tag) {/* put literal operand on right */
1457
	    exp temp = l;
1458
	    l = r;
1459
	    r = temp;
1460
	    if (n <= 2) {
1461
	      n += 2;
1462
	    }
1463
	    else
1464
	      if (n <= 4) {
1465
		n -= 2;
1466
	      }
1467
	  }
1468
	  branch = branches(shl, n);
1469
	  	/* choose branch instruction */
1470
	  a1 = reg_operand (l, sp);
1471
	  if (name (r) == val_tag) {
1472
	    condri_ins (branch, a1, no (r), lab);
1473
	  }
1474
	  else {
1475
	    space nsp;
1476
	    nsp = guardreg (a1, sp);
1477
	    a2 = reg_operand (r, nsp);
1478
	    condrr_ins (branch, a1, a2, lab);
1479
	  }
1480
 
1481
	  return mka;
1482
	}			/* end int test */
1483
      }				/* end test */
1484
 
1485
 
1486
    case ass_tag:
1487
    case assvol_tag:
1488
      {
1489
	exp lhs = son (e);
1490
	exp rhs = bro (lhs);
1491
	where assdest;
1492
	space nsp;
1493
	ash arhs;
1494
 
1495
	int   contreg = NOREG;
1496
	if (name (e) == assvol_tag) {
1497
	  clear_all ();
1498
	  setvolatile ();
1499
	}
1500
 
1501
	arhs = ashof (sh (rhs));
1502
 
1503
 
1504
	if (name (e) == ass_tag && name (rhs) == apply_tag &&
1505
	    (is_floating (name (sh (rhs))) || valregable (sh (rhs)))) {
1506
	  /* if source is simple proc call, evaluate it first and do
1507
	     assignment */
1508
	  ans aa;
1509
	  code_here (rhs, sp, nowhere);
1510
	  if (is_floating (name (sh (rhs)))) {
1511
	    freg frg;
1512
	    frg.fr = 0;
1513
	    frg.dble = (arhs.ashsize == 64) ? 1 : 0;
1514
	    setfregalt (aa, frg);
1515
	  }
1516
	  else {
1517
	    setregalt (aa, 2);
1518
	    sp = guardreg(2,sp);
1519
	  }
1520
	  assdest = locate (lhs, sp, sh (rhs), 0);
1521
	  move (aa, assdest, sp, 1);
1522
	  clear_dep_reg (lhs);
1523
	  return mka;
1524
	}
1525
 
1526
 
1527
	assdest = locate (lhs, sp, sh (rhs), 0);
1528
	nsp = guard (assdest, sp);
1529
	/* evaluate 'address' of destination */
1530
 
1531
	if (name (e) == ass_tag
1532
	      && assdest.answhere.discrim == notinreg) {
1533
	    instore is;
1534
	    is = insalt (assdest.answhere);
1535
	    if (!is.adval) {	/* this is an indirect assignment, so make
1536
				   it direct by loading pointer into reg
1537
				   (and remember it) */
1538
	      int   r = getreg (sp.fixed);
1539
	      ls_ins (i_lw, r, is.b);
1540
	      nsp = guardreg (r, sp);
1541
	      is.adval = 1;
1542
	      is.b.base = r;
1543
	      is.b.offset = 0;
1544
	      setinsalt (assdest.answhere, is);
1545
	      keepexp (lhs, assdest.answhere);
1546
	    }
1547
	  }
1548
 
1549
 
1550
	contreg = code_here (rhs, nsp, assdest);
1551
	/* evaluate source into assignment destination .... */
1552
 
1553
 
1554
 
1555
	switch (assdest.answhere.discrim) {
1556
	  case inreg:
1557
	    {
1558
	      int   a = regalt (assdest.answhere);
1559
	      keepreg (rhs, a);
1560
	      /* remember that source has been evaluated into a */
1561
	      clear_dep_reg (lhs);
1562
	      /* forget register dependencies on destination */
1563
	      break;
1564
	    }
1565
	  case infreg:
1566
	    {
1567
	      freg frg;
1568
	      int   r;
1569
	      frg = fregalt (assdest.answhere);
1570
	      r = frg.fr + 32;
1571
	      if (frg.dble) {
1572
		r = -r;
1573
	      };
1574
	      keepreg (rhs, r);
1575
	      /* remember that source has been evaluated into a */
1576
	      clear_dep_reg (lhs);
1577
	      /* forget register dependencies on destination */
1578
	      break;
1579
	    }
1580
 
1581
	  case notinreg:
1582
	    {
1583
	      if (contreg != NOREG && name (e) == ass_tag) {
1584
		clear_dep_reg (lhs);
1585
		/* forget register dependencies on destination */
1586
 
1587
		if (name(lhs) == name_tag) {
1588
			exp dc = son(lhs);
1589
			exp u = pt(dc);
1590
			while (u != nilexp) {
1591
				/* loook through uses to find cont(name) */
1592
			   if ( last(u) && no(u)==no(lhs) && bro(u)!=nilexp &&
1593
				name(bro(u))==cont_tag &&
1594
				shape_size(sh(bro(u))) == shape_size(sh(rhs)) ) {
1595
				keepreg (bro(u), contreg);
1596
				break;
1597
			   }
1598
			   u = pt(u);
1599
			}
1600
			/* remember cont of name as in contreg */
1601
 
1602
		}
1603
		else
1604
		if (!dependson (lhs, 0, lhs) ){
1605
		  /* remember that dest contains source, provided that it
1606
		     is not dependent on it */
1607
		  keepcont (lhs, contreg);
1608
		}
1609
		return mka;
1610
	      }
1611
	      clear_dep_reg (lhs);
1612
	      /* forget register dependencies on destination */
1613
	      break;
1614
	    }
1615
	  case insomereg: case insomefreg:
1616
	      {
1617
		clear_dep_reg (lhs);
1618
		/* forget register dependencies on destination */
1619
 
1620
	      }
1621
	}			/* end sw on answhere */
1622
 
1623
	if (name (e) == assvol_tag)
1624
	  setnovolatile ();
1625
	return mka;
1626
      }				/* end ass */
1627
 
1628
    case compound_tag:
1629
      {
1630
	exp t = son (e);
1631
	space nsp;
1632
	instore str;
1633
	int r;
1634
 
1635
	nsp = sp;
1636
	switch(dest.answhere.discrim) {
1637
	   case notinreg: {
1638
            str = insalt (dest.answhere);/* it should be !! */
1639
            if (!str.adval) {
1640
              int   r = getreg (sp.fixed);
1641
              nsp = guardreg (r, sp);
1642
              ls_ins (i_lw, r, str.b);
1643
              str.adval = 1;
1644
              str.b.base = r;
1645
              str.b.offset = 0;
1646
            }
1647
            for (;;) {
1648
              where newdest;
1649
              instore newis;
1650
              newis = str;
1651
              newis.b.offset += no(t);
1652
 
1653
              Assert(name(t)==val_tag && al2(sh(t)) >= 8);
1654
 
1655
 
1656
              setinsalt (newdest.answhere, newis);
1657
              newdest.ashwhere = ashof (sh(bro(t)));
1658
              code_here (bro(t), nsp, newdest);
1659
              if (last (bro(t))) {
1660
                return mka;
1661
              }
1662
              t = bro (bro(t));
1663
            }
1664
          }
1665
          case insomereg: {
1666
            int * sr = someregalt(dest.answhere);
1667
            if (*sr != -1) {
1668
              failer ("Somereg *2");
1669
            }
1670
            *sr = getreg (sp.fixed);
1671
            setregalt (dest.answhere, *sr);
1672
 	    /* ,... */
1673
          }
1674
          case inreg: {
1675
            code_here(bro(t), sp, dest);
1676
            r = regalt(dest.answhere);
1677
            Assert(name(t)==val_tag);
1678
            if (no(t) !=0) {
1679
            	rri_ins(i_sll, r, r, (al2(sh(t)) >= 8)? (no(t)<<3):no(t));
1680
            }
1681
            nsp = guardreg(r, sp);
1682
            while(!last(bro(t))) {
1683
            	int z;
1684
            	t = bro(bro(t));
1685
            	Assert(name(t)==val_tag);
1686
            	z = reg_operand(bro(t), nsp);
1687
            	if (no(t) !=0) {
1688
            		rri_ins(i_sll, z,z, (al2(sh(t)) >= 8)? (no(t)<<3):no(t) );
1689
                }
1690
                rrr_ins(i_or, r, r, z);
1691
            }
1692
            return mka;
1693
          }
1694
          case insomefreg: {
1695
	       somefreg sfr;
1696
	       freg fr;
1697
   	       sfr = somefregalt(dest.answhere);
1698
	       if (*sfr.fr != -1) { failer ("Somefreg *2"); }
1699
	       *sfr.fr = getfreg(sp.flt);
1700
	       fr.fr = *sfr.fr;
1701
	       fr.dble = sfr.dble;
1702
	       setfregalt(dest.answhere, fr);
1703
          }
1704
	  case infreg:{
1705
	    code_here(bro(t), sp, dest);
1706
	    if (!last(bro(t)) || name(t)!=val_tag || no(t) !=0) {
1707
	       failer("No Tuples in freg");
1708
	    }
1709
	    return mka;
1710
	  }
1711
        }
1712
 
1713
      }				/* end tup */
1714
 
1715
    case nof_tag: case concatnof_tag:
1716
   {
1717
	exp t = son (e);
1718
	space nsp;
1719
	instore str;
1720
	int r, disp = 0;
1721
 
1722
	if (t == nilexp) return mka;
1723
 
1724
	nsp = sp;
1725
	switch(dest.answhere.discrim) {
1726
	   case notinreg: {
1727
            str = insalt (dest.answhere);/* it should be !! */
1728
            if (!str.adval) {
1729
              int   r = getreg (sp.fixed);
1730
              nsp = guardreg (r, sp);
1731
              ls_ins (i_lw, r, str.b);
1732
              str.adval = 1;
1733
              str.b.base = r;
1734
              str.b.offset = 0;
1735
            }
1736
            for (;;) {
1737
              where newdest;
1738
              instore newis;
1739
              newis = str;
1740
              newis.b.offset += disp;
1741
              setinsalt (newdest.answhere, newis);
1742
              newdest.ashwhere = ashof (sh(t));
1743
              code_here (t, nsp, newdest);
1744
              if (last (t)) {
1745
                return mka;
1746
              }
1747
              disp+=(rounder(shape_size(sh(t)), shape_align(sh(bro(t))))>>3);
1748
              t =bro(t);
1749
            }
1750
          }
1751
          case insomereg: {
1752
            int * sr = someregalt(dest.answhere);
1753
            if (*sr != -1) {
1754
              failer ("Somereg *2");
1755
            }
1756
            *sr = getreg (sp.fixed);
1757
            setregalt (dest.answhere, *sr);
1758
 	    /* ,... */
1759
          }
1760
          case inreg: {
1761
            code_here(t, sp, dest);
1762
            r = regalt(dest.answhere);
1763
            nsp = guardreg(r, sp);
1764
            while(!last(t)) {
1765
            	int z;
1766
            	disp+=rounder(shape_size(sh(t)), shape_align(sh(bro(t))));
1767
            	t =bro(t);
1768
            	z = reg_operand(t, nsp);
1769
            	rri_ins(i_sll, z,z, disp );
1770
                rrr_ins(i_or, r, r, z);
1771
            }
1772
            return mka;
1773
          }
1774
	  default: failer("No Tuples in freg");
1775
        }
1776
 
1777
      }
1778
 
1779
      case ncopies_tag:
1780
   {
1781
	exp t = son (e);
1782
	space nsp;
1783
	instore str;
1784
	int i, r, disp = 0;
1785
 
1786
	nsp = sp;
1787
	switch(dest.answhere.discrim) {
1788
	   case notinreg: {
1789
            str = insalt (dest.answhere);/* it should be !! */
1790
            if (!str.adval) {
1791
              int   r = getreg (sp.fixed);
1792
              nsp = guardreg (r, sp);
1793
              ls_ins (i_lw, r, str.b);
1794
              str.adval = 1;
1795
              str.b.base = r;
1796
              str.b.offset = 0;
1797
            }
1798
            for (i=1;i<=no(e); i++) {
1799
              where newdest;
1800
              instore newis;
1801
              newis = str;
1802
              newis.b.offset += disp;
1803
              setinsalt (newdest.answhere, newis);
1804
              newdest.ashwhere = ashof (sh(t));
1805
              code_here (t, nsp, newdest);
1806
              disp+=(rounder(shape_size(sh(t)), shape_align(sh(t)))>>3);
1807
            }
1808
            return mka;
1809
          }
1810
          case insomereg: {
1811
            int * sr = someregalt(dest.answhere);
1812
            if (*sr != -1) {
1813
              failer ("Somereg *2");
1814
            }
1815
            *sr = getreg (sp.fixed);
1816
            setregalt (dest.answhere, *sr);
1817
 	    /* ,... */
1818
          }
1819
          case inreg: {
1820
            code_here(t, sp, dest);
1821
            r = regalt(dest.answhere);
1822
            nsp = guardreg(r, sp);
1823
            for(i=1; i<=no(e); i++) {
1824
            	int z;
1825
            	disp+=rounder(shape_size(sh(t)), shape_align(sh(t)));
1826
            	z = reg_operand(t, nsp);
1827
            	rri_ins(i_sll, z,z, disp );
1828
                rrr_ins(i_or, r, r, z);
1829
            }
1830
            return mka;
1831
          }
1832
	  default: failer("No Tuples in freg");
1833
        }
1834
 
1835
      }
1836
 
1837
    case caller_tag: {
1838
    	e = son(e); goto tailrecurse;
1839
    }
1840
 
1841
 
1842
 
1843
    case apply_general_tag:
1844
    	{
1845
    	  exp fn = son(e);
1846
    	  exp cers = bro(fn);
1847
    	  exp cees = bro(cers);
1848
    	  exp pl = bro(cees);
1849
    	  space nsp;
1850
 
1851
    	  if (no(cers) !=0) { nsp = do_callers(son(cers),sp); }
1852
	  else { nsp = sp; }
1853
 
1854
    	  IGNORE make_code(cees, nsp, nowhere, 0);
1855
 
1856
    	  if (name (fn) == name_tag && name (son (fn)) == ident_tag
1857
	    && (son (son (fn)) == nilexp ||
1858
	        name (son (son (fn))) == proc_tag ||
1859
	     name (son (son (fn))) == general_proc_tag)) {
1860
	  /* the procedure can be entered directly */
1861
	  	extj_ins (i_jal, boff (son (fn)));
1862
	  }
1863
	  else
1864
	  if (PIC_code) {
1865
		/* have to get address of proc into r25 */
1866
		where w;
1867
		setregalt(w.answhere, 25);
1868
		w.ashwhere = ashof(sh(fn));
1869
		code_here(fn,sp,w);
1870
		br_ins(i_jal, 25);
1871
          }
1872
    	  else {			/* the address of the proc is evaluated
1873
				   and entered indirectly */
1874
	  clear_reg(31); /* can't use 31 as temp reg for jal */
1875
	  br_ins (i_jal, reg_operand (fn, guardreg(31,sp)));
1876
	}
1877
	if (PIC_code) reset_gp();
1878
	clear_all ();		/* forget all register memories */
1879
        { int hda = name(sh(e));
1880
	  ans aa;
1881
	  if (is_floating (hda)) {
1882
	    freg frg;
1883
	    frg.fr = 0;
1884
	    frg.dble = (hda != shrealhd);
1885
	    setfregalt (aa, frg);
1886
	    move (aa, dest, sp, 1);
1887
	    /* move floating point result of application to destination */
1888
	  }
1889
	  else {
1890
	    setregalt (aa, 2);
1891
	    mka.regmove = 2;
1892
	    move (aa, dest, sp, 1);
1893
	    /* move floating point result of application to destination */
1894
	  }
1895
	  /* else struct results are moved by body of proc */
1896
	}
1897
 
1898
	if (call_is_untidy(cees)) {
1899
		rri_ins(i_subu, 29, 29, max_args>>3);
1900
		reset_tos();
1901
		Assert(name(pl)==top_tag);
1902
	}
1903
	else
1904
	if(postlude_has_call(e)) {
1905
		exp x = son(cers);
1906
		postl_chain p;
1907
		for(;x != nilexp ;) {
1908
			if (name(x)==caller_tag) {
1909
				no(x) += max_args;
1910
			}
1911
			if (last(x)) break;
1912
			x = bro(x);
1913
		}
1914
		mka.regmove = NOREG;
1915
		update_plc(old_pls, max_args);
1916
		p.pl = pl;
1917
		p.outer = old_pls;
1918
		old_pls = &p;
1919
		rri_ins(i_subu, 29, 29, max_args>>3);
1920
 		IGNORE make_code(pl, sp, nowhere, 0);
1921
		rri_ins(i_addu, 29, 29, max_args>>3);
1922
		old_pls = p.outer;
1923
		update_plc(old_pls, -max_args);
1924
	}
1925
	else
1926
		IGNORE make_code(pl, sp, nowhere, 0);
1927
 
1928
	return mka;
1929
    }
1930
 
1931
    case caller_name_tag: {
1932
    	return mka;
1933
    }
1934
 
1935
    case make_callee_list_tag: {
1936
 
1937
    	long x = ((no(e)>>3)+23) & ~7;
1938
	do_callee_list(e, sp);
1939
    	if (call_has_vcallees(e)) { rri_ins(i_addu, 30, 29, x);}
1940
    	return mka;
1941
/*
1942
	| 1st callee par	|	= sf on entry
1943
	| 2nd    "" 		|
1944
		.....
1945
  -16	| callers loc reg 23	| Has_vcallees	}
1946
  -12	| callees loc reg 23	| Has_vcallees	}  4 overhd wds
1947
  -8	| callees tos		| Has_tos	}
1948
  -4	| caller's fp = $30	|		}
1949
	 -----------------------
1950
	| caller pars		|   	= top of callers env
1951
	|			|		also $30 if var callees
1952
 
1953
*/
1954
    }
1955
    case same_callees_tag: {
1956
        baseoff b;
1957
        bool vc = call_has_vcallees(e);
1958
        space nsp;
1959
	exp bdy = son(crt_proc);
1960
 
1961
	while(name(bdy)==dump_tag || name(bdy)==diagnose_tag) bdy = son(bdy);
1962
	while (name(bdy)==ident_tag && isparam(bdy)) {
1963
		/* make sure that current callees are in right place */
1964
	   exp sbdy = son(bdy);
1965
	   if (name(sbdy)==formal_callee_tag &&(props(bdy) &inanyreg)!=0
1966
			&& isvar(bdy) ) {
1967
		baseoff b;
1968
		if (Has_fp) {
1969
			b.base = 30;
1970
			b.offset = (no(sbdy)-callee_size)>>3;
1971
		}
1972
		else {
1973
			b.base = 29;
1974
			b.offset = (no(sbdy)+frame_size)>>3;
1975
		}
1976
		if(is_floating(name(sh(sbdy)))) {
1977
			lsfp_ins((name(sh(sbdy))!=shrealhd)?i_s_d:i_s_s,
1978
					  no(bdy)<<1, b);
1979
		}
1980
		else ls_ins(i_sw, no(bdy), b);
1981
	    }
1982
	    bdy = bro(sbdy);
1983
	}
1984
 
1985
    	if (Has_vcallees) {
1986
    		/*  move [fp+16..local_reg] -> top of stack */
1987
 
1988
 
1989
    		int rsize = getreg(sp.fixed);
1990
    		int rsrce; int rdest;
1991
    		int t30;
1992
    		int le = new_label(); int lb = new_label();
1993
    		nsp = guardreg(rsize, sp);
1994
    		t30 = getreg(nsp.fixed); nsp = guardreg(t30, nsp);
1995
    		rsrce = getreg(nsp.fixed); nsp = guardreg(rsrce, nsp);
1996
    		rdest = getreg(nsp.fixed); nsp = guardreg(rdest, nsp);
1997
 
1998
    		mon_ins(i_move, t30, 29);
1999
    		rrr_ins(i_subu, rsize, 30, local_reg);
2000
    		rrr_ins(i_subu, 29,29, rsize);
2001
    		b.base = t30; b.offset = -4;
2002
    		ls_ins(i_sw, 30, b);
2003
    		rri_ins(i_subu, rsrce, 30, 16);
2004
    		rri_ins(i_subu, rdest, t30, 16);
2005
    		condrr_ins(i_beq, rdest, 29, le);
2006
    		set_label(lb);
2007
    		b.base = rsrce; b.offset = -4;
2008
    		ls_ins(i_lw, rsize, b);
2009
    		b.base = rdest;
2010
    		ls_ins(i_sw, rsize, b);
2011
    		rri_ins(i_subu, rsrce, rsrce, 4);
2012
    		rri_ins(i_subu, rdest, rdest, 4);
2013
    		condrr_ins(i_bne, rdest, 29, lb);
2014
    		set_label(le);
2015
    		if (vc) { mon_ins(i_move, 30, t30); }
2016
    	}
2017
    	else {
2018
    		int cs = (callee_size>>3);
2019
    		int i;
2020
    		int tr = getreg(sp.fixed);
2021
    		rri_ins(i_subu, 29,29, cs);
2022
    		b.base = 29; b.offset = cs-4;
2023
    		ls_ins(i_sw, 30, b);
2024
    		for(i = cs-16; i>0; i-=4) {
2025
    		        b.base = 30; b.offset = i-cs-4;
2026
    			ls_ins(i_lw, tr, b);
2027
    			b.base = 29; b.offset = i-4;
2028
    			ls_ins(i_sw, tr, b);
2029
    		}
2030
    		if (vc) { rri_ins(i_addu, 30, 29, cs); }
2031
    	}
2032
    	return mka;
2033
    }
2034
 
2035
 
2036
 
2037
    case make_dynamic_callee_tag: {
2038
    	bool vc = call_has_vcallees(e);
2039
    	int rptr;
2040
    	int rsize;
2041
    	int rdest;
2042
    	int tempreg;
2043
    	space nsp;
2044
    	baseoff b;
2045
    	int ls,le;
2046
	rptr = getreg(sp.fixed);
2047
	load_reg(son(e), rptr, sp);
2048
	nsp = guardreg(rptr, sp);
2049
	rsize = getreg(nsp.fixed);
2050
	load_reg(bro(son(e)), rsize, sp);
2051
	nsp = guardreg(rsize,nsp);
2052
	rdest = getreg(nsp.fixed);
2053
	nsp = guardreg(rdest,nsp);
2054
	tempreg = getreg(nsp.fixed);
2055
	rri_ins(i_addu, rdest, rsize, 7+16);
2056
	rri_ins(i_and, rdest,rdest, ~7);
2057
	b.base= 29; b.offset = -4;
2058
	ls_ins(i_sw, 30, b);
2059
	if (vc) mon_ins(i_move, 30, 29);
2060
	rrr_ins(i_subu, 29, 29, rdest);
2061
	rri_ins(i_addu, rdest, 29, 0);
2062
	ls = new_label();
2063
	le = new_label();
2064
	condrr_ins(i_ble, rsize, 0, le);
2065
	b.offset = 0;
2066
	set_label(ls);
2067
	b.base = rptr;
2068
	ls_ins(i_lw, tempreg, b);
2069
	b.base = rdest;
2070
	ls_ins(i_sw, tempreg, b);
2071
	rri_ins(i_addu, rdest, rdest, 4);
2072
	rri_ins(i_addu, rptr, rptr, 4);
2073
	rri_ins(i_subu, rsize, rsize, 4);
2074
	condrr_ins(i_bgt, rsize, 0, ls);
2075
	set_label(le);
2076
 
2077
        return mka;
2078
    }
2079
 
2080
    case tail_call_tag: {
2081
    	exp fn = son(e);
2082
    	exp cees = bro(fn);
2083
    	bool glob = (name (fn) == name_tag && name (son (fn)) == ident_tag
2084
	    		&& (son (son (fn)) == nilexp ||
2085
	        		name (son (son (fn))) == proc_tag ||
2086
	     			name (son (son (fn))) ==
2087
	     			general_proc_tag));
2088
	exp bdy = son(crt_proc);
2089
	int rptr; int rsz;
2090
	space nsp;
2091
	space xsp;
2092
	int temp_fn_reg;
2093
 
2094
	nsp=sp;
2095
	xsp=sp;
2096
    	if (name(cees)==make_callee_list_tag) {
2097
    		do_callee_list(cees, sp);
2098
    	}
2099
 
2100
	xsp.fixed = 0x800000f0;
2101
	nsp.fixed |= 0x800000f0; /* don't use parregs or linkreg */
2102
    	if (name(cees)==make_dynamic_callee_tag) {
2103
    		rptr = getreg(nsp.fixed);
2104
    		load_reg(son(cees),rptr,nsp);
2105
    		nsp = guardreg(rptr, nsp);
2106
		xsp = guardreg(rptr, xsp);
2107
    		rsz = getreg(nsp.fixed);
2108
    		load_reg(bro(son(cees)),rsz,nsp);
2109
    		nsp = guardreg(rsz, nsp);
2110
		xsp = guardreg(rsz,nsp);
2111
    	}
2112
    	if (PIC_code) {
2113
		temp_fn_reg = 25;
2114
		load_reg(fn,temp_fn_reg,nsp);
2115
	}
2116
	else
2117
    	if(!glob) {
2118
    		temp_fn_reg = getreg(nsp.fixed);
2119
    		load_reg(fn,temp_fn_reg,nsp);
2120
		nsp = guardreg(temp_fn_reg,nsp);
2121
		xsp = guardreg(temp_fn_reg,xsp);
2122
    	}
2123
 
2124
 
2125
	while(name(bdy)==dump_tag || name(bdy)==diagnose_tag) bdy = son(bdy);
2126
 
2127
	while (name(bdy)==ident_tag && isparam(bdy)) {
2128
		/* make sure that current callers and callees are in right place */
2129
		exp sbdy = son(bdy);
2130
		baseoff b;
2131
		if (Has_fp) {
2132
			b.base = 30;
2133
			b.offset = no(sbdy)>>3;
2134
		}
2135
		else {
2136
			b.base = 29;
2137
			b.offset = (no(sbdy)+frame_size+callee_size)>>3;
2138
		}
2139
		if (name(sbdy)==formal_callee_tag
2140
			&& name(cees)== same_callees_tag) {
2141
		   if ((props(bdy) &inanyreg)!=0) {
2142
			b.offset -= (callee_size>>3);
2143
			if(isvar(bdy)) {
2144
			  if(is_floating(name(sh(sbdy)))) {
2145
				lsfp_ins((name(sh(sbdy))!=shrealhd)?i_s_d:i_s_s,
2146
					  no(bdy)<<1, b);
2147
			  }
2148
			  else ls_ins(i_sw, no(bdy), b);
2149
			}
2150
		   }
2151
		}
2152
		else
2153
		if (props(sbdy) == 0 && (props(bdy) &inanyreg)!=0) {
2154
			/* should be instore; is in reg */
2155
			if(isvar(bdy)) {
2156
			  if(is_floating(name(sh(sbdy)))) {
2157
				lsfp_ins((name(sh(sbdy))!=shrealhd)?i_s_d:i_s_s,
2158
					  no(bdy)<<1, b);
2159
			  }
2160
			  else ls_ins(i_sw, no(bdy), b);
2161
			}
2162
		}
2163
		else
2164
		if (props(sbdy) !=0 && (props(bdy) & inanyreg) ==0) {
2165
		        /* should be in reg; is in store */
2166
	               if (!Has_no_vcallers && isvis(bdy) && last_param(bdy) ) {
2167
				int i = no(sbdy)>>5;
2168
				for(; i<4; i++) {
2169
					ls_ins(i_lw, i+4, b);
2170
					b.offset +=4;
2171
				}
2172
			}
2173
			else
2174
			if(is_floating(name(sh(sbdy)))) {
2175
				lsfp_ins((name(sh(sbdy))!=shrealhd)?i_l_d:i_l_s,
2176
					  props(sbdy)<<1, b);
2177
			}
2178
			else ls_ins(i_lw, props(sbdy), b);
2179
 
2180
		}
2181
		else
2182
		if (props(sbdy) !=0 && props(sbdy) != no(bdy) ) {
2183
                	/* in wrong register */
2184
                	if(is_floating(name(sh(sbdy)))) {
2185
                		rrfp_ins((name(sh(sbdy))!=shrealhd)?i_mov_d:i_mov_s,
2186
                		          props(sbdy)<<1, no(bdy)<<1);
2187
                        }
2188
                        else mon_ins(i_move, props(sbdy), no(bdy));
2189
               }
2190
 
2191
 
2192
               bdy = bro(sbdy);
2193
        }
2194
 
2195
        restore_sregs(fixdone, fltdone);
2196
 
2197
 
2198
       if (name(cees)==make_callee_list_tag) {
2199
       		/* copy from top of stack */
2200
       		int x = ((no(cees)>>3)+23) & ~7;
2201
       		int r = getreg(xsp.fixed);
2202
		int r1 = getreg(guardreg(r,xsp).fixed);
2203
       		int i;
2204
       		baseoff b;
2205
		int ncees = no(cees)>>3;
2206
		int rnc = (ncees+7)&~7;
2207
       		for(i= ncees; i > 0; i-=4) {
2208
		   int x = r;
2209
       		   b.base = 29; b.offset = i-4;
2210
       		   ls_ins(i_lw, r, b);
2211
       		   b.base = 30; b.offset = i-rnc-20;
2212
       		   ls_ins(i_sw, r, b);
2213
       		   r = r1; r1 = x;
2214
       		}
2215
    		/*
2216
 
2217
    		sp + 0: p1 ->   fp - 20: p1
2218
    		sp + 4: p2      fp - 24: p2
2219
    		sp + 8: p3      fp - 28: p3
2220
    			....
2221
    		*/
2222
 
2223
    		rri_ins(i_subu, 29, 30, x);
2224
 
2225
	}
2226
	else
2227
	if (name(cees)==make_dynamic_callee_tag) {
2228
		/* rdest = fp-16;
2229
		   rsize = (rsize+23)&~7
2230
		   rsource = rptr + rsize
2231
		   while rsize>0
2232
		      [rdest-4] = [rsource-4];
2233
		      rdest-=4; rsource-=4; rsize-=4;
2234
		   sp = rdest;
2235
		*/
2236
		int rdest; int rsize = rsz;
2237
		int rsource = rptr; int tempr;
2238
		int le, ls;
2239
		baseoff b;
2240
		rdest = getreg(xsp.fixed);
2241
		nsp = guardreg(rdest, nsp);
2242
		tempr = getreg(xsp.fixed);
2243
		rri_ins(i_subu, rdest, 30, 16);
2244
		rri_ins(i_addu, rsize, rsize, 7);
2245
		rri_ins(i_and, rsize, rsize, ~7);
2246
		rrr_ins(i_addu, rsource, rsource, rsize);
2247
		le = new_label(); ls = new_label();
2248
		condrr_ins(i_ble, rsize, 0, le);
2249
		set_label(ls);
2250
		b.base = rsource; b.offset = -4;
2251
		ls_ins(i_lw, tempr, b);
2252
		b.base = rdest;
2253
		ls_ins(i_sw, tempr, b);
2254
		rri_ins(i_subu, rdest, rdest, 4);
2255
		rri_ins(i_subu, rsource, rsource, 4);
2256
		rri_ins(i_subu, rsize, rsize, 4);
2257
		condrr_ins(i_bgt, rsize, 0, ls);
2258
		set_label(le);
2259
		mon_ins(i_move, 29, rdest);
2260
 
2261
 
2262
	}
2263
	else {
2264
		if (Has_vcallees) {
2265
			mon_ins(i_move, 29, local_reg);
2266
		}
2267
		else
2268
		if (Has_fp) {
2269
			 rri_ins(i_subu, 29, 30, callee_size>>3);
2270
		}
2271
		else { /* this should only occur in initialisation procs */
2272
			rri_ins(i_addu, 29, 29, (frame_size+callee_size)>>3);
2273
		}
2274
 
2275
	}
2276
 
2277
        if (Has_vcallees) {
2278
	  	baseoff b;
2279
	  	b.base = 30;
2280
	  	b.offset = -16;
2281
	  	ls_ins(i_lw, local_reg, b); /* old l-reg in -16(30) */
2282
	}
2283
    	if (glob && !PIC_code) {
2284
    		extj_ins(i_j, boff(son(fn)) );
2285
    	}
2286
    	else {
2287
    		br_ins(i_j, temp_fn_reg);
2288
 
2289
    	}
2290
    	clear_all();
2291
    	return mka;
2292
 
2293
 
2294
 
2295
    }
2296
 
2297
    case apply_tag:
2298
      {
2299
	exp fn = son (e);
2300
	exp par = bro (fn);
2301
	exp list = par;
2302
	exp dad = father (e);
2303
	bool tlrecurse = rscope_level == 0 && (name(dad)== res_tag) && props(dad);
2304
	int   hda = name (sh (e));
2305
	int disp;
2306
 
2307
	ash ansash;
2308
 
2309
 
2310
 
2311
	if ((disp = specialfn (fn)) > 0) {/* eg function is strlen */
2312
	  mka.lab = specialmake (disp, list, sp, dest, exitlab);
2313
	  return mka;
2314
	}
2315
 
2316
	ansash = ashof (sh (e));
2317
 
2318
	if (!last(fn)) {
2319
		sp = do_callers(list, sp);
2320
	}
2321
 
2322
 
2323
	if (name (fn) == name_tag && name (son (fn)) == ident_tag
2324
	    && (son (son (fn)) == nilexp || name (son (son (fn))) == proc_tag)) {
2325
	  /* the procedure can be entered directly */
2326
	  if (! tlrecurse) {
2327
	  	extj_ins (i_jal, boff (son (fn)));
2328
		if (PIC_code) reset_gp();
2329
	  }
2330
	  else {
2331
	  	if (Has_fp) {
2332
	  		baseoff b;
2333
	  		b.base = 30;
2334
	  		b.offset = -4;
2335
	  		restore_sregs(fixdone, fltdone);
2336
	  		mon_ins(i_move, 29, 30);
2337
	  		ls_ins(i_lw, 30, b);
2338
	  	}
2339
	  	else {
2340
	  		restore_sregs(fixdone, fltdone);
2341
	  		rri_ins(i_addu, 29, 29, (frame_size+callee_size)>>3);
2342
	  	}
2343
	  	extj_ins(i_j, boff(son(fn)) );
2344
	  	if (as_file) fprintf(as_file," # Tail recursion\n");
2345
	  }
2346
 
2347
	}
2348
	else
2349
	if (PIC_code) {
2350
		/* have to get address of proc into r25 */
2351
		where w;
2352
		setregalt(w.answhere, 25);
2353
		w.ashwhere = ashof(sh(fn));
2354
		code_here(fn,sp,w);
2355
		br_ins(i_jal, 25);
2356
		reset_gp();
2357
        }
2358
	else {			/* the address of the proc is evaluated
2359
				   and entered indirectly */
2360
	  clear_reg(31); /* can't use 31 as temp reg for jal */
2361
	  br_ins (i_jal, reg_operand (fn, guardreg(31,sp)));
2362
	}
2363
	clear_all ();		/* forget all register memories */
2364
        {
2365
	  ans aa;
2366
	  if (is_floating (hda)) {
2367
	    freg frg;
2368
	    frg.fr = 0;
2369
	    frg.dble = (hda != shrealhd);
2370
	    setfregalt (aa, frg);
2371
	    move (aa, dest, sp, 1);
2372
	    /* move floating point result of application to destination */
2373
	  }
2374
	  else {
2375
	    setregalt (aa, 2);
2376
	    mka.regmove = 2;
2377
	    move (aa, dest, guardreg(2,sp), 1);
2378
	    /* move fixed point result of application to destination */
2379
	  }
2380
	  /* else struct results are moved by body of proc */
2381
	}
2382
	return mka;
2383
      }				/* end apply */
2384
 
2385
    case return_to_label_tag: {
2386
	int r = getreg(sp.fixed);
2387
	where w;
2388
	setregalt(w.answhere, r);
2389
	w.ashwhere = ashof (sh(son (e)));
2390
	code_here (son (e), sp, w);
2391
	clear_all();
2392
	if (Has_fp) {
2393
		baseoff b;
2394
		b.base = 30;
2395
		restore_sregs (fixdone, fltdone);
2396
		if (Has_vcallees) {
2397
			b.offset = -16;
2398
			ls_ins(i_lw, local_reg, b);
2399
		}
2400
		b.offset = -4;
2401
		mon_ins(i_move, 29, 30);
2402
		ls_ins(i_lw, 30, b);
2403
	}
2404
	else
2405
	if (frame_size !=0) {
2406
		restore_sregs (fixdone, fltdone);
2407
		/* restore dumped value of s-regs on entry */
2408
		rri_ins (i_addu, 29, 29, frame_size >> 3);
2409
		/* reset stack ptr */
2410
	}
2411
	uncond_ins(i_j, r);
2412
	return mka;
2413
    }
2414
 
2415
 
2416
 
2417
    case res_tag: case untidy_return_tag:
2418
      {
2419
	where w;
2420
	w.answhere = procans;
2421
	w.ashwhere = ashof (sh (son (e)));
2422
	code_here (son (e), sp, w);
2423
	/* evaluate result value */
2424
 
2425
	clear_all ();		/* clear all register memories */
2426
 
2427
	if (rscope_level == 0) {/* normal proc body */
2428
	  if (name(son(e)) == apply_tag && props(e)) return mka;
2429
	  				/* was a tail recursion */
2430
	  if (frame_size == 0
2431
		  && !Has_fp) {
2432
	    uncond_ins (i_j, 31);
2433
	  }
2434
	  else
2435
	  if (result_label != 0 && name(e)==res_tag) {
2436
	  	uncond_ins(i_b, result_label);
2437
	  	if (as_file) fprintf(as_file, " # Return\n");
2438
	  }
2439
	  else{
2440
	      	if ((fixdone|fltdone)==0) {
2441
	  		result_label = new_label();
2442
	  		set_label(result_label);
2443
	     	}
2444
	  	if (Has_fp) {
2445
	  		baseoff b;
2446
	  		b.base = 30;
2447
	  		restore_sregs (fixdone, fltdone);
2448
	  		if (Has_vcallees) {
2449
	  			b.offset = -16;
2450
	  			ls_ins(i_lw, local_reg, b);
2451
	  		}
2452
			b.offset = -4;
2453
	  		if (name(e)==res_tag) mon_ins(i_move, 29, 30);
2454
	  		ls_ins(i_lw, 30, b);
2455
	  	}
2456
	  	else {
2457
                	restore_sregs (fixdone, fltdone);
2458
                	/* restore dumped value of s-regs on entry */
2459
                	if (frame_size != 0 && name(e) == res_tag) {
2460
                		rri_ins (i_addu, 29, 29, frame_size >> 3);
2461
                        }
2462
                	/* reset stack ptr */
2463
                }
2464
	      if (diagPIClab != 0) {
2465
		uncond_ins(i_b, diagPIClab);
2466
	      }
2467
	      else { uncond_ins (i_j, 31); }
2468
	    }
2469
	}
2470
	else {			/* inlined result */
2471
	  if (rscope_label == 0) rscope_label = new_label();
2472
	  if (rscope_label != exitlab) {
2473
	    uncond_ins (i_b, rscope_label);
2474
	  }
2475
	}
2476
	return mka;
2477
      }				/* end result */
2478
 
2479
    case diagnose_tag: {
2480
    	output_diag(dno(e), 0,e);
2481
    	mka = make_code (son (e), sp, dest, exitlab);
2482
	output_end_scope(dno(e),e);
2483
	return mka;
2484
    }
2485
 
2486
    /*
2487
	removed in version 3.0
2488
     case rscope_tag:
2489
      {
2490
 
2491
	  ans old_procans;
2492
	  int   old_rscope_label = rscope_label;
2493
	  if (dest.answhere.discrim == insomereg) {
2494
 
2495
	    int  *sr = someregalt (dest.answhere);
2496
	    if (*sr != -1) {
2497
	      failer ("Somereg *2");
2498
	    }
2499
	    *sr = getreg (sp.fixed);
2500
	    setregalt (dest.answhere, *sr);
2501
	  }
2502
	  else
2503
	  if (dest.answhere.discrim == insomefreg) {
2504
	       somefreg sfr;
2505
	       freg fr;
2506
   	       sfr = somefregalt(dest.answhere);
2507
	       if (*sfr.fr != -1) { failer ("Somefreg *2"); }
2508
	       *sfr.fr = getfreg(sp.flt);
2509
	       fr.fr = *sfr.fr;
2510
	       fr.dble = sfr.dble;
2511
	       setfregalt(dest.answhere, fr);
2512
	  }
2513
	  rscope_level++;
2514
	  old_procans = procans;
2515
	  procans = dest.answhere;
2516
	  rscope_label =  exitlab;
2517
 
2518
	  if (as_file) fprintf(as_file, " # start inlined proc\n");
2519
	  mka = make_code (son (e), sp, dest, rscope_label);
2520
	  if (as_file) fprintf(as_file, " # end inlined proc\n");
2521
 
2522
 
2523
	  if (mka.lab != 0 && mka.lab != rscope_label) {
2524
	  	set_label(mka.lab);
2525
	  }
2526
	  mka.lab = rscope_label;
2527
	  mka.regmove = NOREG;
2528
	  rscope_level--;
2529
	  procans = old_procans;
2530
	  rscope_label = old_rscope_label;
2531
	  return mka;
2532
	}
2533
*/
2534
 
2535
    case solve_tag:
2536
      {
2537
	exp m = bro (son (e));
2538
	int   l = exitlab;
2539
	if (dest.answhere.discrim == insomereg) {
2540
	  /* choose register for result */
2541
	  int  *sr = someregalt (dest.answhere);
2542
	  if (*sr != -1) {
2543
	    failer ("Somereg *2");
2544
	  }
2545
	  *sr = getreg (sp.fixed);
2546
	  setregalt (dest.answhere, *sr);
2547
	}
2548
	else
2549
	if (dest.answhere.discrim == insomefreg ){
2550
	       somefreg sfr;
2551
	       freg fr;
2552
   	       sfr = somefregalt(dest.answhere);
2553
	       if (*sfr.fr != -1) { failer ("Somefreg *2"); }
2554
	       *sfr.fr = getfreg(sp.flt);
2555
	       fr.fr = *sfr.fr;
2556
	       fr.dble = sfr.dble;
2557
	       setfregalt(dest.answhere, fr);
2558
	}
2559
 
2560
	for (;;) {		/* set up all the labels in the component
2561
				   labst_tags */
2562
	  no (son (m)) = new_label ();
2563
	  if (last (m))
2564
	    break;
2565
	  m = bro (m);
2566
	}
2567
 
2568
	m = son (e);
2569
	for (;;) {		/* evaluate all the component statements
2570
				*/
2571
	  int   fl = make_code (m, sp, dest, l).lab;
2572
	  clear_all ();
2573
	  if (fl != 0)
2574
	    l = fl;
2575
	  if (!last (m)) {	/* jump to end of solve */
2576
	    if (l == 0)
2577
	      l = new_label ();
2578
	    if (name (sh (m)) != bothd) {
2579
	      uncond_ins (i_b, l);
2580
	    }
2581
	  }
2582
	  if (last (m)) {
2583
	    mka.lab = l;
2584
	    return mka;
2585
	  };
2586
	  m = bro (m);
2587
	}
2588
      }				/* end solve */
2589
 
2590
 
2591
 
2592
    case case_tag:
2593
      {
2594
	int   r = reg_operand (son (e), sp);
2595
	/* evaluate controlling integer into reg r */
2596
	mm lims;
2597
	exp z = bro (son (e));
2598
	exp zt = z;
2599
	long  n;
2600
	long  l;
2601
	long  u = 0x80000000;
2602
 
2603
	sp = guardreg(r,sp);
2604
	l = no (zt);
2605
	for (n = 1;; n++) {	/* calculate crude criterion for using
2606
				   jump vector or branches */
2607
	  if (u + 1 != no (zt) && son (zt) != nilexp) {
2608
	    n++;
2609
	  }
2610
	  if (last (zt)) {
2611
	    u = (son (zt) != nilexp) ? no (son (zt)) : no (zt);
2612
	    break;
2613
	  }
2614
	  if (son (zt) != nilexp) {
2615
	    u = no (son (zt));
2616
	  }
2617
	  else {
2618
	    if (u + 1 == no (zt))
2619
	      u += 1;
2620
	  }
2621
 
2622
	  zt = bro (zt);
2623
	}
2624
 
2625
	/* now l is lowest controlling value and u is highest */
2626
 
2627
	if (is_signed(sh(son(e))) ) { u = u/2 - l/2; }
2628
	else { u = ((unsigned)u)/2 - ((unsigned)l)/2; }
2629
 
2630
	if ( u <= n * n / 4 -3 /* ware overflow! */) {
2631
	  /* space-time product criterion for jump vector instead of tests
2632
	     and branches *//* use jump vector */
2633
	  int   endlab = new_label ();
2634
	  int   veclab = next_dlab_sym ();
2635
	  baseoff zeroveclab;
2636
	  baseoff zero3;
2637
	  int   mr = getreg (sp.fixed);
2638
	  int r3 = getreg(guardreg(mr,sp).fixed);
2639
	  zero3.base = r3;
2640
	  zero3.offset = 0;
2641
	  zeroveclab.offset = 0;
2642
	  zeroveclab.base = veclab;
2643
	  n = l;
2644
 
2645
	  if (as_file)
2646
	    fprintf (as_file, "\t.rdata\n$$%d:\n", veclab);
2647
	  out_common (0, irdata);
2648
	  out_common (tempsnos[veclab - 32], ilabel);
2649
	  for (;;) {
2650
	    for (; no (z) > n; n++) {/* o/p jump vector */
2651
	      if (as_file)
2652
		fprintf (as_file,
2653
			(PIC_code)?"\t.gpword\t$%d\n":"\t.word\t$%d\n", endlab);
2654
	      out_value (-endlab, (PIC_code)?igpword:iword, 0, 1);
2655
	    }
2656
	    u = (son (z) == nilexp) ? n : no (son (z));
2657
	    for (; n <= u; n++) {
2658
	      props(son(pt(z))) = 1; /* as bug - see labst_tag */
2659
	      if (as_file)
2660
		fprintf (as_file,
2661
			 (PIC_code)?"\t.gpword\t$%d\n":"\t.word\t$%d\n", no (son (pt (z))));
2662
	      out_value (-no (son (pt (z))), (PIC_code)?igpword:iword, 0, 1);
2663
	    }
2664
	    if (last (z))
2665
	      break;
2666
	    z = bro (z);
2667
	  }
2668
 
2669
	  if (as_file)
2670
	    fprintf (as_file, "\t.text\n");
2671
	  out_common (0, itext);
2672
 
2673
	  ls_ins (i_la, r3, zeroveclab);
2674
	  if (l != 0) {
2675
	    rri_ins (i_addu, mr, r, -l);
2676
	    condri_ins (i_bgeu, mr, u - l + 1, endlab);
2677
	    rri_ins (i_mul, mr, mr, 4);
2678
	  }
2679
	  else {
2680
	    condri_ins (i_bgeu, r, u + 1, endlab);
2681
	    rri_ins (i_mul, mr, r, 4);
2682
	  }
2683
	  rrr_ins (i_addu, r3, r3, mr);
2684
	  ls_ins (i_lw, r3, zero3);
2685
	  if (PIC_code) {  rrr_ins(i_addu, r3, r3, 28); }
2686
	  uncond_ins (i_j, r3);
2687
	  set_label (endlab);
2688
	  return mka;
2689
	}
2690
	else
2691
	if (is_signed(sh(son(e)))) {
2692
	  int   over = 0;	/* use branches - tests are already
2693
				   ordered */
2694
	  bool usw;
2695
	  lims = maxmin (sh (son (e)));
2696
	  for (;;) {
2697
	    int   lab = no (son (pt (z)));
2698
	    long l = no (z);
2699
	    if (son (z) == nilexp) {/* only single test required */
2700
	      condri_ins (i_beq, r, l, lab);
2701
	      if (l == lims.maxi)
2702
		lims.maxi -= 1;
2703
	      else
2704
		if (l == lims.mini)
2705
		  lims.mini += 1;
2706
	    }
2707
	    else
2708
	      if (u = no (son (z)), l > lims.mini) {
2709
		if ( u >= lims.maxi)
2710
		{/* have already tested lower */
2711
		  condri_ins (i_bge, r, l, lab);
2712
		  lims.maxi = l - 1;
2713
		}
2714
		else {
2715
		  if (over == 0) {
2716
		    over = new_label ();
2717
		  }
2718
		  condri_ins (i_blt, r, l, over);
2719
		  condri_ins (i_ble, r, u, lab);
2720
		  lims.mini = u + 1;
2721
		}
2722
	      }
2723
	      else		/* lower is <= lower limit of shape */
2724
		if (u < lims.maxi) {
2725
		  condri_ins (i_ble, r, u, lab);
2726
		  lims.mini = u + 1;
2727
		}
2728
		else {		/* upper is >= upper limit of shape */
2729
		  uncond_ins (i_b, lab);
2730
		}
2731
	    if (last (z)) {
2732
	      if (over != 0) {
2733
		set_label (over);
2734
	      } return mka;
2735
	    }
2736
	    z = bro (z);
2737
	  }
2738
	}
2739
	else {
2740
	  int   over = 0;	/* use branches - tests are already
2741
				   ordered */
2742
	  unsigned long maxi;
2743
	  unsigned long mini;
2744
	  lims = maxmin (sh (son (e)));
2745
	  maxi = (unsigned)lims.maxi;
2746
	  mini = (unsigned)lims.mini;
2747
	  for (;;) {
2748
	    int   lab = no (son (pt (z)));
2749
	    unsigned long l = no (z);
2750
	    if (son (z) == nilexp) {/* only single test required */
2751
	      condri_ins (i_beq, r, l, lab);
2752
	      if (l == maxi)
2753
		maxi -= 1;
2754
	      else
2755
		if (l == mini)
2756
		  mini += 1;
2757
	    }
2758
	    else
2759
	      if (u = no (son (z)), l > mini) {
2760
		if ( u >= maxi)
2761
		{/* have already tested lower */
2762
		  condri_ins (i_bgeu, r, l, lab);
2763
		  maxi = l - 1;
2764
		}
2765
		else {
2766
		  if (over == 0) {
2767
		    over = new_label ();
2768
		  }
2769
		  condri_ins (i_bltu, r, l, over);
2770
		  condri_ins (i_bleu, r, u, lab);
2771
		  mini = u + 1;
2772
		}
2773
	      }
2774
	      else		/* lower is <= lower limit of shape */
2775
		if (u < maxi) {
2776
		  condri_ins (i_bleu, r, u, lab);
2777
		  mini = u + 1;
2778
		}
2779
		else {		/* upper is >= upper limit of shape */
2780
		  uncond_ins (i_b, lab);
2781
		}
2782
	    if (last (z)) {
2783
	      if (over != 0) {
2784
		set_label (over);
2785
	      } return mka;
2786
	    }
2787
	    z = bro (z);
2788
	  }
2789
	}
2790
 
2791
      }				/* end case */
2792
 
2793
    case offset_add_tag: { /* byte offset + bit offset - see needs scan */
2794
	exp l = son(e);
2795
	exp r = bro(l);
2796
	int r1 = reg_operand(l, sp);
2797
	int tmp, d, r2;
2798
	space nsp;
2799
	ans aa;
2800
	tmp = getreg(sp.fixed);
2801
	rri_ins(i_sll, tmp, r1, 3);
2802
	d = regfrmdest(&dest, sp);
2803
	if (name(r)==val_tag) {
2804
		rri_ins(i_addu, d, tmp, no(r));
2805
	}
2806
	else {
2807
		nsp = guardreg(tmp, sp);
2808
		r2 = reg_operand(r, nsp);
2809
		rrr_ins(i_addu, d, tmp, r2);
2810
	}
2811
	setregalt(aa, d);
2812
	mka.regmove = move(aa, dest, guardreg(d, sp), 0);
2813
	return mka;
2814
    }
2815
 
2816
   case offset_subtract_tag: { /* bit offset - byte offset - see needs scan */
2817
	exp l = son(e);
2818
	exp r = bro(l);
2819
	int r2 = reg_operand(r, sp);
2820
	int tmp, d, r1;
2821
	space nsp;
2822
	ans aa;
2823
	tmp = getreg(sp.fixed);
2824
	rri_ins(i_sll, tmp, r2, 3);
2825
	d = regfrmdest(&dest, sp);
2826
	nsp = guardreg(tmp, sp);
2827
	r1 = reg_operand(l, nsp);
2828
	rrr_ins(i_subu, d, r1, tmp);
2829
 
2830
	setregalt(aa, d);
2831
	mka.regmove = move(aa, dest, guardreg(d, sp), 0);
2832
	return mka;
2833
    }
2834
 
2835
 
2836
 
2837
    case plus_tag:
2838
      {
2839
        if (optop(e) ) {
2840
          mka.regmove =
2841
            comm_op (e, sp, dest, i_addu);
2842
          return mka;
2843
        }
2844
       if ((errhandle(e)&3)==3 && is_signed(sh(e)) && shape_size(sh(e))==32 ) {
2845
          mka.regmove =
2846
            comm_op (e, sp, dest, i_add);
2847
          return mka;
2848
        }
2849
        else {
2850
          /* possible overflow - can optimised a bit fot lit. operand*/
2851
          int r1 = reg_operand(son(e), sp);
2852
          int r2, r3, r0;
2853
          long over = new_label();
2854
          long trap = trap_label(e);
2855
          space nsp;
2856
          ans aa;
2857
          nsp = guardreg(r1, sp);
2858
          r2 = reg_operand(bro(son(e)), nsp);
2859
          nsp = guardreg(r2, nsp);
2860
          r0 = getreg(nsp.fixed);
2861
          nsp = guardreg(r0, nsp);
2862
          rrr_ins(i_addu, r0, r1, r2);
2863
 
2864
          switch(name(sh(e)) ) {
2865
             case slonghd: {
2866
             	r3 = getreg(nsp.fixed);
2867
          	rrr_ins(i_xor, r3, r1, r2);
2868
 
2869
          	condr_ins(i_bltz, r3, over);
2870
          	rrr_ins(i_xor, r3, r0, r1);
2871
          	condr_ins(i_bltz, r3, trap);
2872
 
2873
          	set_label(over);
2874
          	break;
2875
             }
2876
             case ulonghd: {
2877
             	r3 = getreg(nsp.fixed);
2878
          	mon_ins(i_not, r3, r1);
2879
          	rrr_ins(i_sltu, r3, r3, r2);
2880
          	condrr_ins(i_bne, r3, 0, trap);
2881
          	break;
2882
             }
2883
             case scharhd: {
2884
                testsigned(r0, -128, 127, trap);
2885
                break;
2886
             }
2887
             case ucharhd: {
2888
                testusigned(r0, 255, trap);
2889
                break;
2890
             }
2891
             case swordhd: {
2892
                testsigned(r0, -0x8000, 0x7fff, trap);
2893
                break;
2894
             }
2895
             case uwordhd: {
2896
                testusigned(r0, 0xffff, trap);
2897
                break;
2898
             }
2899
             default: failer("NOT integer in plus with o/f");
2900
          }
2901
          setregalt(aa, r0);
2902
          mka.regmove = move(aa, dest, nsp, 0);
2903
          return mka;
2904
      }
2905
    }				/* end plus */
2906
 
2907
 
2908
    case chvar_tag:
2909
      {
2910
	int   a;
2911
	int   d;
2912
	ans aa;
2913
	int   nsh = name (sh (e));
2914
	if (!BIGEND && dest.answhere.discrim == inreg
2915
		&& regalt(dest.answhere) != 0) {
2916
	      ash arga;
2917
	      arga = ashof (sh (son (e)));
2918
	      if (arga.ashsize <= dest.ashwhere.ashsize) {
2919
		dest.ashwhere = arga;
2920
	      }
2921
	      a = regalt (dest.answhere);
2922
	      code_here (son (e), sp, dest);
2923
	      /* evaluate arguement into reg */
2924
	}
2925
	else {
2926
	      a = reg_operand (son (e), sp);
2927
	      /* evaluate arguement into a */
2928
	}
2929
	setregalt (aa, a);
2930
	if (!optop(e)) {
2931
		long trap = trap_label(e);
2932
		bool sg = is_signed(sh(son(e)));
2933
		switch(nsh) {
2934
		case scharhd:
2935
	           	if (sg) { testsigned(a, -128, 127, trap);}
2936
			else { testusigned(a, 127, trap); }
2937
			break;
2938
		case ucharhd: testusigned(a, 255, trap); break;
2939
		case swordhd:
2940
			if (sg){ testsigned(a, -0x8000, 0x7fff, trap); }
2941
			else { testusigned(a, 0x7fff, trap); }
2942
			break;
2943
		case uwordhd: testusigned(a, 0xffff, trap); break;
2944
		case slonghd:
2945
			if (!sg) { testusigned(a, 0x7fffffff, trap); }
2946
			break;
2947
		case ulonghd:
2948
			if (sg) { testusigned(a, 0x7fffffff, trap); }
2949
			break;
2950
		}
2951
		mka.regmove = move (aa, dest, sp, 1);
2952
		return mka;
2953
	}
2954
 
2955
	if (sh (son (e)) == sh (e) || nsh  >= slonghd) {
2956
	  /* no changes required, so just move */
2957
	  mka.regmove = move (aa, dest, sp, 1);
2958
	  return mka;
2959
	}
2960
 
2961
	switch (dest.answhere.discrim) {
2962
	  case insomereg:
2963
	    {
2964
	      int  *dr = someregalt (dest.answhere);
2965
	      d = getreg (sp.fixed);
2966
	      *dr = d;
2967
	      goto out;
2968
	    }
2969
	  case inreg:
2970
	    {
2971
	      d = regalt (dest.answhere);
2972
	      goto out;
2973
	    }
2974
	  default:
2975
	    /* representation in store will be same so just move */
2976
	    {
2977
	      move (aa, dest, sp, 1);
2978
	      return mka;
2979
	    }
2980
	}
2981
 
2982
    out: 			/* d is destination register - do
2983
				   appropriate ands etc */
2984
	if (d==0) return mka;
2985
 
2986
	if (nsh == ucharhd) {
2987
	  rri_ins (i_and, d, a, 255);
2988
	}
2989
	else
2990
	  if (nsh == uwordhd) {
2991
	    rri_ins (i_and, d, a, (1 << 16) - 1);
2992
	  }
2993
	  else
2994
	    if (nsh == scharhd) {
2995
	      rri_ins (i_sll, d, a, 24);
2996
	      rri_ins (i_sra, d, d, 24);
2997
	    }
2998
	    else
2999
	      if (nsh == swordhd) {
3000
		rri_ins (i_sll, d, a, 16);
3001
		rri_ins (i_sra, d, d, 16);
3002
	      }
3003
	mka.regmove = d;
3004
	return mka;
3005
      }				/* end chvar */
3006
 
3007
    case minus_tag:
3008
      {
3009
        if (optop(e)) {
3010
          mka.regmove =
3011
            non_comm_op (e, sp, dest, i_subu);
3012
          return mka;
3013
        }
3014
        else
3015
	if ((errhandle(e)&3)==3 && is_signed(sh(e)) && shape_size(sh(e))==32 ) {
3016
          mka.regmove =
3017
            non_comm_op (e, sp, dest, i_sub);
3018
          return mka;
3019
        }
3020
        else {
3021
          /* possible overflow - can optimised a bit for lit. operand*/
3022
          int r1 = reg_operand(son(e), sp);
3023
          int r2, r3, r0;
3024
          long over = new_label();
3025
          long trap = trap_label(e);
3026
          space nsp;
3027
          ans aa;
3028
          nsp = guardreg(r1, sp);
3029
          r2 = reg_operand(bro(son(e)), nsp);
3030
          nsp = guardreg(r2, nsp);
3031
          r0 = getreg(nsp.fixed);
3032
          nsp = guardreg(r0,nsp);
3033
          rrr_ins(i_subu, r0, r1, r2);
3034
          switch(name(sh(e))) {
3035
             case slonghd: {
3036
             	r3 = getreg(nsp.fixed);
3037
             	rrr_ins(i_xor, r3, r1, r2);
3038
 
3039
             	condr_ins(i_bgez, r3, over);
3040
             	rrr_ins(i_xor, r3, r0, r1);
3041
             	condr_ins(i_bltz, r3, trap);
3042
 
3043
             	set_label(over);
3044
/* Alteration 2 also in plus_tag */
3045
             	break;
3046
             }
3047
             case ulonghd: {
3048
             	r3 = getreg(nsp.fixed);
3049
/* Alteration 3 */
3050
             	rrr_ins(i_sltu, r3, r1, r2);
3051
             	condrr_ins(i_bne, r3, 0, trap);
3052
             	break;
3053
             }
3054
             case scharhd: {
3055
                testsigned(r0, -128, 127, trap);
3056
                break;
3057
             }
3058
             case ucharhd: {
3059
                testusigned(r0, 255, trap);
3060
                break;
3061
             }
3062
             case swordhd: {
3063
                testsigned(r0, -0x8000, 0x7fff, trap);
3064
                break;
3065
             }
3066
             case uwordhd: {
3067
                testusigned(r0, 0xffff, trap);
3068
                break;
3069
             }
3070
             default: failer("NOT integer in minus with o/f");
3071
          }
3072
          setregalt(aa, r0);
3073
          mka.regmove = move(aa, dest, nsp, 0);
3074
          return mka;
3075
      }
3076
 
3077
    }				/* end minus */
3078
 
3079
    case mult_tag: case offset_mult_tag:
3080
      {
3081
	exp rop = bro (son (e));
3082
	if (!optop(e)) {	/* test for overflo */
3083
          int r1 = reg_operand(son(e), sp);
3084
          int r2, r3, r0;
3085
          long trap = trap_label(e);
3086
          space nsp;
3087
          ans aa;
3088
          nsp = guardreg(r1, sp);
3089
          r2 = reg_operand(bro(son(e)), nsp);
3090
          nsp = guardreg(r2, nsp);
3091
          r0 = getreg(nsp.fixed);
3092
          nsp = guardreg(r0, nsp);
3093
          r3 = getreg(nsp.fixed);
3094
          switch(name(sh(e))) {
3095
             case slonghd: {
3096
                int r4;
3097
		mon_ins(i_mult, r1, r2);
3098
		hilo_ins(i_mflo, r0);
3099
		hilo_ins(i_mfhi, r3);
3100
		r4 = getreg(guardreg(r3, nsp).fixed);
3101
		rri_ins(i_sra, r4, r0, 31);
3102
		condrr_ins(i_bne, r4, r3, trap);
3103
		break;
3104
	     }
3105
	     case ulonghd: {
3106
	     	mon_ins(i_multu, r1, r2);
3107
	     	hilo_ins(i_mflo, r0);
3108
	     	hilo_ins(i_mfhi, r3);
3109
	     	condrr_ins(i_bne, r3, 0, trap);
3110
	     	break;
3111
	     }
3112
             case scharhd: {
3113
             	rrr_ins(i_mul, r0, r1, r2);
3114
                testsigned(r0, -128, 127, trap);
3115
                break;
3116
             }
3117
             case ucharhd: {
3118
                rrr_ins(i_mul, r0, r1, r2);
3119
                testusigned(r0, 255, trap);
3120
                break;
3121
             }
3122
             case swordhd: {
3123
                rrr_ins(i_mul, r0, r1, r2);
3124
                testsigned(r0, -0x8000, 0x7fff, trap);
3125
                break;
3126
             }
3127
             case uwordhd: {
3128
             	rrr_ins(i_mul, r0, r1, r2);
3129
                testusigned(r0, 0xffff, trap);
3130
                break;
3131
             }
3132
             default: failer("NOT integer in mult with o/f");
3133
          }
3134
          setregalt(aa, r0);
3135
          mka.regmove = move(aa, dest, nsp, 0);
3136
          return mka;
3137
      }
3138
 
3139
 
3140
 
3141
	if (last (rop) && name (rop) == val_tag) {
3142
	  /* multiplication by constant m */
3143
	  int   m = no (rop);
3144
	  int   p2;
3145
	  if (m > 1 && (
3146
		((p2 = m) & (m - 1)) == 0 ||
3147
		(m & (p2 = m + 1)) == 0 ||
3148
		((p2 = m - 1) & (m - 2)) == 0
3149
	      )
3150
	    ) {			/* m = 2^shleng   or  m = 2^(shleng +/- 1)
3151
				*/
3152
	    int   r = reg_operand (son (e), sp);
3153
	    /* evaluate first arguement */
3154
	    int   rr;
3155
	    space nsp;
3156
	    int   shleng;
3157
	    ans aa;
3158
	    for (shleng = 0; p2 != 1; shleng++)
3159
	      p2 >>= 1;
3160
 
3161
	    switch (dest.answhere.discrim) {
3162
	      case inreg:
3163
		{
3164
		  rr = regalt (dest.answhere);
3165
		  if (rr != r || (m & (m - 1)) == 0) {
3166
		    nsp = sp;
3167
		    break;
3168
		  }
3169
		  /* else continue to next case */
3170
		}
3171
	      default:
3172
		{
3173
		 	if ((m &(m-1))==0) {
3174
				rr = getreg(sp.fixed);
3175
				nsp = sp;
3176
			}
3177
			else {
3178
				nsp = guardreg (r, sp);
3179
		  		rr = getreg (nsp.fixed);
3180
			}
3181
		}
3182
	    }
3183
 
3184
	    rri_ins (i_sll, rr, r, shleng);
3185
 
3186
	    if ((m & (m - 1)) != 0)
3187
	      rrr_ins (((m & (m + 1)) == 0) ? i_subu : i_addu, rr, rr, r);
3188
	    setregalt (aa, rr);
3189
	    mka.regmove = move (aa, dest, guardreg (rr, sp), 1);
3190
	    return mka;
3191
	  }
3192
	}			/* else do straightforward mult */
3193
 
3194
	mka.regmove = comm_op (e, sp, dest, i_mul);
3195
	return mka;
3196
      }				/* end mult */
3197
 
3198
 
3199
 
3200
    case div0_tag:case div2_tag: case offset_div_by_int_tag: case offset_div_tag:
3201
      {
3202
	exp rop = bro (son (e));
3203
	exp lop = son(e);
3204
	bool uns = !(is_signed(sh (e)));
3205
	int trap;
3206
	space nsp;
3207
	int r0, r1, r2;
3208
	ans aa;
3209
	if ( name (rop) == val_tag ) {
3210
	  /* division by constant */
3211
	  int   m = no (rop);
3212
	  if (m==1) {
3213
		e = lop;
3214
		goto tailrecurse;
3215
	  }
3216
	  if ((name(e) == div0_tag || uns) && m > 1 && (m & (m - 1)) == 0) {
3217
	      int   r = reg_operand (son (e), sp);
3218
	       /* replace div by 2^shleng by sh right shleng */
3219
              int   shleng;
3220
              int   rr;
3221
              for (shleng = 0; m != 1; shleng++)
3222
                m >>= 1;
3223
 
3224
              rr = regfrmdest(&dest, sp);
3225
              rri_ins ( (uns)?i_srl:i_sra, rr, r, shleng);
3226
              setregalt (aa, rr);
3227
              mka.regmove = move (aa, dest, guardreg (rr, sp), 1);
3228
              return mka;
3229
          }
3230
	}
3231
 
3232
	r1 = reg_operand(lop, sp);
3233
	nsp = guardreg(r1, sp);
3234
	r2 = reg_operand(rop, nsp);
3235
 
3236
	if (!optop(e)|| (errhandle(e)&3)==2) { /* test for (-inf)/-1 and /0 */
3237
	   long over = new_label();
3238
           trap = ((errhandle(e)&3)==2)?new_label():trap_label(e);
3239
	   condri_ins(i_beq, r2, 0, trap);
3240
	   if (!uns) {
3241
             condri_ins(i_bne, r2, -1, over);
3242
             condri_ins(i_beq, r1, maxmin(sh(e)).mini, trap);
3243
             set_label(over);
3244
           }
3245
	}
3246
	r0 = regfrmdest(&dest,sp);
3247
	rrr_ins((uns)?i_divu:i_div, r0, r1, r2);
3248
	if ((errhandle(e)&3)==2) set_label(trap);
3249
	setregalt(aa, r0);
3250
	mka.regmove = move(aa, dest, guardreg(r0,sp), 0);
3251
	return mka;
3252
      }
3253
 
3254
      case div1_tag:
3255
 
3256
      {  /* only applies to signed operands */
3257
	exp rop = bro (son (e));
3258
	exp lop = son(e);
3259
	space nsp;
3260
	int r0, r1, r2;
3261
	int lab, treg, trap;
3262
	ans aa;
3263
 
3264
	if (name (rop) == val_tag ) {/*  division by constant */
3265
	  int   m = no (rop);
3266
	  if (m > 1 && (m & (m - 1)) == 0) {
3267
	      int   r = reg_operand (son (e), sp);
3268
	       /* replace div by 2^shleng by arith sh right shleng */
3269
              int   shleng;
3270
              int   rr;
3271
              for (shleng = 0; m != 1; shleng++)
3272
                m >>= 1;
3273
 
3274
              rr = regfrmdest(&dest, sp);
3275
              rri_ins ( i_sra, rr, r, shleng);
3276
              setregalt (aa, rr);
3277
              mka.regmove = move (aa, dest, guardreg (rr, sp), 1);
3278
              return mka;
3279
          }
3280
	}
3281
 
3282
	r1 = reg_operand(lop, sp);
3283
	nsp = guardreg(r1, sp);
3284
	r2 = reg_operand(rop, nsp);
3285
	nsp = guardreg(r2, sp);
3286
 
3287
 
3288
	if (!optop(e)|| (errhandle(e)&3)==2) { /* test for (-inf)/-1 and /0 */
3289
	   long over = new_label();
3290
           trap = ((errhandle(e)&3)==2)?new_label():trap_label(e);
3291
	   condri_ins(i_beq, r2, 0, trap);
3292
           condri_ins(i_bne, r2, -1, over);
3293
           condri_ins(i_beq, r1, maxmin(sh(e)).mini, trap);
3294
           set_label(over);
3295
	}
3296
	r0 = regfrmdest(&dest,nsp);
3297
        rrr_ins((is_signed(sh(e)))?i_div:i_divu, r0, r1, r2);
3298
	treg = getreg(guardreg(r0,nsp).fixed);
3299
	lab = new_label();
3300
	hilo_ins(i_mfhi, treg);
3301
	condri_ins(i_beq, treg, 0, lab);
3302
	rrr_ins(i_xor, treg, treg, r2);
3303
	rri_ins(i_sra, treg, treg, 31);
3304
	rrr_ins(i_addu, r0, r0, treg);
3305
	set_label(lab);
3306
	if ((errhandle(e)&3)==2) set_label(trap);
3307
	setregalt(aa, r0);
3308
	mka.regmove = move(aa, dest, guardreg(r0,sp), 0);
3309
	return mka;
3310
    }
3311
 
3312
 
3313
    case abs_tag: {
3314
	int r = reg_operand(son(e), sp);
3315
	int d = regfrmdest(&dest, guardreg(r, sp));
3316
	int l = new_label();
3317
	ans aa;
3318
	setnoreorder();
3319
	condri_ins(i_bge,r, 0, l);
3320
	rri_ins(i_addu, d, r, 0);
3321
	rrr_ins(i_subu, d, 0, r);
3322
	setreorder();
3323
	if (!optop(e)) {
3324
		condri_ins (i_ble, r, maxmin(sh(e)).mini, trap_label(e));
3325
	}
3326
        set_label_no_clear(l);
3327
	setregalt(aa, d);
3328
	mka.regmove = move(aa, dest, guardreg(d, sp), 0);
3329
	return mka;
3330
    }
3331
    case neg_tag: case offset_negate_tag:
3332
      {
3333
	if (optop(e) ) {
3334
          mka.regmove = monop (e, sp, dest, i_negu);
3335
          return mka;
3336
        }
3337
        if ((errhandle(e)&3)==3 && shape_size(sh(e)) == 32) {
3338
          mka.regmove = monop (e, sp, dest, i_neg);
3339
          return mka;
3340
        }
3341
        else {
3342
          int r1 = reg_operand(son(e), sp);
3343
          long trap = trap_label(e);
3344
          int r2;
3345
          ans aa;
3346
          condri_ins((is_signed(sh(e)))?i_ble:i_bne, r1, maxmin(sh(e)).mini, trap);
3347
          r2 = getreg(sp.fixed);
3348
          mon_ins(i_neg, r2, r1);
3349
	  if (is_signed(sh(e)))condri_ins(i_ble, r2, maxmin(sh(e)).mini, trap);
3350
	  setregalt(aa, r2);
3351
	  mka.regmove = move(aa, dest, guardreg(r2, sp), 0);
3352
	  return mka;
3353
	}
3354
 
3355
 
3356
      }				/* end neg */
3357
 
3358
 
3359
 
3360
    case goto_lv_tag: {
3361
    	int r = reg_operand(son(e),sp);
3362
    	uncond_ins(i_j, r);
3363
    	clear_all();
3364
    	return mka;
3365
    }
3366
 
3367
 
3368
 
3369
    case shl_tag:
3370
    case shr_tag:
3371
      {
3372
	exp s = son (e);
3373
	exp b = bro (s);
3374
	int   a;
3375
	int   d;
3376
	int sz = shape_size(sh(s));
3377
        bool lded = ((name (s) == name_tag && regofval (s) >= 100)
3378
	      		|| (name (s) == cont_tag &&
3379
		    (name (son (s)) != name_tag || regofval (son (s)) > 0)
3380
	      		    )
3381
		    );
3382
        bool signok = (sz == 32 || name(s)== chvar_tag || lded );
3383
	ans aa;
3384
	space nsp;
3385
	bool sgned = is_signed(sh (e));
3386
	char *shnat;
3387
	char *shun;
3388
	int norms = 0;
3389
	if (lded && name (b) == val_tag && (no (b) == 16 || no (b) == 24)
3390
	    && name (e) == shr_tag  ) {
3391
		/* can use short loads instead of shifts */
3392
	  where w;
3393
	  instore is;
3394
	  w = locate (s, sp, sh (s), 0);
3395
	  /* 'address' of  first operand with shape of result */
3396
 
3397
	  switch (w.answhere.discrim) {
3398
	      /* if w is a register we still have to do shifts */
3399
	    case inreg: {
3400
		a = regalt (w.answhere);
3401
		goto alreadythere;
3402
	      }
3403
	    case notinreg:
3404
	      {
3405
		is = insalt (w.answhere);
3406
		if (!is.adval)
3407
		  break;
3408
		if (is.b.offset == 0 && (a = is.b.base) >= 0 && a <= 31) {
3409
		  goto alreadythere;
3410
		}
3411
	      }
3412
	    default: {	/* this shoudn't happen - shift of address or
3413
	    		    perhaps float in reg */
3414
	    	where temp;
3415
		a = -1;
3416
		setsomeregalt(temp.answhere, &a);
3417
		temp.ashwhere = dest.ashwhere;
3418
		move(w.answhere, temp, sp, 1);
3419
		goto alreadythere;
3420
	      }
3421
	  }
3422
 
3423
	  d = regfrmdest(&dest,sp);
3424
 
3425
	  /* d is destination register */
3426
	  if (!BIGEND) {
3427
            if (no (b) == 16) {
3428
              is.b.offset += 2;
3429
            }
3430
            else {
3431
              is.b.offset += 3;
3432
            }
3433
          }
3434
	  ls_ins ((no (b) == 16) ? ((sgned) ? i_lh : i_lhu) : ((sgned) ? i_lb : i_lbu),
3435
	      d, is.b);
3436
	  setregalt (aa, d);
3437
	  move (aa, dest, guardreg (d, sp), 0);
3438
	  mka.regmove = d;
3439
	  return mka;
3440
 
3441
	}
3442
 
3443
	a = reg_operand (s, sp);
3444
    alreadythere:
3445
	/* choose which shift instruction */
3446
	if (name (e) == shr_tag) {
3447
	  shnat = (sgned) ? i_sra : i_srl;
3448
	  shun = i_sll;
3449
	  if (!signok) {
3450
		rri_ins(i_sll, a, a, norms = 32-sz);
3451
	  }
3452
	}
3453
	else {
3454
	  shnat = i_sll;
3455
	  shun = (sgned) ? i_sra : i_srl;
3456
	}
3457
 
3458
 
3459
	nsp = guardreg (a, sp);
3460
	d = regfrmdest(&dest, nsp);
3461
 
3462
 
3463
	if (name (b) == val_tag) {
3464
	  /* if its a constant shift we dont have to choose shift
3465
	     dynamically ... */
3466
	  if (no (b) >= 0) {
3467
	    rri_ins (shnat, d, a, no (b)+norms);
3468
	  }
3469
	  else {
3470
	    rri_ins (shun, d, a, -no (b));
3471
	  }
3472
	}
3473
	else {
3474
	  int   sr = getreg (nsp.fixed);
3475
	  int   ar = reg_operand (b, nsp);
3476
	  if (norms != 0) {
3477
		rri_ins(shnat, a, a, norms);
3478
	  }
3479
	  if (NONEGSHIFTS || !is_signed(sh(e))
3480
	      || (name (b) == and_tag && name (bro (son (b))) == val_tag
3481
		&& no (bro (son (b))) > 0 && no (bro (son (b))) <= 31)
3482
	    ) {			/* ... similarly in these cases */
3483
	    rrr_ins (shnat, d, a, ar);
3484
	  }
3485
	  else {		/* choose shift dynamically - is this
3486
				   necessary for C? */
3487
	    int   l = new_label ();
3488
	    int   endl = new_label ();
3489
	    condri_ins (i_bge, ar, 0, l);
3490
	    mon_ins (i_neg, sr, ar);
3491
	    rrr_ins (shun, d, a, sr);
3492
	    uncond_ins (i_b, endl);
3493
	    set_label (l);
3494
	    rrr_ins (shnat, d, a, ar);
3495
	    set_label (endl);
3496
	  }
3497
	}
3498
	setregalt (aa, d);
3499
	move (aa, dest, nsp, 1);
3500
	mka.regmove = d;
3501
	return mka;
3502
      }				/* end shl */
3503
 
3504
 
3505
 
3506
    case mod_tag:
3507
      {  /* only applies to signed operands */
3508
	exp rop = bro (son (e));
3509
	exp lop = son(e);
3510
	space nsp;
3511
	int r0, r1, r2;
3512
	int lab, treg;
3513
	ans aa;
3514
	if (name (rop) == val_tag) {/* mod by constant */
3515
	  int   m = no (rop);
3516
	  if (m > 1 && (m & (m - 1)) == 0) {
3517
	    /* mod by power of 2 replaced by and */
3518
	    int   r = reg_operand (son (e), sp);
3519
	    ans aa;
3520
	    int   rr = regfrmdest(&dest,sp);
3521
	    rri_ins (i_and, rr, r, no (rop) - 1);
3522
	    setregalt (aa, rr);
3523
	    mka.regmove = move (aa, dest, guardreg (rr, sp), 1);
3524
	    return mka;
3525
	  }
3526
	}
3527
 
3528
	r1 = reg_operand(lop, sp);
3529
	nsp = guardreg(r1, sp);
3530
	r2 = reg_operand(rop, nsp);
3531
 
3532
	if (!optop(e)) { /* test for (-inf)/-1 and /0 */
3533
	   long over = new_label();
3534
           long trap = trap_label(e);
3535
	   condri_ins(i_beq, r2, 0, trap);
3536
           condri_ins(i_bne, r2, -1, over);
3537
           condri_ins(i_beq, r1, maxmin(sh(e)).mini, trap);
3538
           set_label(over);
3539
	}
3540
	r0 = regfrmdest(&dest, nsp);
3541
	rrr_ins(i_rem, r0, r1, r2);
3542
	treg= getreg(guardreg(r0, nsp).fixed);
3543
	lab = new_label();
3544
	condri_ins(i_beq, r0, 0, lab);
3545
	rrr_ins(i_xor, treg, r0, r2);
3546
	condri_ins(i_bge, treg, 0, lab);
3547
	rrr_ins(i_addu, r0, r0, r2);
3548
	set_label(lab);
3549
	setregalt(aa, r0);
3550
	mka.regmove = move(aa, dest, guardreg(r0,sp), 0);
3551
	return mka;
3552
    }
3553
 
3554
    case rem2_tag: case rem0_tag:
3555
      {
3556
	exp rop = bro (son (e));
3557
	exp lop = son(e);
3558
	bool uns = !is_signed(sh (e));
3559
	space nsp;
3560
	int r0, r1, r2;
3561
	ans aa;
3562
	if ((uns || name(e)==rem0_tag) && name (rop) == val_tag) {
3563
		/* mod by constant */
3564
	  int   m = no (rop);
3565
	  if (m > 1 && (m & (m - 1)) == 0) {
3566
	    /* mod by power of 2 replaced by and */
3567
	    int   r = reg_operand (son (e), sp);
3568
	    ans aa;
3569
	    int   rr = regfrmdest(&dest,sp);
3570
	    rri_ins (i_and, rr, r, no (rop) - 1);
3571
	    setregalt (aa, rr);
3572
	    mka.regmove = move (aa, dest, guardreg (rr, sp), 1);
3573
	    return mka;
3574
	  }
3575
	  if( m != 0 && (m!=-1 || uns)) {
3576
	  	r1 = reg_operand(lop, sp);
3577
	  	r0 = regfrmdest(&dest, sp);
3578
		rri_ins((uns)?i_remu:i_rem, r0, r1, m);
3579
		setregalt(aa, r0);
3580
		mka.regmove = move(aa, dest, guardreg(r0,nsp), 0);
3581
		return mka;
3582
	  }
3583
	}
3584
 
3585
	r1 = reg_operand(lop, sp);
3586
	nsp = guardreg(r1, sp);
3587
	r2 = reg_operand(rop, nsp);
3588
 
3589
	if (!optop(e)) { /* test for (-inf)/-1 and /0 */
3590
	   long over = new_label();
3591
           long trap = trap_label(e);
3592
	   condri_ins(i_beq, r2, 0, trap);
3593
	   if (!uns) {
3594
             condri_ins(i_bne, r2, -1, over);
3595
             condri_ins(i_beq, r1, maxmin(sh(e)).mini, trap);
3596
             set_label(over);
3597
           }
3598
	}
3599
 
3600
	r0 = regfrmdest(&dest, sp);
3601
	rrr_ins((uns)?i_remu:i_rem, r0, r1, r2);
3602
	setregalt(aa, r0);
3603
	mka.regmove = move(aa, dest, guardreg(r0,nsp), 0);
3604
	return mka;
3605
 
3606
      }				/* end mod */
3607
 
3608
 
3609
    case minptr_tag: case make_stack_limit_tag:
3610
      {
3611
	mka.regmove = non_comm_op (e, sp, dest, i_subu);
3612
	return mka;
3613
      }
3614
 
3615
    case fplus_tag:
3616
      {
3617
	mka.regmove =
3618
	  fop (e, sp, dest, (name (sh (e)) != shrealhd) ? i_add_d : i_add_s);
3619
	if (!optop(e)) checknan(e, sp);
3620
	return mka;
3621
      }
3622
 
3623
    case fminus_tag:
3624
      {
3625
	mka.regmove =
3626
	  fop (e, sp, dest, (name (sh (e)) != shrealhd) ? i_sub_d : i_sub_s);
3627
	if (!optop(e)) checknan(e, sp);
3628
	return mka;
3629
      }
3630
 
3631
    case fmult_tag:
3632
      {
3633
	mka.regmove =
3634
	  fop (e, sp, dest, (name (sh (e)) != shrealhd) ? i_mul_d : i_mul_s);
3635
	if (!optop(e)) checknan(e, sp);
3636
	return mka;
3637
      }
3638
 
3639
    case fdiv_tag:
3640
      {
3641
	mka.regmove =
3642
	  fop (e, sp, dest, (name (sh (e)) != shrealhd) ? i_div_d : i_div_s);
3643
	if (!optop(e)) checknan(e, sp);
3644
	return mka;
3645
      }
3646
 
3647
    case fneg_tag:
3648
      {
3649
	mka.regmove =
3650
	  fmop (e, sp, dest, (name (sh (e)) != shrealhd) ? i_neg_d : i_neg_s);
3651
	if (!optop(e)) checknan(e, sp);
3652
	return mka;
3653
      }
3654
 
3655
    case fabs_tag:
3656
      {
3657
	mka.regmove =
3658
	  fmop (e, sp, dest, (name (sh (e)) != shrealhd) ? i_abs_d : i_abs_s);
3659
	if (!optop(e)) checknan(e, sp);
3660
	return mka;
3661
      }
3662
 
3663
    case float_tag:
3664
      {
3665
	exp in = son (e);
3666
	where w;
3667
	int r;
3668
	int   f
3669
	=     (dest.answhere.discrim == infreg) ? regalt (dest.answhere)
3670
				/* cheat */
3671
	:     getfreg (sp.flt);
3672
	freg frg;
3673
	ans aa;
3674
	ash ain;
3675
	ain = ashof (sh (in));
3676
	frg.fr = f;
3677
	frg.dble = 0;
3678
	if (ain.ashsize == 32 && name(sh(in)) != ulonghd) {
3679
	  setfregalt (w.answhere, frg);
3680
	  w.ashwhere = ashof (sh (in));
3681
	  code_here (in, sp, w);
3682
	  /* evaluate fix pt arguement into float pt reg f */
3683
	}
3684
	else {			/* bytes and halfs must go through fixpt
3685
				   regs */
3686
	  r = reg_operand (in, sp);
3687
	  cop_ins (i_mtc1, r, f << 1);
3688
	}
3689
 
3690
	rrfp_ins ((name (sh (e)) != shrealhd) ? i_cvt_d_w : i_cvt_s_w,
3691
	    f << 1, f << 1);
3692
	if (name (sh (e)) != shrealhd) {
3693
	  frg.dble = 1;
3694
	}
3695
 
3696
	if( name(sh(in))==ulonghd) {
3697
	     int tmp = getreg(sp.fixed);
3698
	     int constf = getfreg(guardfreg(f,sp).flt);
3699
	     rri_ins(i_and, tmp,r, 0x80000000);
3700
	     cop_ins (i_mtc1, tmp, constf << 1);
3701
	     rrfp_ins ((frg.dble) ? i_cvt_d_w : i_cvt_s_w,
3702
	     		constf << 1, constf << 1);
3703
	     rrrfp_ins((frg.dble) ? i_sub_d: i_sub_s, f<<1, f<<1, constf<<1);
3704
	     rrrfp_ins((frg.dble) ? i_sub_d: i_sub_s, f<<1, f<<1, constf<<1);
3705
	}
3706
	setfregalt (aa, frg);
3707
	move (aa, dest, sp, 1);
3708
	mka.regmove = (frg.dble) ? -(f + 32) : (f + 32);
3709
	return mka;
3710
      }
3711
    case chfl_tag:
3712
      {
3713
	int   to = name (sh (e));
3714
	int   from = name (sh (son (e)));
3715
	bool dto = (to != shrealhd) ? 1 : 0;
3716
	bool dfrom = (from != shrealhd) ? 1 : 0;
3717
	if (dto == dfrom) {	/* no change in representation */
3718
	  return make_code (son (e), sp, dest, exitlab);
3719
	}
3720
	else {
3721
	  freg frg;
3722
	  ans aa;
3723
	  where w;
3724
	  if (dest.answhere.discrim == infreg) {
3725
	    frg = fregalt (dest.answhere);
3726
	  }
3727
	  else {
3728
	    frg.fr = getfreg (sp.flt);
3729
	  }
3730
	  frg.dble = dfrom;
3731
	  setfregalt (aa, frg);
3732
	  w.answhere = aa;
3733
	  w.ashwhere = ashof (sh (son (e)));
3734
	  code_here (son (e), sp, w);
3735
	  if (!optop(e) && !dto) setnoreorder();
3736
	  rrfp_ins ((dfrom) ? i_cvt_s_d : i_cvt_d_s, frg.fr << 1, frg.fr << 1);
3737
	  frg.dble = dto;
3738
	  setfregalt (aa, frg);
3739
	  move (aa, dest, sp, 1);
3740
	  mka.regmove = (frg.dble) ? -(frg.fr + 32) : (frg.fr + 32);
3741
	  if (!optop(e) && !dto) {
3742
		setreorder();
3743
		checknan(e, sp);
3744
	  }
3745
	  return mka;
3746
	}
3747
      }
3748
 
3749
    case and_tag:
3750
      {
3751
	exp r = son (e);
3752
	exp l = bro (son (e));
3753
	ans aa;
3754
	space nsp;
3755
	where d1;
3756
	if (last (l) && name (l) == val_tag && (no (l) == 255 || no (l) == 0xffff)
3757
	    && ((name (r) == name_tag && regofval (r) == 100)
3758
	      || (name (r) == cont_tag &&
3759
		(name (son (r)) != name_tag
3760
		  || regofval (son (r)) > 0
3761
		)
3762
	      )
3763
	    )
3764
	    && (aa = iskept (r), (aa.discrim == inreg && regalt (aa) == 0))
3765
	  ) {			/* can use load short instructions */
3766
	  where w;
3767
	  int   dsize = dest.ashwhere.ashsize;
3768
	  int   asize = (no (l) == 255) ? 8 : 16;
3769
	  w = locate (r, sp, sh (r), 0);
3770
	  if (w.answhere.discrim == notinreg
3771
	      && dest.answhere.discrim == notinreg && no (l) == 0xffff) {
3772
	    instore isw;
3773
	    instore isd;
3774
	    isw = insalt (w.answhere);
3775
	    isd = insalt (dest.answhere);
3776
	    if (!isw.adval && isd.adval && isw.b.base == isd.b.base &&
3777
		isd.b.offset == isw.b.offset) {
3778
	      if (dsize > 16) {
3779
		if (!BIGEND) isd.b.offset += 2;
3780
		/* just clear out top bits */
3781
		ls_ins (i_sh, 0, isd.b);
3782
	      }
3783
	      return mka;
3784
	    }			/* else drop through to load short case */
3785
	  }
3786
	  if (!BIGEND) {
3787
	  	nsp = guard(w,sp);
3788
	  	setregalt(aa,getreg(nsp.fixed));
3789
	  	d1.answhere = aa;
3790
	  	d1.ashwhere.ashsize = d1.ashwhere.ashalign = asize;
3791
	  	move(w.answhere, d1, nsp, 0);
3792
	  	mka.regmove
3793
	   	 = move (aa, dest, guard(d1,nsp), 0 /* unsigned */ );
3794
 
3795
            	return mka;
3796
	  }
3797
	}
3798
	mka.regmove = comm_op (e, sp, dest, i_and);
3799
	return mka;
3800
      }
3801
    case or_tag:
3802
      {
3803
	mka.regmove = comm_op (e, sp, dest, i_or);
3804
	return mka;
3805
      }
3806
 
3807
    case xor_tag:
3808
      {
3809
	mka.regmove = comm_op (e, sp, dest, i_xor);
3810
	return mka;
3811
      }
3812
 
3813
    case not_tag:
3814
      {
3815
	if (name(son(e)) == or_tag) {
3816
		mka.regmove = comm_op(son(e), sp, dest, i_nor);
3817
	}
3818
	else {
3819
		mka.regmove = monop (e, sp, dest, i_not);
3820
	}
3821
	return mka;
3822
      }
3823
 
3824
 
3825
    case offset_pad_tag: {
3826
	int r, v;
3827
	ans aa;
3828
        if (al2(sh(son(e))) >= al2(sh(e))) {
3829
	    if (al2(sh(e)) != 1 || al2(sh(son(e))) == 1) {
3830
		/* is already aligned correctly, whether as bit or byte-offset*/
3831
		e = son(e); goto tailrecurse;
3832
	    }
3833
  	    r = regfrmdest(&dest, sp);
3834
	    v = reg_operand(son(e), sp);
3835
	    rri_ins(i_sll, r, v, 3);
3836
	}
3837
	else {
3838
		int al = (al2(sh(son(e)))==1)?al2(sh(e)):(al2(sh(e))/8);
3839
		r = regfrmdest(&dest, sp);
3840
		v = reg_operand(son(e), sp);
3841
		rri_ins(i_addu, r, v, al-1);
3842
		rri_ins(i_and, r, r, -al);
3843
		if (al2(sh(son(e)))==1) { /* operand is bit-offset,
3844
						byte-offset required */
3845
			rri_ins(i_sra, r, r, 3);
3846
		}
3847
	}
3848
	setregalt(aa,r);
3849
	mka.regmove = move(aa, dest, guardreg(r,sp), 0);
3850
        return mka;
3851
    }
3852
 
3853
   case locptr_tag: {
3854
    	int pr = reg_operand(son(e), sp);
3855
    	int ansr = regfrmdest(&dest, sp);
3856
    	baseoff b;
3857
    	ans aa;
3858
    	b.base = pr; b.offset = -12;
3859
    	ls_ins(i_lw, ansr, b);
3860
    	setregalt(aa,ansr);
3861
    	mka.regmove = move(aa, dest, guardreg(ansr,sp), 0);
3862
    	return mka;
3863
    }
3864
 
3865
    case cont_tag:
3866
    case name_tag:
3867
    case field_tag:
3868
    case reff_tag:
3869
    case addptr_tag:
3870
    case subptr_tag:
3871
    case contvol_tag:
3872
      {
3873
	where w;
3874
	bool sgned;
3875
	ash desper;
3876
 
3877
	int   dr = (dest.answhere.discrim == inreg) ? dest.answhere.val.regans : 0;
3878
	desper = ashof (sh (e));
3879
 
3880
	if (name (e) == contvol_tag) {
3881
	  clear_all ();
3882
	  setvolatile ();
3883
	}
3884
	w = locate (e, sp, sh (e), dr);
3885
	/* 'address of arguement */
3886
	sgned = ((w.ashwhere.ashsize >= 32) || is_signed(sh (e)) )? 1 : 0;
3887
	mka.regmove = move (w.answhere, dest, (guard (w, sp)), sgned);
3888
	if (name (e) == contvol_tag) {
3889
	  mka.regmove = NOREG;
3890
	  setnovolatile ();
3891
	}
3892
	return mka;
3893
      }				/* end cont */
3894
 
3895
 
3896
    case real_tag: {
3897
	int dble = shape_size(sh(e))>32;
3898
	r2l x;
3899
	int i;
3900
	ans aa;
3901
        instore isa;
3902
	int n = (nca<16)?nca:16;
3903
	x = real2longs_IEEE(&flptnos[no (e)], dble);
3904
	for(i=0; i< n; i++) {
3905
	    rcache *r = &rca[i];
3906
	    if (r->dble == dble && r->r.i1 == x.i1 && r-> r.i2 == x.i2)
3907
		{isa = r->ad; goto found;}
3908
	}
3909
	isa = evaluated(e, 0,(dec*)0);
3910
        rca[nca & 15].dble = dble; rca[nca & 15].r = x; rca[nca & 15].ad = isa;
3911
	nca++;
3912
	settext();
3913
  found:setinsalt (aa, isa);
3914
	mka.regmove = move (aa, dest, sp, 0);
3915
	return mka;
3916
    }
3917
    case string_tag:
3918
      {
3919
	instore isa;
3920
	ans aa;
3921
	bool sgned = ((ashof (sh (e)).ashsize >= 32) || is_signed(sh (e)))? 1 : 0;
3922
	isa = evaluated (e, 0, (dec*)0);
3923
	/* place constant in appropriate data segment */
3924
	settext ();
3925
	setinsalt (aa, isa);
3926
	mka.regmove = move (aa, dest, sp, sgned);
3927
	return mka;
3928
      }				/* end eval */
3929
 
3930
    case val_tag:
3931
      {
3932
	if( shape_size(sh(e))>32) {
3933
		flt64 temp;
3934
		int ov;
3935
		int r = getreg(sp.fixed);
3936
		space nsp;
3937
		baseoff bc;
3938
		ans aa;
3939
		if (dest.answhere.discrim!=notinreg) return mka;
3940
		if (isbigval(e)) {
3941
			temp = flt_to_f64(no(e), 0, &ov);
3942
		}
3943
		else {
3944
			temp.big = (is_signed(sh(e)) && no(e)<0)?-1:0;
3945
			temp.small = no(e);
3946
		}
3947
		nsp = guardreg(r, sp);
3948
		bc.base =0;
3949
		bc.offset = temp.small;
3950
		ls_ins(i_li, r, bc);
3951
		setregalt(aa,r);
3952
		dest.ashwhere.ashsize = 32;
3953
		dest.ashwhere.ashalign = 32;
3954
		move(aa,dest,nsp,1);
3955
		bc.offset = temp.big;
3956
		ls_ins(i_li, r, bc);
3957
		dest.answhere.val.instoreans.b.offset+=4;
3958
		move(aa,dest,nsp,1);
3959
		return mka;
3960
	}
3961
	if (no (e) == 0) {
3962
	  goto null_tag_case;
3963
	}
3964
	else {
3965
	  ash a;
3966
	  a = ashof (sh (e));
3967
	  if (a.ashsize == 32 || !is_signed(sh (e))) {
3968
	    constval = no (e);
3969
	  }
3970
	  else
3971
	    if (a.ashsize == 8) {
3972
	      constval = no (e) & 255;
3973
	      constval -= (constval & 128) << 1;
3974
	    }
3975
	    else {
3976
	      constval = no (e) & 65535;
3977
	      constval -= (constval & 32768) << 1;
3978
	    }
3979
	  goto moveconst;
3980
	}
3981
      }
3982
 
3983
    case top_tag: {
3984
	return mka;
3985
      }
3986
 
3987
    case dump_tag: {
3988
    	long fxd = no(e);
3989
    	long fld = no(pt(e));
3990
    	long old_fixdone = fixdone;
3991
    	long old_fltdone = fltdone;
3992
    	long old_result_label = result_label;
3993
    	exp l;
3994
    	result_label =0;
3995
    	dump_sregs(fxd, fld);
3996
    	if ((fxd &(1<<31))) sp.fixed &= ~(1<<31); /*release link reg */
3997
    	for(l=son(crt_proc); name(l)==ident_tag && isparam(l); ){
3998
    		/* move any pars still in registers which go into dump regs */
3999
    		int sr = props(son(l));
4000
    		int tr = no(l);
4001
    		if ((props(l) & inanyreg)!=0 && (tr !=sr) && sr != 0) {
4002
    		    if ((props(l) & infreg_bits)!=0 &&
4003
    		         (fld &(3<<(sr<<1))) !=0 ) {
4004
    		       if (name(sh(son(l))) != shrealhd) {
4005
    		       	  rrfp_ins(i_mov_d, sr<<1, tr<<1);
4006
    		       }
4007
    		       else {
4008
   		       	  rrfp_ins(i_mov_s, sr<<1, tr<<1);
4009
    		       }
4010
    		       sp.flt &= ~(1<<tr); /* release fpar reg */
4011
    		       no(l) = sr; props(son(l)) = tr;
4012
    		    }
4013
    		    else
4014
    		    if ((fxd & (1<<sr)) !=0 ) {
4015
    		    	mon_ins(i_move, sr, tr);
4016
    		    	sp.fixed &= ~(1<<tr); /* release par reg */
4017
    		    	no(l)=sr; props(son(l)) = tr;
4018
    		    }
4019
    		 }
4020
    		 l = bro(son(l));
4021
    		 if (name(l)==dump_tag) l = son(l);
4022
        }
4023
        code_here(son(e), sp, dest);
4024
    	for(l=son(crt_proc); name(l)==ident_tag && isparam(l); ){
4025
    		/* restore structure of moved pars */
4026
    		int sr = props(son(l));
4027
    		int tr = no(l);
4028
    		if ((props(l) & inanyreg)!=0 && (tr !=sr) && sr != 0) {
4029
    		    if ((props(l) & infreg_bits)!=0 &&
4030
    		         (fld &(3<<(tr<<1))) !=0 ) {
4031
    		       no(l) = sr; props(son(l)) = tr;
4032
    		    }
4033
    		    else
4034
    		    if ((fxd & (1<<tr)) !=0 ) {
4035
    		    	no(l)=sr; props(son(l)) = tr;
4036
    		    }
4037
    		 }
4038
    		 l = bro(son(l));
4039
    		 if (name(l)==dump_tag) l = son(l);
4040
        }
4041
        if (name(sh(e)) != bothd) {
4042
        	restore_sregs(fxd, fld);
4043
        }
4044
        fixdone = old_fixdone;
4045
        fltdone = old_fltdone;
4046
        result_label = old_result_label;
4047
        return mka;
4048
    }
4049
 
4050
    case env_size_tag: {
4051
	exp tg = son(son(e));
4052
	procrec * pr = &procrecs[no(son(tg))];
4053
	constval = (pr->frame_size+pr->callee_size) >> 3;
4054
	goto moveconst;
4055
   }
4056
 
4057
    case proc_tag: case general_proc_tag:
4058
      {				/*
4059
				 set up locals_offset, fixdump, floatdump, frame_size, dumpstart
4060
				 dec stack  ; output frame and mask
4061
				 code here;
4062
				 */
4063
	procrec * pr = & procrecs[no(e)];
4064
	needs * ndpr = & pr->needsproc;
4065
	long pprops = (ndpr->propsneeds);
4066
	bool leaf = (pprops & anyproccall) == 0;
4067
	space tbd;
4068
	space pars;
4069
	long st;
4070
	exp l;
4071
 
4072
	crt_proc = e;
4073
	old_pls = (postl_chain*)0;
4074
 
4075
	frame_size = pr->frame_size;
4076
	locals_offset = pr->locals_offset;
4077
	max_args = pr->max_args;
4078
	fixdump = pr->fixdump;
4079
	floatdump = pr->floatdump;
4080
	dumpstart = pr->dumpstart;
4081
	fldumpstart = pr->fldumpstart;
4082
	callee_size = pr->callee_size;
4083
 
4084
        setframe_flags(e, leaf);
4085
 
4086
	st = (frame_size+callee_size) >> 3;
4087
 
4088
	fixdone = fltdone = 0;	/* no s-regs have been dumped yet */
4089
 
4090
 
4091
	tbd.fixed = fixdump;
4092
	tbd.flt = floatdump;
4093
 
4094
	pars.fixed = (leaf)?0:(1<<31);
4095
	pars.flt = 0;
4096
 
4097
	for (l = son(e);
4098
	     name(l) == ident_tag && isparam(l)
4099
		&& name(son(l))	!= formal_callee_tag;
4100
             l = bro(son(l))) {
4101
		if ((props(l) & infreg_bits)!= 0) {
4102
			int n = props(son(l));
4103
			if (n != no(l) && n != 0) {
4104
				pars.flt |= (3<<(no(l)<<1));
4105
			}
4106
		}
4107
		else
4108
		if ((props(l) & inreg_bits)!=0) {
4109
			int n = props(son(l));
4110
			if (n != no(l) && n != 0) {
4111
				pars.fixed |= (1<<no(l));
4112
			}
4113
		}
4114
	}
4115
 
4116
	dump_opt(e, &tbd, &pars);
4117
 
4118
	if (PIC_code) {
4119
	    setnoreorder();
4120
	    out_cpload(current_symno, 25);
4121
	    if (as_file) {
4122
	    	fprintf(as_file, "\t.cpload\t$25\n");
4123
	    }
4124
	    setreorder();
4125
	}
4126
 
4127
 
4128
	if (name(e)==general_proc_tag) {
4129
	  if (Has_vcallees) {
4130
	  	baseoff b;
4131
	  	b.base = 30;
4132
	  	b.offset = -16;
4133
	  	ls_ins(i_sw, local_reg, b); /* old l-reg in -16(30) */
4134
		mon_ins(i_move, local_reg, 29);
4135
		/* if(!leaf) */ {
4136
			b.offset = -12; /* new l_reg in -12(30); */
4137
			ls_ins(i_sw, local_reg, b);
4138
		}
4139
	  }
4140
	  else
4141
	  if (Has_fp && name(e)==general_proc_tag) {
4142
	 	rri_ins(i_addu, 30, 29, callee_size>>3);
4143
	   }
4144
	  if (frame_size !=0) {
4145
		rri_ins (i_subu, 29, 29, frame_size>>3);
4146
	  }
4147
	}
4148
	else {
4149
	  if (st !=0) {
4150
		rri_ins (i_subu, 29, 29, st);
4151
	  }
4152
	  if (Has_fp) {
4153
		baseoff b;
4154
		b.base = 29;
4155
		b.offset = st-4;
4156
		ls_ins(i_sw, 30, b);
4157
		rri_ins(i_addu, 30, 29, st);
4158
	  }
4159
        }
4160
 
4161
	if (Has_tos ) {
4162
		baseoff b;
4163
		b.base = 30;
4164
		b.offset = -8;
4165
		ls_ins(i_sw, 29, b);
4166
	}
4167
 
4168
        diagPIClab = 0;
4169
	if (PIC_code && !leaf) {
4170
		dump_gp();
4171
	        if (diagnose && frame_size != 0) {
4172
			diagPIClab = new_label();
4173
		}
4174
	}
4175
 
4176
	allocaerr_lab = 0;
4177
	if (proc_has_checkstack(e)) {
4178
		baseoff b;
4179
		exp stl = find_named_tg("__TDFstacklim",
4180
				f_pointer(f_alignment(f_proc)));
4181
		setvar(stl);
4182
		b = boff(stl);
4183
		stackerr_lab = new_label();
4184
		ls_ins(i_lw, 2, b);
4185
		condrr_ins(i_bgt, 2, 29, stackerr_lab);
4186
	}
4187
	else stackerr_lab = 0;
4188
 
4189
	setframe (st);
4190
	/* I'm not sure that this is the right order for these -
4191
	   diagnostics ? */
4192
 
4193
 
4194
	if (fixdump != 0) {
4195
	  setmask (fixdump, dumpstart - st - 4);
4196
	}
4197
	if (floatdump != 0) {
4198
	  setfmask (floatdump, fldumpstart - st - 4 );
4199
	}
4200
 
4201
 
4202
	if ((pprops & realresult_bit) != 0) {
4203
	      /* proc has real result */
4204
	      freg frg;
4205
	      frg.fr = 0;
4206
	      frg.dble = (pprops & longrealresult_bit) ? 1 : 0;
4207
	      setfregalt (procans, frg);
4208
	}
4209
	else
4210
	if ((pprops & has_result_bit) != 0) {
4211
		/* proc has fixed pt result */
4212
		setregalt (procans, 2);
4213
	}
4214
	else {		/* proc has no result */
4215
		setregalt (procans, 0);
4216
	}
4217
 
4218
	rscope_level = 0;
4219
	result_label = 0;
4220
 
4221
        aritherr_lab = 0;
4222
 
4223
	code_here (son(e), guardreg(31,sp), nowhere);
4224
	/* evaluate body of proc */
4225
        if (stackerr_lab != 0 || allocaerr_lab != 0) {
4226
	   if (stackerr_lab != 0) {
4227
		set_label(stackerr_lab);
4228
		rri_ins (i_addu, 29, 29, frame_size>>3);
4229
	   }
4230
	   if (allocaerr_lab != 0) { set_label(allocaerr_lab); }
4231
	   do_exception(MIPS_SIGUSR1);
4232
	}
4233
	if (aritherr_lab != 0) {
4234
		set_label(aritherr_lab);
4235
		do_exception(MIPS_SIGFPE);
4236
	}
4237
	if (diagPIClab != 0) {
4238
		set_label(diagPIClab);
4239
		uncond_ins (i_j, 31);
4240
	}
4241
 
4242
	return mka;
4243
 
4244
      }				/* end proc */
4245
 
4246
    case alloca_tag: {
4247
    	exp s = son(e);
4248
    	int r = regfrmdest(&dest, sp);
4249
    	ans aa;
4250
	if (checkalloc(e)) {
4251
	    int tmp = getreg(guardreg(r,sp).fixed);
4252
	    exp stl = find_named_tg("__TDFstacklim",
4253
			f_pointer(f_alignment(f_proc)) );
4254
	    baseoff b;
4255
	    setvar(stl);
4256
	    if (name(s)==val_tag) {
4257
		    rri_ins(i_subu, r, 29, (no(s)+7 )&~7);
4258
	    }
4259
	    else {
4260
		    int rr = reg_operand(s, sp);
4261
		    rri_ins(i_addu, tmp, rr, 7 );
4262
		    rri_ins(i_and, tmp,tmp, ~7);
4263
		    rrr_ins(i_subu, r, 29, tmp);
4264
	    }
4265
	    b = boff(stl);
4266
	    if (allocaerr_lab == 0) allocaerr_lab = new_label();
4267
	    ls_ins(i_lw, tmp, b);
4268
	    condrr_ins(i_bgt, tmp, r, allocaerr_lab);
4269
	    rri_ins(i_addu, 29, r, 0);
4270
	}
4271
	else {
4272
	    if (name(s)==val_tag) {
4273
		    rri_ins(i_subu, 29, 29, (no(s)+7 )&~7);
4274
	    }
4275
	    else {  int tmp = getreg(sp.fixed);
4276
		    int rr = reg_operand(s, sp);
4277
		    rri_ins(i_addu, tmp, rr, 7 );
4278
		    rri_ins(i_and, tmp,tmp, ~7);
4279
		    rrr_ins(i_subu, 29, 29, tmp);
4280
	    }
4281
	}
4282
	reset_tos();
4283
	rri_ins(i_addu, r, 29, (max_args>>3) );
4284
    	setregalt(aa, r);
4285
    	mka.regmove = move(aa, dest, sp, 1);
4286
    	return mka;
4287
    }
4288
 
4289
    case last_local_tag: {
4290
    	int r = regfrmdest(&dest, sp);
4291
    	ans aa;
4292
    	rri_ins(i_addu, r, 29, max_args>>3);
4293
    	setregalt(aa, r);
4294
    	mka.regmove = move(aa, dest, sp, 1);
4295
    	return mka;
4296
    }
4297
 
4298
    case local_free_tag: {
4299
	exp p = son(e);
4300
    	int r = reg_operand(p, sp);
4301
	exp off = bro(p);
4302
	if (name(off)==val_tag) {
4303
		rri_ins(i_addu, r, r,(no(off)+7 )&~7);
4304
	}
4305
	else {
4306
		int tmp = reg_operand(off, guardreg(r, sp));
4307
		rri_ins(i_addu, tmp, tmp, 7 );
4308
		rri_ins(i_and, tmp,tmp, ~7);
4309
		rrr_ins(i_addu, r, r, tmp);
4310
	}
4311
 
4312
    	if (Has_fp) {
4313
          rri_ins(i_subu, 29, r, max_args>>3);
4314
          reset_tos();
4315
        }
4316
    	return mka;
4317
    }
4318
 
4319
    case local_free_all_tag: {
4320
    	if (Has_fp) {
4321
          rri_ins(i_subu, 29, 30 , (frame_size+callee_size)>>3);
4322
          reset_tos();
4323
        }
4324
    	return mka;
4325
    }
4326
 
4327
    case current_env_tag: {
4328
    	int r = regfrmdest(&dest, sp);
4329
    	ans aa;
4330
    	if (Has_fp) {
4331
    		mon_ins(i_move, r, 30);
4332
    	}
4333
    	else {
4334
    		rri_ins(i_addu, r, 29, (frame_size+callee_size)>>3);
4335
    	}
4336
    	setregalt(aa, r);
4337
    	mka.regmove = move(aa, dest, sp, 1);
4338
    	return mka;
4339
    }
4340
 
4341
    case env_offset_tag: case general_env_offset_tag:{
4342
    	constval = frame_offset(son(e));
4343
    	goto moveconst;
4344
    }
4345
 
4346
    case null_tag:
4347
  null_tag_case:
4348
      {
4349
	ans aa;
4350
	setregalt (aa, 0);
4351
	mka.regmove = move (aa, dest, sp, 1);
4352
	return mka;
4353
      }
4354
 
4355
    case round_tag:
4356
   /* case trunc_tag: */
4357
      {
4358
	int   r = (dest.answhere.discrim == inreg) ? regalt (dest.answhere)
4359
	:     getreg (sp.fixed);
4360
	int   sfr = freg_operand (son (e), sp);
4361
	int   dfr = getfreg (guardfreg (sfr, sp).flt);
4362
	ans aa;
4363
	int   s = shape_size(sh(son(e)));
4364
	int mr = (round_number(e)== f_to_nearest)? 3:
4365
			(round_number(e)== f_toward_zero)? 2:
4366
			(round_number(e)== f_toward_larger)? 1:
4367
			(round_number(e)== f_toward_smaller)? 0:3;
4368
	int r1;
4369
	if (r==0) r = getreg(sp.fixed);
4370
	sp = guardreg(r, sp);
4371
	r1 = getreg(sp.fixed);
4372
 	if (!optop(e)) setnoreorder();
4373
 
4374
	cop_ins(i_cfc1, r, 31);
4375
	rrr_ins(i_or, 0, 0, 0); /* nop */
4376
	rri_ins(i_or, r1, r , 3);
4377
	rri_ins(i_xor, r1, r1, mr);
4378
	cop_ins(i_ctc1, r1, 31);
4379
	rrr_ins(i_or, 0, 0, 0); /* nop */
4380
	rrfp_ins((s==32)?i_cvt_w_s:i_cvt_w_d, dfr<<1, sfr<<1);
4381
 
4382
	if (!optop(e)) {
4383
		setreorder();
4384
		checknan(e, guardreg(r, sp));
4385
	}
4386
	cop_ins(i_ctc1, r, 31);
4387
	cop_ins (i_mfc1, r, dfr << 1);
4388
 
4389
 
4390
/*  cfc1    r,$31
4391
  cfc1    r,$31
4392
  ori     r1,dfr,0x3
4393
  xori    r1,r1, to_n = 3, to_z = 2, to+i = 1, to-i = 0
4394
  ctc1    r1,$31
4395
  srl     r0,r0,0
4396
  cvt.w.s $f6,$f0
4397
	check
4398
  ctc1    r,$31
4399
	expansion of i_round_w_s etc
4400
*/
4401
 
4402
	setregalt (aa, r);
4403
	mka.regmove = move (aa, dest, sp, 1);
4404
	return mka;
4405
      }
4406
 
4407
 
4408
    case int_to_bitf_tag:
4409
      {
4410
	int   r;
4411
	where w;
4412
	ash a;
4413
	ash ai;
4414
	ans aa;
4415
	space nsp;
4416
	a = ashof (sh (e));
4417
	ai = ashof (sh (son (e)));
4418
	r = regfrmdest(&dest, sp);
4419
 
4420
	setregalt (w.answhere, r);
4421
	w.ashwhere = a;
4422
	code_here (son (e), sp, w);
4423
	if (a.ashsize != ai.ashsize) {
4424
	  rri_ins (i_and, r, r, (1 << a.ashsize) - 1);
4425
	}
4426
	nsp = guardreg (r, sp);
4427
	setregalt (aa, r);
4428
	move (aa, dest, nsp, 0);
4429
	return mka;
4430
      }
4431
 
4432
 
4433
    case bitf_to_int_tag:
4434
      {
4435
	ash a;
4436
	int   r;
4437
	where w;
4438
	a = ashof (sh (son (e)));
4439
	r = regfrmdest(&dest, sp);
4440
 
4441
	setregalt (w.answhere, r);
4442
	w.ashwhere = a;
4443
	code_here (son (e), sp, w);
4444
	if (a.ashsize != 32) {
4445
	  if ( is_signed(sh (e)) ) {
4446
	    rri_ins (i_sll, r, r, 32 - a.ashsize);
4447
	    rri_ins (i_sra, r, r, 32 - a.ashsize);
4448
	  }
4449
	  else {
4450
	    rri_ins (i_and, r, r, ((1 << a.ashsize) - 1));
4451
	  }
4452
	}
4453
 
4454
	move (w.answhere, dest, guardreg (r, sp), 0);
4455
	keepreg (e, r);
4456
	return mka;
4457
      }
4458
 
4459
 
4460
    case movecont_tag: {
4461
        exp szarg = bro(bro(son(e)));
4462
    	int dr, sr, szr, mr;
4463
 	int lout = new_label();
4464
 	space nsp;
4465
 	int bytemove;
4466
 	where w;
4467
 
4468
 	sr = getreg(sp.fixed);
4469
 	setregalt(w.answhere, sr);
4470
 	w.ashwhere = ashof(sh(son(e)));
4471
 	IGNORE make_code(son(e), sp, w , 0);
4472
 	nsp = guardreg(sr, sp);
4473
 	dr = getreg(nsp.fixed);
4474
 	setregalt(w.answhere, dr);
4475
 	IGNORE make_code(bro(son(e)), nsp, w, 0);
4476
 	nsp = guardreg(dr, nsp);
4477
 	w.ashwhere = ashof(sh(bro(bro(son(e)))));
4478
 	szr = getreg(nsp.fixed);
4479
 	setregalt(w.answhere, szr);
4480
 	IGNORE make_code(szarg, nsp, w, 0);
4481
 	nsp = guardreg(szr, nsp);
4482
 	mr = getreg(nsp.fixed);
4483
        bytemove = (al2(sh(szarg)) <= 8);
4484
 
4485
 
4486
	if(name(szarg) != val_tag || no(szarg) == 0) {
4487
		condrr_ins(i_beq, szr, 0, lout);
4488
	}
4489
	if (isnooverlap(e)) {
4490
		move_dlts(dr,sr,szr,mr, bytemove);
4491
	}
4492
	else {
4493
		int gtlab = new_label();
4494
		condrr_ins(i_bgt, dr, sr,gtlab);
4495
		move_dlts(dr,sr,szr, mr, bytemove);
4496
		uncond_ins(i_b, lout);
4497
		set_label(gtlab);
4498
		move_dgts(dr,sr,szr, mr, bytemove);
4499
	}
4500
 	set_label(lout);
4501
 	return mka;
4502
   }
4503
    case set_stack_limit_tag: {
4504
	baseoff b ;
4505
	int r = reg_operand(son(e), sp);
4506
	exp stl = find_named_tg("__TDFstacklim",
4507
				f_pointer(f_alignment(f_proc)));
4508
	setvar(stl);
4509
	b = boff(stl);
4510
	ls_ins(i_sw, r, b);
4511
	return mka;
4512
    }
4513
    case give_stack_limit_tag: {
4514
    	baseoff b;
4515
    	ans aa;
4516
	int r = regfrmdest(&dest, sp);
4517
	exp stl = find_named_tg("__TDFstacklim",
4518
				f_pointer(f_alignment(f_proc)));
4519
	setvar(stl);
4520
	b = boff(stl);
4521
	ls_ins(i_lw, r, b);
4522
	setregalt (aa, r);
4523
        move (aa, dest, guardreg (r, sp), 1);
4524
	return mka;
4525
    }
4526
    case trap_tag: {
4527
	if (no(e) == f_overflow) {
4528
		do_exception(MIPS_SIGFPE);
4529
	}
4530
	else
4531
	if (no(e) == f_nil_access) {
4532
		do_exception(MIPS_SIGSEGV);
4533
	}
4534
	else do_exception(MIPS_SIGUSR1);
4535
 
4536
	return mka;
4537
    }
4538
 
4539
 
4540
 
4541
    default:
4542
      failer ("not done yet");
4543
  }				/* end outer switch */
4544
 
4545
 
4546
 
4547
moveconst:
4548
  {
4549
    int   r = regfrmdest(&dest, sp);
4550
    baseoff b;
4551
    ans aa;
4552
 
4553
    if (r != 0) {		/* somewhere! */
4554
      b.base = 0;
4555
      b.offset = constval;
4556
      ls_ins (i_li, r, b);
4557
      setregalt (aa, r);
4558
      move (aa, dest, guardreg (r, sp), 1);
4559
    }
4560
    mka.regmove = r;
4561
    return mka;
4562
  }
4563
 
4564
}				/* end make_code */