Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/* 	$Id: coder.c,v 1.2 1998/02/04 10:43:30 release Exp $	 */
32
 
33
#ifndef lint
34
static char vcid[] = "$Id: coder.c,v 1.2 1998/02/04 10:43:30 release Exp $";
35
#endif /* lint */
36
/*
37
$Log: coder.c,v $
38
 * Revision 1.2  1998/02/04  10:43:30  release
39
 * Changes during testing.
40
 *
41
 * Revision 1.1.1.1  1998/01/17  15:55:58  release
42
 * First version to be checked into rolling release.
43
 *
44
 * Revision 1.46  1997/09/05  12:22:14  john
45
 * Changed case behaviour
46
 *
47
 * Revision 1.45  1996/11/27  17:56:27  john
48
 * Changed case behaviour
49
 *
50
 * Revision 1.44  1996/03/18  17:00:17  john
51
 * Fix to rem operation
52
 *
53
 * Revision 1.43  1996/03/15  10:29:39  john
54
 * Fix to char & short ops
55
 *
56
 * Revision 1.42  1996/02/29  17:35:49  john
57
 * Fix to remainder op
58
 *
59
 * Revision 1.41  1996/02/19  09:25:05  john
60
 * change to register
61
 *
62
 * Revision 1.40  1996/02/15  09:49:16  john
63
 * Some changes to general proc handling
64
 *
65
 * Revision 1.39  1996/01/23  16:48:40  john
66
 * Fixed vararg handling for general procs
67
 *
68
 * Revision 1.38  1996/01/17  09:30:14  john
69
 * Various fixes
70
 *
71
 * Revision 1.37  1995/12/04  09:12:17  john
72
 * Fix to varparams & alloca
73
 *
74
 * Revision 1.36  1995/11/14  15:20:53  john
75
 * Fixes to general procs
76
 *
77
 * Revision 1.35  1995/11/13  12:10:15  john
78
 * Fixes to arithmetic
79
 *
80
 * Revision 1.34  1995/10/27  16:17:00  john
81
 * Change to general procs
82
 *
83
 * Revision 1.33  1995/10/27  12:07:40  john
84
 * Fix to same_callees
85
 *
86
 * Revision 1.32  1995/10/24  09:27:53  john
87
 * Fixes to large numbers
88
 *
89
 * Revision 1.31  1995/10/19  16:36:13  john
90
 * Fix to error treatments
91
 *
92
 * Revision 1.30  1995/10/18  09:28:40  john
93
 * Fix to round_tag
94
 *
95
 * Revision 1.29  1995/09/29  15:27:04  john
96
 * Some changes for vcallers
97
 *
98
 * Revision 1.28  1995/09/22  16:02:04  john
99
 * Minor fix
100
 *
101
 * Revision 1.27  1995/09/21  15:40:43  john
102
 * Various improvements to error handling
103
 *
104
 * Revision 1.26  1995/09/15  16:21:15  john
105
 * New exception handling
106
 *
107
 * Revision 1.25  1995/09/13  15:45:29  john
108
 * Cleared out some old code
109
 *
110
 * Revision 1.24  1995/09/13  08:22:10  john
111
 * Addition for exception handling
112
 *
113
 * Revision 1.23  1995/09/07  12:27:46  john
114
 * Changes to general procs
115
 *
116
 * Revision 1.22  1995/09/04  16:13:00  john
117
 * Fix to general procs
118
 *
119
 * Revision 1.21  1995/09/01  09:08:56  john
120
 * Fix to mult_tag
121
 *
122
 * Revision 1.20  1995/08/31  15:41:46  john
123
 * Added fmax_tag & fixed some limits bugs
124
 *
125
 * Revision 1.19  1995/08/30  16:13:14  john
126
 * Various fixes to error treatments
127
 *
128
 * Revision 1.18  1995/08/23  16:05:06  john
129
 * Corrected comment
130
 *
131
 * Revision 1.17  1995/08/21  13:37:28  john
132
 * Changed handling of caller_tag
133
 *
134
 * Revision 1.16  1995/08/21  10:44:11  john
135
 * Added trap_tag
136
 *
137
 * Revision 1.15  1995/08/21  08:43:28  john
138
 * Changed include files
139
 *
140
 * Revision 1.14  1995/08/04  15:49:40  john
141
 * Fixed parameters of tail call and added new error jumps
142
 *
143
 * Revision 1.13  1995/07/27  09:24:39  john
144
 * Changed general procs, repositioned $fp
145
 *
146
 * Revision 1.12  1995/07/04  09:07:43  john
147
 * Fixed tail call
148
 *
149
 * Revision 1.11  1995/06/30  07:58:34  john
150
 * Fixed bug in tail_call, callee parameters were being passed the wrong
151
 * way round.
152
 *
153
 * Revision 1.10  1995/06/28  10:19:37  john
154
 * Fix to shr_tag
155
 *
156
 * Revision 1.9  1995/06/21  14:24:51  john
157
 * Reformatting
158
 *
159
 * Revision 1.8  1995/06/15  09:43:44  john
160
 * Added code for stack error handling
161
 *
162
 * Revision 1.7  1995/06/15  08:34:41  john
163
 * Some reformatting and additions for new error treatment
164
 *
165
 * Revision 1.6  1995/05/25  15:33:02  john
166
 * Cosmetic changes
167
 *
168
 * Revision 1.5  1995/05/23  10:53:53  john
169
 * Reformatting + additions for spec 3.1
170
 *
171
 * Revision 1.4  1995/04/10  14:14:50  john
172
 * Added new division code.  Not fully tested in this version
173
 *
174
 * Revision 1.3  1995/03/29  14:01:08  john
175
 * Changes to keep tcheck happy
176
 *
177
 * Revision 1.2  1995/03/29  10:29:33  john
178
 * Added code to detect and handle IEEE denormals
179
 *
180
 * Revision 1.1.1.1  1995/03/23  10:39:03  john
181
 * Entered into CVS
182
 *
183
 * Revision 1.51  1995/03/23  10:00:47  john
184
 * Various changes for AVS test suite
185
 *
186
 * Revision 1.50  1995/03/16  09:43:41  john
187
 * Removed bitfield operations, fixed local_free_tag and changed
188
 * chvar_tag
189
 *
190
 * Revision 1.49  1995/03/09  14:08:55  john
191
 * Introduced code to use the scheduler, and fixed a bug in test_tag
192
 *
193
 * Revision 1.48  1995/02/09  17:17:29  john
194
 * Fix to rep_tag and local_free_tag
195
 *
196
 * Revision 1.47  1995/02/06  16:45:11  john
197
 * Fix to case_tag
198
 *
199
 * Revision 1.46  1995/01/26  13:30:54  john
200
 * Modified error jump handling, and did some reformating
201
 *
202
 * Revision 1.45  1995/01/23  09:18:45  john
203
 * First attempt at implementing error jumps
204
 *
205
 * Revision 1.44  1995/01/18  11:49:03  john
206
 * Fixed errors in abslike_tag and case_tag, and added overflow check to
207
 * div_tag
208
 *
209
 * Revision 1.43  1995/01/17  10:30:44  john
210
 * Changed implementation of absbool_tag
211
 *
212
 * Revision 1.42  1995/01/10  09:42:23  john
213
 * Minor reformating and removal of dead code.
214
 *
215
*/
216
 
217
/* 
218
   coder.c
219
   This is the principal code producing module
220
*/
221
#include "config.h"
222
#include "coder.h"
223
#include "common_types.h"
224
#include "addresstypes.h"
225
#include "tags.h"
226
#include "expmacs.h"
227
#include "exp.h"
228
#include "exptypes.h"
229
#include "externs.h"
230
#include "maxminmacs.h"
231
#include "shapemacs.h"
232
#include "basicread.h"
233
#include "procrectypes.h"
234
#include "eval.h"
235
#include "move.h"
236
#include "operators.h"
237
#include "pseudo.h"
238
#include "getregs.h"
239
#include "guard.h"
240
#include "locate.h"
241
#include "code_here.h"
242
#include "inst_fmt.h"
243
#include "alpha_ins.h"
244
#include "handle_sregs.h"
245
#include "bitsmacs.h"
246
#include "labels.h"
247
#include "regexps.h"
248
#include "special.h"
249
#include "new_tags.h"
250
#include "syms.h"
251
#include "flags.h"
252
#include "main.h"
253
#include "dump_distr.h"
254
#include "extratags.h"
255
#include "frames.h"
256
#include "reg_defs.h"
257
#include "cross.h"
258
#include "flpttypes.h"
259
#include "flpt.h"
260
#include "f64.h"
261
#include "fail.h"
262
#include "bool.h"
263
#include "regable.h"
264
#include "symdiags.h"
265
#include "f64.h"
266
#include "install_fns.h"
267
#include "outofline.h"
268
#include "diag_fns.h"
269
#include "out_ba.h"
270
#include "float.h"
271
#include "szs_als.h"
272
#include "translate.h"
273
extern  FILE * as_file;
274
int fscopefile;	/* file of current proc */
275
 
276
/*extern void add_odd_bits PROTO_S ((outofline*));*/
277
 
278
ans procans;
279
int rscope_level;
280
int rscope_label;
281
int result_label = 0;
282
int currentnop;
283
long max_args;
284
 
285
baseoff procbase=
286
{
287
  RA,0L
288
};
289
 
290
flt alpha_word_max = {{32768,0,0,0,0,0,0,0},1,0};
291
flt alpha_long_max = {{1,0,0,0,0,0,0,0},1,2};
292
flt alpha_quad_max = {{1,0,0,0,0,0,0,0},1,4};
293
 
294
where nowhere;
295
int stack_top;
296
int paramsdumpstart;
297
int gpdumpstart;
298
int arg_stack_space=0;
299
 
300
static exp crt_proc;
301
 
302
int use_andcomp = 0;
303
int in_general_proc = 0;
304
int in_vcallers_apply = 0;
305
int aritherr_lab = 0;
306
int stackerr_lab = 0;
307
 
308
int testrev[] = {
309
  4,3,2,1,6,5
310
};
311
/*
312
outofline *odd_bits;
313
int doing_odd_bits;
314
*/
315
/* put register number 'Reg' back into the current space. */
316
#define replace_reg(Reg,Space) ((Space) & ~(1<<(Reg)))
317
 
318
#define fix_parameter_size(X,Y) if(Y==32){\
319
operate_fmt_immediate(i_addl,X,0,X);\
320
}
321
 
322
#define error_treatment_is_trap(e) ((errhandle(e)&3)==3)
323
 
324
/*
325
  Return TRUE if the floating point number is zero and FALSE
326
  otherwise.
327
*/
328
static bool is_fzero
329
    PROTO_N ( ( fnum ) )
330
    PROTO_T ( flt fnum )
331
{
332
  int i;
333
  for(i=0;(i<MANT_SIZE) && (fnum.mant[i]==0);++i);
334
  return (i==MANT_SIZE);
335
}
336
 
337
 
338
 
339
/*
340
  Functions to handle the 'trap' exception handling mechanism
341
*/
342
static int trap_label
343
    PROTO_N ( ( e ) )
344
    PROTO_T ( exp e )
345
{
346
  if (error_treatment_is_trap(e)){
347
    if (aritherr_lab == 0) aritherr_lab = new_label();
348
    return aritherr_lab;
349
  }
350
  else return no(son(pt(e)));
351
}
352
 
353
static void do_exception
354
    PROTO_N ( ( ex ) )
355
    PROTO_T ( int ex )
356
{
357
  baseoff b;
358
 
359
  load_store_immediate(i_ldiq, FIRST_INT_ARG,  ex);
360
  setnoat();
361
  /*  b = find_tag("__TDFhandler");*/
362
  b = find_tag("__alpha_errhandler");
363
  load_store(i_ldq,AT,b);
364
  operate_fmt(i_bis,AT,AT,PV);
365
  b.base = AT;
366
  b.offset = 0;
367
  integer_jump(i_jmp,31,AT,0);
368
  setat();
369
  return;
370
}
371
 
372
 
373
/*
374
  check that the floating point register contains a non-negative 
375
  value and,if it does, convert to signed by adding the 
376
  appropriate constant.
377
*/
378
static void fix_unsigned
379
    PROTO_N ( ( fr,sp,name ) )
380
    PROTO_T ( freg fr X space sp X int name )
381
{
382
  space nsp;
383
  int ftmp;
384
  freg newfr;  
385
  ans aa;
386
  flpt fltval;
387
  exp float_exp;
388
  instore isa;
389
  where dest;
390
  flt constval;
391
  nsp = guardfreg(fr.fr,sp);
392
  ftmp = getfreg(nsp.flt);
393
  fltval = new_flpt();
394
  switch(name){
395
    case uwordhd:
396
    constval = alpha_word_max;
397
    break;
398
    case ulonghd:
399
    constval =  alpha_long_max;
400
    break;
401
    case u64hd:
402
    constval = alpha_quad_max;
403
    break;
404
  }
405
  flptnos[fltval] = constval;
406
  comment("BEGIN fix_unsigned");
407
  float_exp = getexp(realsh,nilexp,1,nilexp,nilexp,0,fltval,real_tag);
408
#if DO_SCHEDULE
409
  start_new_capsule(false);
410
#endif
411
  isa = evaluated(float_exp,0);
412
  set_text_section();
413
#if DO_SCHEDULE
414
  close_capsule();
415
#endif
416
  setinsalt(aa,isa);
417
  dest.ashwhere.ashsize = (fr.type == IEEE_single)?32:64;
418
  dest.ashwhere.ashalign = dest.ashwhere.ashsize;
419
  newfr.fr = ftmp;
420
  newfr.type = fr.type;
421
  setfregalt(dest.answhere,newfr);
422
  (void)move(aa,dest,nsp,0);
423
  float_op((fr.type == IEEE_single)?i_adds:i_addt,fr.fr,ftmp,ftmp);
424
  float_op(i_fcmovlt,fr.fr,ftmp,fr.fr);
425
  comment("END fix_unsigned");
426
  return;
427
}
428
 
429
 
430
INT64 unsigned_rep
431
    PROTO_N ( ( val, dest_shape ) )
432
    PROTO_T ( INT64 val X shape dest_shape )
433
{
434
  switch(name (dest_shape)){
435
    case ucharhd: return val & 0xff;
436
    case uwordhd: return val & 0xffff;
437
    case ulonghd: return val & 0xffffffff;
438
    case u64hd: return val;
439
  }
440
  return val;
441
}
442
 
443
 
444
 
445
/*
446
  Inserts global pointer reference.
447
*/
448
static void set_global_pointer
449
    PROTO_Z ()
450
{
451
  baseoff a;
452
  a.offset = 0;
453
  a.base = PV;
454
  load_store(i_ldgp,GP,a);
455
  return;
456
}
457
 
458
#if !DO_NEW_DIVISION
459
/*
460
  This function produces a code sequence to divide the contents of 
461
  register 'src' by constant value 'm' and store the result in
462
  register 'target'.  The division is performed by calculating 
463
  umax64/b and then performing an umulh of this with the source 
464
  register.
465
*/
466
static void divide_by_constant
467
    PROTO_N ( ( src,m,target,sp ) )
468
    PROTO_T ( int src X INT64 m X int target X space sp )
469
{
470
  space newsp;
471
  int rtmp;
472
  int ruse;
473
  INT64 divres;
474
  int use_div_lab,exit_lab;
475
  newsp = guardreg(src,sp);
476
  rtmp=getreg(newsp.fixed);
477
  ruse = getreg(guardreg(rtmp,newsp).fixed);
478
  exit_lab = new_label();
479
  use_div_lab = new_label();
480
  operate_fmt(i_subq,31,src,ruse);
481
  operate_fmt(i_cmovgt,src,src,ruse);
482
  INT64_assign(divres, INT64_increment(INT64_divide(umax,m,0)));
483
  load_store_immediate(i_ldiq,rtmp,divres);
484
  operate_fmt(i_umulh,rtmp,ruse,target);
485
  operate_fmt(i_subq,31,target,ruse);
486
  operate_fmt(i_cmovlt,src,ruse,target);
487
  return;
488
}
489
#endif
490
 
491
#if DO_NEW_DIVISION
492
 
493
/* 
494
   Output log2(x) rounding up.
495
*/
496
int log2
497
    PROTO_N ( ( val ) )
498
    PROTO_T ( INT64 val )
499
{
500
  int res = 0;
501
  int absval = abs(val);
502
  while(!INT64_eq(absval,make_INT64(0,1))){
503
    /*while (absval != 1){*/
504
    while (!INT64_eq(INT64_mod(absval,make_INT64(0,2),1),make_INT64(0,0))){
505
      /*while (absval % 2){*/
506
      absval = INT64_increment(absval);
507
      /*++absval;*/
508
    }
509
    while (INT64_eq(INT64_mod(absval,make_INT64(0,2),1),make_INT64(0,0))){
510
      /*while (absval % 2 == 0){*/
511
      ++res;
512
      absval = INT64_divide(absval,make_INT64(0,2),1);
513
      /*absval /=2;*/
514
    }
515
  }
516
  return res;
517
}
518
 
519
 
520
 
521
 
522
/*
523
  If 1/m can be transformed into the form:
524
 
525
  1/m = 1/(2^n) * (2^x/b).  Then return the values of n and x
526
  required.  If successfull, return TRUE, otherwise, return FALSE.
527
*/
528
bool calculate_shift_for_division
529
    PROTO_N ( ( m,n,x,is_quad ) )
530
    PROTO_T ( INT64 m X int *n X int *x X bool is_quad )
531
{
532
  INT64 val = m;
533
  INT64 r;
534
  int shift=0;
535
  int power = 1;
536
  INT64 max32 = make_INT64(0,0xffffffff);
537
  INT64 max16 = make_INT64(0,0xffff);
538
  if (is_quad){
539
    /*r = (429496729L%m) * 429496729L;*/
540
    r = INT64_mult( max32, INT64_mod(max32,m,1),1);
541
  }
542
  else{
543
    /*r = (65536%m) *65536;*/
544
    r = INT64_mult( max16, INT64_mod(max16,m,1),1);
545
  }
546
  r = INT64_mod(r,val,1);
547
  /*r = r % val; */
548
  while(INT64_eq(INT64_mod(val,make_INT64(0,2),1),make_INT64(0,0))){
549
    /*  while(val%2 == 0){*/
550
    val = INT64_shift_right(val,1,1);
551
    /*val/=2;*/
552
    shift++;
553
  }
554
  if (INT64_eq(val,make_INT64(0,1))){
555
    failer("Unexpected power of 2 in shift calculation");
556
    exit(EXIT_FAILURE);
557
  }
558
  while ((INT64_lt(make_INT64(0,power),val) && 
559
	  INT64_lt(make_INT64(0,power), INT64_subtract(val,r,1)))){
560
    /*while ((power<val) && (val-r > power)){*/
561
    r = INT64_mult(r,make_INT64(0,2),1);
562
    /*r *= 2;*/
563
    /*r = r % val;*/
564
    r = INT64_mod(r,val,1);
565
    power *=2;
566
    /*power *= 2;*/
567
  }
568
  *n = shift;
569
  *x = power;
570
  return INT64_lt(make_INT64(0,power),val)?TRUE:FALSE;
571
  /*return (power<val)?TRUE:FALSE;*/
572
}
573
 
574
 
575
/*
576
  This function produces a code sequence to divide the contents of 
577
  register 'src' by constant value 'm' and store the result in
578
  register 'target'.  The division is performed by calculating 
579
  umax64/b and then performing an umulh of this with the source 
580
  register.  The code produced makes use of the AT register.
581
*/
582
static void divide_by_constant
583
    PROTO_N ( ( div,lhs,valexp,r_dest,nsp ) )
584
    PROTO_T ( exp div X exp lhs X exp valexp X int r_dest X space nsp )
585
{
586
  INT64 m = zero_int64;	
587
  INT64 divres;
588
  bool simple_div;
589
  INT64 max_val;
590
  INT64 factor;
591
  int shift,power /*,factor*/;
592
  int src = reg_operand(lhs,nsp);
593
  int ruse,rdest,r_frac_value;
594
  space newsp = guardreg(src,nsp);
595
  int is_quad = !is32(sh(lhs));
596
  newsp = guardreg(r_dest,newsp);
597
  if(!is_quad){
598
    m = make_INT64(0,no(valexp));
599
  }
600
  else{
601
    m = flt64_to_INT64(exp_to_f64(valexp));
602
  }	
603
  if(!is_signed(sh(lhs)) && INT64_lt(m,make_INT64(0,0))){
604
    setnoat();
605
    load_store_immediate(i_ldiq,AT,m);
606
    operate_fmt(i_cmpule,AT,src,rdest);
607
    setat();
608
    return;
609
  }	
610
  /*max_val = is_quad?0xffffffffffffffffL:0xffffffffL;*/
611
  max_val = is_quad?make_INT64(0xffffffff,0xffffffff):make_INT64(0,0xffffffff);
612
 
613
  simple_div = calculate_shift_for_division(m,&shift,&power,is_quad);
614
  r_frac_value = r_dest;	/* alias, saves registers */
615
  if(simple_div){
616
    factor = m/*2<<power*/;
617
    factor = INT64_shift_left(make_INT64(0,2),log2(m)-1,1);
618
    /*factor = 2<<(log2(m)-1);*/
619
  }
620
  else if(is_signed(sh(lhs))){
621
    factor = (m);
622
    factor = INT64_shift_left(make_INT64(0,2),log2(m)-1,1);
623
    /*factor = 2<<(log2(m)-1);*/
624
    shift = 0 /*factor*/;
625
  }
626
  else{
627
    factor = INT64_subtract(
628
			    INT64_shift_left(make_INT64(0,2),log2(m)-1,1),
629
			    m,1);
630
    /*factor = (2<<(log2(m)-1))-m;*/
631
    /*    factor = power-m;*/
632
  }
633
  divres = INT64_add(INT64_divide(factor,m,1),
634
		     INT64_mult(
635
				INT64_divide(max_val,m,1),
636
				factor,
637
				1
638
				),	
639
		     1
640
		     );
641
  /*  divres = factor/m + (max_val/m)*factor;*/
642
  if(!is_quad) divres = 
643
    INT64_add(
644
	      INT64_divide(
645
			   INT64_shift_left(
646
					    make_INT64(0,1),
647
					    32+log2(m)-1,
648
					    1
649
					    ),
650
			   m,
651
			   1
652
			   ),
653
	      INT64_divide(
654
			   INT64_shift_left(
655
					    make_INT64(0,1),
656
					    log2(m)-1,
657
					    1
658
					    ),
659
			   m,
660
			   1
661
			   ),
662
	      1
663
	      );
664
#if 0				        
665
  if (!is_quad) divres = (((long)0x1<<(32+log2(m)))/m) + (1<<log2(m))/m;
666
#endif
667
  if(is_signed(sh(lhs))){
668
    /*ruse = getreg(newsp.fixed);*/
669
    ruse = AT;
670
    setnoat();
671
    operate_fmt(i_subq,31,src,ruse);
672
    operate_fmt(i_cmovgt,src,src,ruse);
673
  }	
674
  else{
675
    if(!is_quad){
676
      /*ruse = getreg(newsp.fixed);*/
677
      ruse = AT;
678
      setnoat();
679
      operate_fmt_immediate(i_zap,src,240,ruse);
680
    }
681
    else {
682
      ruse = src;
683
    }	
684
  }
685
  if(is_quad){
686
    operate_fmt_big_immediate(i_umulh,ruse,divres,r_dest);
687
  }
688
  else{
689
    load_store_immediate(i_ldiq,r_frac_value,divres);
690
    operate_fmt(i_mulq,ruse,r_frac_value,r_dest);
691
  }	
692
  if(is_signed(sh(lhs))){
693
    operate_fmt_immediate(i_sra,r_dest,(is_quad?0:32)+log2(m)-1,r_dest);
694
  }
695
  else{
696
    operate_fmt_immediate(i_srl,r_dest,(is_quad?0:32)+((!simple_div)?0:
697
						       (log2(m)-1)),r_dest);
698
  }
699
  if(is_signed(sh(lhs))){
700
    operate_fmt(i_subq,31,r_dest,ruse);
701
    operate_fmt(INT64_lt(make_INT64(0,0),m)?i_cmovlt:i_cmovgt,src,ruse,r_dest);
702
    /*operate_fmt((m>0)?i_cmovlt:i_cmovgt,src,ruse,r_dest);*/
703
  }
704
  else if(!simple_div && !is_signed(sh(lhs))){
705
    operate_fmt(i_addq,r_dest,ruse,r_dest);
706
    operate_fmt_immediate(i_srl,r_dest,log2(m),r_dest);
707
  }
708
  if (ruse == AT) setat();
709
  return;
710
}
711
 
712
#endif
713
 
714
 
715
 
716
/*
717
  This function produces a code sequence to convert the value in 
718
  register reg from shape src_shape to shape dest_shape. 
719
  Returns TRUE if any code is produced and FALSE otherwise.
720
*/
721
static bool convert_shapes
722
    PROTO_N ( ( dest_shape,src_shape,reg,dreg ) )
723
    PROTO_T ( int dest_shape X int src_shape X int reg X int dreg )
724
{
725
  if(reg<32 && dreg<32){
726
    switch(dest_shape){
727
      case s64hd:
728
      case u64hd:
729
      switch(src_shape){
730
	case ucharhd:
731
	operate_fmt_immediate(i_zapnot,reg,1,dreg);
732
	/* clear all but the bottom byte */
733
	return TRUE;
734
	case uwordhd:
735
	operate_fmt_immediate(i_zapnot,reg,3,dreg);
736
	return TRUE;
737
	case ulonghd:
738
	operate_fmt_immediate(i_zapnot,reg,15,dreg);
739
	return TRUE;
740
	default: return FALSE;
741
      }
742
      case slonghd:
743
      switch(src_shape){
744
	case ucharhd:
745
	operate_fmt_immediate(i_zapnot,reg,1,dreg);
746
	return TRUE;
747
	case uwordhd:
748
	operate_fmt_immediate(i_zapnot,reg,3,dreg);
749
	return TRUE;
750
	case ulonghd:
751
/*	operate_fmt_immediate(i_addl,reg,0,dreg);
752
	return TRUE;*/
753
	return FALSE;
754
	/* sign extend */
755
#if 0
756
	case s64hd: 
757
	operate_fmt_immediate(i_zapnot,reg,15,dreg);
758
	/*operate_fmt_immediate(i_addl,reg,0,reg);*/
759
	return TRUE;
760
#endif
761
	default:return FALSE;
762
      }
763
      case ulonghd:
764
      switch(src_shape){
765
	case scharhd:
766
	operate_fmt_immediate(i_zapnot,reg,1,dreg);
767
	return TRUE;
768
	case swordhd:
769
	operate_fmt_immediate(i_zapnot,reg,3,dreg);
770
	return TRUE;
771
	case slonghd:
772
/*	operate_fmt_immediate(i_zapnot,reg,15,dreg);
773
	return TRUE;*/
774
	return FALSE;
775
#if 0
776
	case s64hd:
777
	operate_fmt_immediate(i_zapnot,reg,15,dreg);
778
	return TRUE;
779
#endif
780
	default: return FALSE
781
		   ;
782
      }
783
      default:return FALSE;
784
    }
785
  }
786
  return FALSE;
787
}
788
 
789
#define OVERFLOW_VALUE 0x02e0000000000000
790
/*
791
  Checks for floating point error.  
792
 
793
  This function outputs code to look at the contents of the 
794
  floating  point control register (FPCR) and determine whether 
795
  or not a floating point error has occured.  If an error is 
796
  detected a jump is made to the label specified in no(son(pt(e))).  
797
 
798
  The error status is determined by looking at the summary bit 
799
  of the FPCR (bit 63) which is a bitwise OR of all the error bits.
800
  The errors recognised are : integer overflow,inexact result,
801
  underflow,overflow,division by zero, and invalid operation.
802
*/
803
#if 0
804
static void check_exception
805
    PROTO_N ( ( e,sp ) )
806
    PROTO_T ( exp e X space sp )
807
{
808
  long trap;
809
  int r1,r2;
810
  if(!pt(e)){
811
    alphafail(NO_ERROR_HANDLER);
812
  }
813
  trap = trap_label(e);  	/* label of handler */
814
  r1 = getfreg(sp.flt);
815
  r2 = getfreg(guardfreg(r1,sp).flt);
816
  no_parameter_instructions(i_trapb); 
817
  float_op(i_mf_fpcr,r1,r1,r1);    
818
#if 0
819
  /*float_op(i_mt_fpcr,31,31,31);*/
820
  float_load_store_immediate(i_ldit,r2,"1.0"); 	/* ?? */
821
  float_op(i_cpys,r1,r2,r2);/* take the sign bit of the fpcr and append 1.0 */
822
  no_parameter_instructions(i_trapb); 
823
  float_branch(i_fblt,r2,trap);
824
#else
825
  {
826
    baseoff b;
827
    int rt = getreg(sp.fixed);
828
    b.base = SP;
829
    b.offset = stack_top;
830
    float_load_store(i_stt,r1,b);
831
    load_store(i_ldq,rt,b);
832
    /* now check for overflow (bits 57/55/54/53) */
833
    operate_fmt_big_immediate(i_and,rt,OVERFLOW_VALUE,rt);
834
    no_parameter_instructions(i_trapb); 
835
    integer_branch(i_bne,rt,trap);
836
  }
837
#endif  
838
}
839
#endif
840
#define check_exception( e, sp )	( ( void ) 0 )
841
 
842
#define PLUS_INFINITY 3
843
 
844
void set_up_rounding_mode
845
    PROTO_N ( ( val ) )
846
    PROTO_T ( int val )
847
{
848
  return;
849
}
850
 
851
 
852
/*
853
  This function returns the appropriate branch instruction 
854
  for the test represented by 'i'
855
*/
856
static instruction sbranches
857
    PROTO_N ( ( i ) )
858
    PROTO_T ( int i )
859
{
860
  switch (i) {
861
    case  1: 
862
    return i_ble;
863
    case 2: 
864
    return i_blt;
865
    case 3: 
866
    return i_bge;
867
    case 4: 
868
    return i_bgt;
869
    case 5: 
870
    return i_bne;
871
    case 6: 
872
    return i_beq;
873
    default:
874
    failer("Illegal value for ntest");
875
  }
876
  return i_ble;
877
}
878
 
879
 
880
void testunsigned
881
    PROTO_N ( ( r,max,lab,sp ) )
882
    PROTO_T ( int r X long max X int lab X space sp )
883
{
884
  int rtmp = getreg(sp.fixed);
885
  operate_fmt_immediate(i_cmpule,r,max,rtmp);
886
  integer_branch(i_bne,rtmp,lab);
887
  return;
888
}
889
 
890
 
891
 
892
static bool fdouble_comparisons
893
    PROTO_N ( ( ins,i ) )
894
    PROTO_T ( instruction *ins X int i )
895
{
896
  bool rev = FALSE;
897
  switch(i){
898
    case 1:
899
    *ins = i_cmptle;
900
    break;
901
    case 2:
902
    *ins = i_cmptlt;
903
    break;
904
    case 3:
905
    *ins = i_cmptlt;
906
    rev = TRUE;
907
    break;
908
    case 4:
909
    *ins = i_cmptle;
910
    rev = TRUE;
911
    break;
912
    case 5:
913
    *ins = i_cmpteq;
914
    rev = TRUE;
915
    break;
916
    case 6:
917
    *ins = i_cmpteq;
918
    break;
919
    default:
920
    failer("illegal branch");
921
    break;
922
  }
923
  return rev;
924
}
925
 
926
 
927
/*
928
  This function selects an appropriate compare instruction for
929
  the test represented by 'i', returning the instruction name in
930
  the 'ins' parameter.  As the set of instructions available does
931
  not directly cover all the required tests, some instructions
932
  carry out the inverse of the required test.  In these cases, the
933
  return value is TRUE, otherwise it is FALSE.
934
*/
935
static bool comparisons
936
    PROTO_N ( ( ins,s,i ) )
937
    PROTO_T ( instruction *ins X shape s X int i )
938
{
939
  bool rev=FALSE;
940
  if((is_signed(s))){
941
    /* treat pointer as signed (even though it isn't) */
942
    switch(i){
943
      case 1:
944
      *ins=i_cmple;
945
      break;
946
      case 2:
947
      *ins = i_cmplt;
948
      break;
949
      case 3:
950
      *ins = i_cmplt;
951
      rev = TRUE;
952
      break;
953
      case 4:
954
      *ins = i_cmple;
955
      rev = TRUE;
956
      break;
957
      case 5:
958
      *ins = i_cmpeq;
959
      rev = TRUE;
960
      break;
961
      case 6:
962
      *ins = i_cmpeq;
963
      break;
964
      default:
965
      failer("illegal branch");
966
      break;
967
    }
968
  }
969
  else{
970
    switch(i){
971
      case 1:
972
      *ins=i_cmpule;
973
      break;
974
      case 2:
975
      *ins=i_cmpult;
976
      break;
977
      case 3:
978
      *ins=i_cmpult;
979
      rev=TRUE;		/* actually >= */
980
      break;
981
      case 4:			
982
      *ins=i_cmpule;	/* actually > */
983
      rev=TRUE;
984
      break;
985
      case 5:
986
      *ins = i_cmpeq;
987
      rev = 1;
988
      break;
989
      case 6:
990
      *ins = i_cmpeq;
991
      break;
992
      default:
993
      failer("illegal branch");
994
    }
995
  }
996
  return rev;
997
}
998
 
999
 
1000
 
1001
/*
1002
  conditional moves
1003
*/
1004
static instruction condmove
1005
    PROTO_N ( ( i ) )
1006
    PROTO_T ( int i )
1007
{
1008
  switch(i){
1009
    case 1:
1010
    return i_cmovle;
1011
    case 2:
1012
    return i_cmovlt;
1013
    case 3:
1014
    return i_cmovge;
1015
    case 4:
1016
    return i_cmovgt;
1017
    case 5:
1018
    return i_cmovne;
1019
    case 6:
1020
    return i_cmoveq;
1021
    default:
1022
    failer("Illegal value for ntest");
1023
  }
1024
  return i_cmovle;
1025
}
1026
/*
1027
static instruction fcondmove
1028
    PROTO_N ( ( i ) )
1029
    PROTO_T ( int i )
1030
{
1031
  switch(i){
1032
   case 1:
1033
    return i_fcmovle;
1034
   case 2:
1035
    return i_fcmovlt;
1036
   case 3:
1037
    return i_fcmovge;
1038
   case 4:
1039
    return i_fcmovgt;
1040
   case 5:
1041
    return i_fcmovne;
1042
   case 6:
1043
    return i_fcmoveq;
1044
 default:
1045
     failer("Illegal value for ntest");
1046
 }
1047
}
1048
*/
1049
 
1050
 
1051
static bool compares
1052
    PROTO_N ( ( ins,s,i ) )
1053
    PROTO_T ( instruction *ins X shape s X int i )
1054
{
1055
  bool rev=FALSE;
1056
  if (is_signed(s)){
1057
    /* signed comparison */
1058
    switch(i){
1059
      case 1:
1060
      *ins= i_cmplt;
1061
      break;
1062
      case 2:
1063
      *ins= i_cmple;
1064
      break;
1065
      case 3:
1066
      *ins= i_cmplt;
1067
      break;
1068
      case 4:
1069
      *ins= i_cmple;
1070
      break;
1071
      case 5:
1072
      *ins= i_cmpeq;
1073
      break;
1074
      case 6:
1075
      *ins= i_cmpeq;
1076
      break;
1077
    }
1078
  }
1079
  else{
1080
    switch(i){
1081
      case 1:
1082
      *ins= i_cmpult;
1083
      break;
1084
      case 2:
1085
      *ins= i_cmpule;	
1086
      break;
1087
      case 3:
1088
      *ins= i_cmpult;
1089
      rev=TRUE;
1090
      break;
1091
      case 4:
1092
      *ins= i_cmpule;
1093
      rev=TRUE;
1094
      break;
1095
      case 5:
1096
      *ins= i_cmpeq;
1097
      break;
1098
      case 6:
1099
      *ins= i_cmpeq;
1100
      break;
1101
    }
1102
  }
1103
  return rev;
1104
}
1105
 
1106
/*
1107
static instruction fbranches
1108
    PROTO_N ( ( i ) )
1109
    PROTO_T ( int i )
1110
{
1111
  switch (i) {
1112
    case  1: 
1113
    return i_fble;
1114
    case 2: 
1115
    return i_fblt;
1116
    case 3: 
1117
    return i_fbge;
1118
    case 4: 
1119
    return i_fbgt;
1120
    case 5: 
1121
    return i_fbne;
1122
    case 6: 
1123
    return i_fbeq;
1124
    default:
1125
    failer("Illegal value for ntest");
1126
  }
1127
}
1128
 
1129
static instruction fdbranches
1130
    PROTO_N ( ( i ) )
1131
    PROTO_T ( int i )
1132
{
1133
  switch (i) {
1134
   case  1: 
1135
    return i_fble;
1136
   case 2: 
1137
    return i_fblt;
1138
   case 3: 
1139
    return i_fbge;
1140
   case 4: 
1141
    return i_fbgt;
1142
   case 5: 
1143
    return i_fbne;
1144
   case 6: 
1145
    return i_fbeq;
1146
   default:
1147
    failer("Illegal value for ntest");
1148
  }
1149
}
1150
*/
1151
long  notbranch[6] = {
1152
  4, 3, 2, 1, 6, 5
1153
};
1154
/* used to invert TDF tests */
1155
 
1156
/*
1157
  count the number of bits set in b.
1158
*/
1159
int bitsin
1160
    PROTO_N ( ( b ) )
1161
    PROTO_T ( int32 b )
1162
{
1163
  int   n = 0;
1164
  int32  mask = 1;
1165
  for (; b != 0;) {
1166
    n += ((b & mask) != 0) ? 1 : 0;
1167
    b &= ~mask;
1168
    mask = mask << 1;
1169
  }
1170
  return n;
1171
}
1172
 
1173
 
1174
/*****************************************************************/
1175
 
1176
/*
1177
  Move sizereg bytes to dest from source using movereg 
1178
  bytemove is the maximum number of bytes which can be moved 
1179
  in a single instruction if available.  
1180
  In order to reduce the time for the operation the function 
1181
  attempts to use the most appropriate load & store instructions, 
1182
  which requires that the number of bytes remaining to be copied 
1183
  and the alignment of the object be taken into account.  
1184
  As the code sequence required to generate word (16 bit) 
1185
  load/store is prohibitively long, these cases are treated 
1186
  as bytes.
1187
*/
1188
 
1189
 
1190
/*
1191
  Without overlap (destination < source)
1192
*/
1193
void move_dlts
1194
    PROTO_N ( ( dest,src,sizereg,movereg,bytemove,sp ) )
1195
    PROTO_T ( int dest X int src X int sizereg X int movereg X int bytemove X space sp )
1196
{
1197
 
1198
  int qword_lab,lword_lab,word_lab,byte_lab,endlab;
1199
  int rtest = getreg(sp.fixed);
1200
  baseoff b;
1201
  b.offset = 0;
1202
  qword_lab = (bytemove==8)?new_label():-1;
1203
  lword_lab = (bytemove>=4)?new_label():-1;
1204
  word_lab = (bytemove>=2)?new_label():-1;
1205
  byte_lab = new_label();
1206
  endlab = new_label();
1207
  switch(bytemove){
1208
    case 8 :{
1209
      set_label(qword_lab);
1210
      operate_fmt_immediate(i_cmplt,sizereg,8,rtest);
1211
      integer_branch(i_bne,rtest,lword_lab);
1212
      b.base = src;
1213
      load_store(i_ldq,movereg,b);
1214
      b.base = dest;
1215
      load_store(i_stq,movereg,b);
1216
      operate_fmt_immediate(i_addq,src,8,src);
1217
      operate_fmt_immediate(i_addq,dest,8,dest);
1218
      operate_fmt_immediate(i_subq,sizereg,8,sizereg);
1219
      integer_branch(i_beq,sizereg,endlab);
1220
      integer_branch(i_br,31,qword_lab);
1221
    }
1222
    FALL_THROUGH;
1223
    case 4 :{
1224
      set_label(lword_lab);
1225
      operate_fmt_immediate(i_cmplt,sizereg,4,rtest);
1226
      integer_branch(i_bne,rtest,byte_lab);
1227
      b.base = src;
1228
      load_store(i_ldl,movereg,b);
1229
      b.base = dest;
1230
      load_store(i_stq,movereg,b);
1231
      operate_fmt_immediate(i_addq,src,4,src);
1232
      operate_fmt_immediate(i_addq,dest,4,dest);
1233
      operate_fmt_immediate(i_subq,sizereg,4,sizereg);
1234
      integer_branch(i_beq,sizereg,endlab);
1235
      integer_branch(i_br,31,lword_lab);
1236
    }
1237
    FALL_THROUGH;
1238
    case 2 :	
1239
    FALL_THROUGH;
1240
    case 1 :{
1241
      int rtmp = getreg(sp.fixed);
1242
      int rtmp2 = getreg(sp.fixed);
1243
      set_label(byte_lab);
1244
      integer_branch(i_beq,sizereg,endlab);
1245
      b.base=src;
1246
      load_store(i_ldq_u,movereg,b);
1247
      setnoat();
1248
      load_store(i_lda,AT,b);
1249
      operate_fmt(i_extbl,movereg,AT,movereg);
1250
      b.base=dest;
1251
      load_store(i_lda,AT,b);
1252
      load_store(i_ldq_u,rtmp,b);
1253
      operate_fmt(i_insbl,movereg,AT,rtmp2);
1254
      operate_fmt(i_mskbl,rtmp,AT,rtmp);
1255
      setat();
1256
      operate_fmt(i_bis,rtmp,rtmp2,rtmp);
1257
      load_store(i_stq_u,rtmp,b);
1258
      operate_fmt_immediate(i_addq,src,1,src);
1259
      operate_fmt_immediate(i_addq,dest,1,dest);
1260
      operate_fmt_immediate(i_subq,sizereg,1,sizereg);
1261
      integer_branch(i_bne,sizereg,byte_lab);
1262
    }
1263
  }
1264
  set_label(endlab);
1265
  return;
1266
}
1267
 
1268
 
1269
/*
1270
  With overlap (destination > src)
1271
*/
1272
void move_dgts
1273
    PROTO_N ( ( dest,src,sizereg,movereg,bytemove,sp ) )
1274
    PROTO_T ( int dest X int src X int sizereg X int movereg X int bytemove X space sp )
1275
{
1276
  int qword_lab,lword_lab,word_lab,byte_lab,endlab;
1277
  int rtest = getreg(sp.fixed);
1278
  baseoff b;
1279
  b.offset = 0;
1280
  qword_lab = (bytemove==8)?new_label():-1;
1281
  lword_lab = (bytemove>=4)?new_label():-1;
1282
  word_lab = (bytemove>=2)?new_label():-1;
1283
  byte_lab = new_label();
1284
  endlab = new_label();
1285
  operate_fmt(i_addq,dest,sizereg,dest);
1286
  operate_fmt(i_addq,src,sizereg,src);
1287
  switch(bytemove){
1288
    case 8 :{
1289
      b.offset = -8;
1290
      set_label(qword_lab);
1291
      operate_fmt_immediate(i_cmplt,sizereg,8,rtest);
1292
      integer_branch(i_bne,rtest,lword_lab);
1293
      b.base = src;
1294
      load_store(i_ldq,movereg,b);
1295
      b.base = dest;
1296
      load_store(i_stq,movereg,b);
1297
      operate_fmt_immediate(i_subq,src,8,src);
1298
      operate_fmt_immediate(i_subq,dest,8,dest);
1299
      operate_fmt_immediate(i_subq,sizereg,8,sizereg);
1300
      integer_branch(i_beq,sizereg,endlab);
1301
      integer_branch(i_br,31,qword_lab);
1302
    }
1303
    FALL_THROUGH;
1304
    case 4 :{
1305
      b.offset = -4;
1306
      set_label(lword_lab);
1307
      operate_fmt_immediate(i_cmplt,sizereg,4,rtest);
1308
      integer_branch(i_bne,rtest,byte_lab);
1309
      b.base = src;
1310
      load_store(i_ldl,movereg,b);
1311
      b.base = dest;
1312
      load_store(i_stq,movereg,b);
1313
      operate_fmt_immediate(i_subq,src,4,src);
1314
      operate_fmt_immediate(i_subq,dest,4,dest);
1315
      operate_fmt_immediate(i_subq,sizereg,4,sizereg);
1316
      integer_branch(i_beq,sizereg,endlab);
1317
      integer_branch(i_br,31,lword_lab);
1318
    }
1319
    FALL_THROUGH;
1320
    case 2 :	
1321
    FALL_THROUGH;
1322
    case 1 :{
1323
      int rtmp = getreg(sp.fixed);
1324
      int rtmp2 = getreg(sp.fixed);
1325
      b.offset = -1;
1326
      set_label(byte_lab);
1327
      integer_branch(i_beq,sizereg,endlab);
1328
      b.base=src;
1329
      load_store(i_ldq_u,movereg,b);
1330
      setnoat();
1331
      load_store(i_lda,AT,b);
1332
      operate_fmt(i_extbl,movereg,AT,movereg);
1333
      b.base=dest;
1334
      load_store(i_lda,AT,b);
1335
      load_store(i_ldq_u,rtmp,b);
1336
      operate_fmt(i_insbl,movereg,AT,rtmp2);
1337
      operate_fmt(i_mskbl,rtmp,AT,rtmp);
1338
      setat();
1339
      operate_fmt(i_bis,rtmp,rtmp2,rtmp);
1340
      load_store(i_stq_u,rtmp,b);
1341
      operate_fmt_immediate(i_subq,src,1,src);
1342
      operate_fmt_immediate(i_subq,dest,1,dest);
1343
      operate_fmt_immediate(i_subq,sizereg,1,sizereg);
1344
      integer_branch(i_bne,sizereg,byte_lab);
1345
    }
1346
  }
1347
  set_label(endlab);
1348
  return;
1349
}
1350
 
1351
/****************************************************************/
1352
 
1353
 
1354
 
1355
 
1356
static void reset_tos
1357
    PROTO_Z ()
1358
{
1359
  if (Has_tos) { 
1360
    baseoff b;
1361
    b.base = FP;
1362
    b.offset = -((PTR_SZ>>3)*2) - arg_stack_space;
1363
    load_store(i_stq,SP,b);
1364
  }
1365
  return;
1366
}
1367
 
1368
 
1369
 
1370
/*
1371
  This function finds the last test in the sequence e which is 
1372
  a branch to second, if any exists, otherwise it returns nil.
1373
*/
1374
static exp testlast
1375
    PROTO_N ( ( e, second ) )
1376
    PROTO_T ( exp e X exp second )
1377
{
1378
  if (name (e) == test_tag && pt (e) == second) {
1379
    return (e);
1380
  }
1381
  if (name (e) == seq_tag) {
1382
    if (name (bro (son (e))) == test_tag && pt (bro (son (e))) == second) {
1383
      return bro (son (e));
1384
    }
1385
    else if (name (bro (son (e))) == top_tag) {
1386
      exp list = son (son (e));
1387
      for (;;) {
1388
	if (last (list)) {
1389
	  if (name (list) == test_tag && pt (list) == second) {
1390
	    return list;
1391
	  }
1392
	  else {
1393
	    return 0;
1394
	  }
1395
	}
1396
	else {
1397
	  list = bro (list);
1398
	}
1399
      }
1400
    }
1401
  }
1402
  return 0;
1403
}
1404
 
1405
 
1406
bool last_param
1407
    PROTO_N ( ( e ) )
1408
    PROTO_T ( exp e )
1409
{
1410
  bool res=0;
1411
  if (isparam(e)){
1412
    e = bro(son(e));
1413
    while(name(e) == diagnose_tag)
1414
      e = son(e);
1415
    if((name(e) != ident_tag) || !isparam(e) || 
1416
       name(son(e))==formal_callee_tag)
1417
      res=1;
1418
  }
1419
  return res;
1420
}
1421
 
1422
 
1423
void test_unsigned
1424
    PROTO_N ( ( reg,upper,trap ) )
1425
    PROTO_T ( int reg X unsigned long upper X unsigned trap )
1426
{
1427
  setnoat();
1428
  operate_fmt_big_immediate(i_cmpule,reg,upper,AT);
1429
  integer_branch(i_beq,AT,trap);
1430
  setat();
1431
  return;
1432
}
1433
 
1434
void test_signed
1435
    PROTO_N ( ( reg,lower,upper,trap ) )
1436
    PROTO_T ( int reg X long lower X long upper X int trap )
1437
{
1438
  setnoat();
1439
  operate_fmt_big_immediate(i_cmplt,reg,lower,AT);
1440
  integer_branch(i_bne,AT,trap);
1441
  operate_fmt_big_immediate(i_cmple,reg,upper,AT);
1442
  integer_branch(i_beq,AT,trap);
1443
  setat();
1444
  return;
1445
}
1446
 
1447
 
1448
void test_signed_and_trap
1449
    PROTO_N ( ( reg,lower,upper,except ) )
1450
    PROTO_T ( int reg X long lower X long upper X int except )
1451
{
1452
  int ok_lab = new_label();
1453
  int jump_label = new_label();
1454
 
1455
  setnoat();
1456
  operate_fmt_big_immediate(i_cmplt,reg,lower,AT);
1457
  integer_branch(i_bne,AT,jump_label);
1458
  operate_fmt_big_immediate(i_cmple,reg,upper,AT);
1459
  integer_branch(i_beq,AT,jump_label);
1460
  setat();
1461
  integer_branch(i_br,31,ok_lab);
1462
  set_label(jump_label);
1463
  do_exception(except);
1464
  set_label(ok_lab);
1465
  return;
1466
}
1467
 
1468
void test_unsigned_and_trap
1469
    PROTO_N ( ( reg,upper,except ) )
1470
    PROTO_T ( int reg X unsigned long upper X unsigned except )
1471
{
1472
  int ok_lab = new_label();
1473
  setnoat();
1474
  operate_fmt_big_immediate(i_cmpule,reg,upper,AT);
1475
  integer_branch(i_bne,AT,ok_lab);
1476
  setat();
1477
  do_exception(except);
1478
  set_label(ok_lab);
1479
  return;
1480
}
1481
 
1482
 
1483
 
1484
 
1485
/*
1486
  This function returns a register for use as a destination operand.
1487
  If the final destination is in a register then that register is 
1488
  returned, otherwise a new register is selected from the pool.
1489
*/
1490
int regfrmdest
1491
    PROTO_N ( ( dest, sp ) )
1492
    PROTO_T ( where *dest X space sp )
1493
{
1494
  switch (dest->answhere.discrim) {
1495
    case inreg :{
1496
      return regalt (dest->answhere);
1497
    }
1498
    default :{
1499
      return getreg (sp.fixed);
1500
    }
1501
  }
1502
}	
1503
 
1504
 
1505
freg fregfrmdest
1506
    PROTO_N ( ( dest,sp ) )
1507
    PROTO_T ( where *dest X space sp )
1508
{
1509
  switch (dest->answhere.discrim) {
1510
    case infreg : {
1511
      return fregalt(dest->answhere);
1512
    }
1513
    default : {
1514
      freg fr;
1515
      fr.fr = getfreg(sp.flt);
1516
      fr.type = IEEE_double;
1517
      return fr;
1518
    }
1519
  }
1520
}
1521
 
1522
 
1523
/*
1524
  Divide dividend by divisor using the divide instructions supplied 
1525
  by the the assembler.  These divide instructions corrupt the t-regs
1526
  23,24,25,27(PV), and 28(AT) which have to be protected if in use.
1527
  Returns result register.
1528
*/
1529
static int divide_using_div
1530
    PROTO_N ( ( div,dividend,divisor,dest,sp,div_ins ) )
1531
    PROTO_T ( exp div X exp dividend X exp divisor X where dest X space sp X instruction div_ins )
1532
{
1533
  int r_result;
1534
  space newsp;
1535
  int r_dividend,r_divisor;
1536
  int uns;
1537
  newsp = guardreg(AT,sp);
1538
  uns = !is_signed(sh(dividend));
1539
  r_result = regfrmdest(&dest,newsp);
1540
  if(r_result == NO_REG) {
1541
    r_result = getreg(newsp.fixed);
1542
  }
1543
  newsp = guardreg(r_result,newsp);
1544
  r_dividend = reg_operand(dividend,newsp);
1545
  clear_reg(AT),clear_reg(23),clear_reg(24),clear_reg(25),clear_reg(27);
1546
  newsp = guardreg(r_dividend,newsp);
1547
  if(r_result == NO_REG) r_result = getreg(newsp.fixed);
1548
  if(name(divisor) == val_tag && optop(div)){
1549
    r_divisor = no(divisor);
1550
  }
1551
  else{
1552
    r_divisor = reg_operand(divisor,newsp);
1553
  }
1554
  if (!optop(div) && !error_treatment_is_trap(div)) {
1555
    /* test for (-inf)/-1 and /0 */
1556
    int over = new_label();
1557
    int trap = trap_label(div);
1558
    integer_branch(i_beq,r_divisor,trap);
1559
    if(!(is_signed(sh(div)))) {
1560
      int rt=getreg(newsp.fixed);
1561
      comment(" check unsigned overflow ");
1562
      operate_fmt_immediate(i_cmpeq,r_divisor,-1,rt);
1563
      integer_branch(i_bne,rt,trap);
1564
      set_label(over);
1565
    }
1566
  }
1567
 
1568
  if(!optop(div) && is_signed(sh(div)) && (is64(sh(div)) || is32(sh(div)))){
1569
    int continue_lab = new_label();
1570
    setnoat();
1571
    operate_fmt_immediate(i_cmpeq,r_divisor,-1,AT);
1572
    integer_branch(i_beq,AT,continue_lab);
1573
    operate_fmt_big_immediate(i_cmpeq,r_dividend,maxmin(sh(div)).mini,AT);
1574
    integer_branch(i_beq,AT,continue_lab);
1575
    if(error_treatment_is_trap(div)){
1576
      do_exception(f_overflow);
1577
    }
1578
    else{
1579
      integer_branch(i_br,31,trap_label(div));
1580
    }
1581
    set_label(continue_lab);
1582
    setat();
1583
  }
1584
 
1585
  if((name(divisor) != val_tag) || !optop(div)){
1586
    operate_fmt(div_ins,r_dividend,r_divisor,r_result);
1587
  }
1588
  else{
1589
    operate_fmt_immediate(div_ins,r_dividend,r_divisor,r_result);
1590
  }
1591
  if(name(div) == div1_tag){
1592
    int rem_neg = new_label();
1593
    int exitlab = new_label();
1594
    int rrem = getreg(newsp.fixed);
1595
    if((name(divisor) != val_tag) || !optop(div)) {
1596
      operate_fmt(((uns)?((is64(sh(div)))?i_remqu:i_remlu):
1597
		   (is64(sh(div)))?i_remq:i_reml),
1598
		  r_dividend,r_divisor,rrem);
1599
    }
1600
    else {
1601
      operate_fmt_immediate(((uns)?((is64(sh(div)))?i_remqu:i_remlu):
1602
			     (is64(sh(div)))?i_remq:i_reml),
1603
			    r_dividend,r_divisor,rrem);
1604
    }
1605
 
1606
    integer_branch(i_beq,rrem,exitlab);
1607
    integer_branch(i_blt,rrem,rem_neg);
1608
    /*set_label(rem_pos);*/
1609
    integer_branch(i_bge,r_divisor,exitlab);
1610
    operate_fmt_immediate((is64(sh(div)))?i_addq:i_addl,r_result,-1,r_result);
1611
    integer_branch(i_br,31,exitlab);
1612
    set_label(rem_neg);
1613
    integer_branch(i_ble,r_divisor,exitlab);
1614
    operate_fmt_immediate((is64(sh(div)))?i_addq:i_addl,r_result,-1,r_result);
1615
    set_label(exitlab);
1616
  }
1617
  if(!optop(div)) {
1618
    switch(name(sh(div))){
1619
      case ucharhd :{
1620
	if(error_treatment_is_trap(div)){
1621
	  test_unsigned_and_trap(r_result,255,f_overflow);
1622
	}
1623
	else {
1624
	  test_unsigned(r_result,255,trap_label(div));
1625
	}
1626
	break;
1627
      }
1628
      case scharhd :{
1629
	if(error_treatment_is_trap(div)){
1630
	  test_signed_and_trap(r_result,-128,127,f_overflow);
1631
	}
1632
	else{
1633
	  test_signed(r_result,-128,127,trap_label(div));
1634
	}
1635
	break;
1636
      }
1637
      case uwordhd :{
1638
	if(error_treatment_is_trap(div)){
1639
	  test_unsigned_and_trap(r_result,0xffff,f_overflow);
1640
	}
1641
	else {
1642
	  test_unsigned(r_result,0xffff,trap_label(div));
1643
	}
1644
	break;
1645
      }
1646
      case swordhd : {
1647
	if(error_treatment_is_trap(div)){
1648
	  test_signed_and_trap(r_result,-0x8000,0x7fff,f_overflow);
1649
	}
1650
	else {
1651
	  test_signed(r_result,-0x8000,0x7fff,trap_label(div));
1652
	}
1653
	break;
1654
      }
1655
      case ulonghd :{
1656
	if(error_treatment_is_trap(div)){
1657
	  test_unsigned_and_trap(r_result,0xffffffff,f_overflow);
1658
	}
1659
	else{
1660
	  test_unsigned(r_result,0xffffffff,trap_label(div));
1661
	}
1662
	break;
1663
      }
1664
      case slonghd :{
1665
	if(error_treatment_is_trap(div)){
1666
	  test_signed_and_trap(r_result,-0x80000000L,0x7fffffff,f_overflow);
1667
	}
1668
	else{
1669
	  test_signed(r_result,-0x80000000L,0x7fffffff,trap_label(div));
1670
	}
1671
	break;
1672
      }
1673
      case s64hd :{
1674
	if(error_treatment_is_trap(div)){
1675
	  test_signed_and_trap(r_result,-0x8000000000000000L,0x7fffffffffffffffL
1676
			       ,f_overflow);  
1677
	}
1678
	else{
1679
	  test_signed(r_result,-0x8000000000000000L,0x7fffffffffffffffL
1680
		      ,trap_label(div));
1681
	}
1682
	break;
1683
      }
1684
      case u64hd :{
1685
	if(error_treatment_is_trap(div)){
1686
	  test_unsigned_and_trap(r_result,0xffffffffffffffffL,f_overflow);
1687
	}
1688
	else{
1689
	  test_unsigned(r_result,0xffffffffffffffffL,trap_label(div));
1690
	}
1691
	break;
1692
      }
1693
      default:failer("Illegal shape in div");
1694
    }
1695
  }
1696
  return r_result;
1697
}
1698
 
1699
 
1700
static int proc_has_vararg;
1701
 
1702
 
1703
/*
1704
  Process a parameter list 
1705
*/
1706
space do_callers
1707
    PROTO_N ( ( list,sp,sizecallers ) )
1708
    PROTO_T ( exp list X space sp X int *sizecallers )
1709
{
1710
  int disp;
1711
  int spar;
1712
  int fpar = 16;
1713
  ash ansash;
1714
  bool hadfixed;
1715
  instore is;
1716
  is.b.base = SP;
1717
  is.b.offset = 0;
1718
  is.adval = 1;
1719
 
1720
#ifdef DO_SPECIAL
1721
  if ((disp = specialfn (fn)) > 0) { /* eg function is strlen */
1722
    mka.lab = specialmake (disp, list, sp, dest, exitlab);
1723
    return mka;
1724
  }
1725
#endif
1726
  ansash = ashof (sh (list));
1727
  disp = 0;
1728
  spar = FIRST_INT_ARG;/* register holding 1st integer parameter */
1729
  hadfixed = 0;
1730
  for (;;) {		/* evaluate parameters in turn */
1731
    int   hd = name (sh (list));
1732
    where w;
1733
    ash ap;
1734
    int paral;
1735
    int parsize;
1736
    ap = ashof (sh (list));
1737
    paral = (ap.ashalign < 32)?32:ap.ashalign;
1738
    if(spar>21){
1739
      ap.ashalign=64;
1740
      paral = 64;
1741
    }
1742
    parsize = ap.ashsize;
1743
    /* all parameters passed on stack are quadword aligned */
1744
    w.ashwhere = ap;
1745
    disp = rounder(disp,paral);
1746
    spar = FIRST_INT_ARG+ (disp>>6);
1747
    fpar = FIRST_FLOAT_ARG+ (disp>>6);
1748
    if (disp>448) {spar =22; fpar = 22; }
1749
    if (is_floating(hd) && disp+parsize <= 384) {
1750
      freg frg;
1751
      ans ansfr;
1752
      frg.fr = fpar++;
1753
      if(hd != shrealhd)
1754
	frg.type = IEEE_double;
1755
      else
1756
	frg.type = IEEE_single;
1757
      setfregalt (ansfr, frg);
1758
      w.answhere = ansfr;
1759
      code_here (list, sp, w);
1760
      /* evaluate parameter into floating parameter register */
1761
      sp = guardfreg(frg.fr, sp);
1762
    }
1763
    else if(((valregable(sh(list)) || (name(sh(list))==cpdhd)) ||
1764
	     (name(sh(list))==nofhd)) && spar<=21){	
1765
      /* compound types are always passed in registers
1766
	 (given enough space). */
1767
      ans ansr;
1768
      int par_reg;
1769
      int numleft = parsize-((LAST_INT_ARG-spar+1)<<6);
1770
      int pregs_used = min((numleft>>6)+6,6);
1771
      hadfixed=1;
1772
      setregalt(ansr,spar);
1773
      w.answhere=ansr;
1774
      for(par_reg=spar;par_reg<spar+pregs_used;++par_reg){
1775
	sp = guardreg(par_reg,sp);
1776
      }
1777
      sp = guardreg(spar,sp);
1778
      code_here(list,sp,w);
1779
      if(numleft>0){
1780
	is.b.offset+=(numleft>>3); /* += number of bytes remaining */
1781
      }
1782
    }
1783
    else {
1784
      /* pass remaining parameters on the stack.  
1785
	 The parameters are aligned on 8 byte boundaries. 
1786
	 */
1787
      setinsalt (w.answhere, is);
1788
      is.b.offset+=(max(ap.ashsize,REG_SIZE)>>3);	
1789
      /* 'size' was used here */
1790
      code_here (list, sp, w);
1791
      hadfixed = 1;
1792
      /* eval parameter into argument space on stack */
1793
    }	
1794
    if(name(list) == caller_tag) {
1795
      no(list) = disp;
1796
    }
1797
    disp+=parsize;
1798
    disp = rounder(disp, REG_SIZE);
1799
    *sizecallers = min(disp,NUM_PARAM_REGS*REG_SIZE);
1800
    if (last (list)) return sp;
1801
    list = bro (list);
1802
  } /* end for */
1803
  return sp;
1804
}
1805
 
1806
 
1807
void load_reg
1808
    PROTO_N ( ( e,r,sp ) )
1809
    PROTO_T ( exp e X int r X space sp )
1810
{
1811
  where w;
1812
  w.ashwhere = ashof(sh(e));
1813
  setregalt(w.answhere,r);
1814
  code_here(e,sp,w);
1815
  return;
1816
}
1817
 
1818
 
1819
 
1820
static postlude_chain * old_postludes;
1821
 
1822
void update_plc
1823
    PROTO_N ( ( chain,ma ) )
1824
    PROTO_T ( postlude_chain *chain X int ma )
1825
{
1826
  while(chain) {
1827
    exp pl = chain->postlude;
1828
    while (name(pl) == ident_tag && name(son(pl)) == caller_name_tag) {
1829
      no(pl) += (ma<<1);
1830
      pl = bro(son(pl));
1831
    }
1832
    chain = chain->outer;
1833
  }
1834
  return;
1835
}
1836
 
1837
 
1838
/*
1839
  This function finds the caller_tag corresponding to a caller_name tag
1840
*/
1841
exp find_ote
1842
    PROTO_N ( ( name,n ) )
1843
    PROTO_T ( exp name X int n )
1844
{
1845
  exp dad = father(name);
1846
  while(name(dad) != apply_general_tag) {
1847
    dad = father(dad);
1848
  }
1849
  dad = son(bro(son(dad)));
1850
  while(n) {
1851
    dad = bro(dad);
1852
    n -- ;
1853
  }
1854
  Assert(name(dad) == caller_tag);
1855
  return dad;
1856
}
1857
 
1858
 
1859
 
1860
/*
1861
  This function produces code for expression e, evaluating 
1862
  its result into dest.
1863
*/
1864
makeans make_code
1865
    PROTO_N ( ( e,sp,dest,exitlab ) )
1866
    PROTO_T ( exp e X space sp X where dest X int exitlab )
1867
{
1868
  INT64  constval;
1869
  makeans mka;
1870
  static int param_stack_space;
1871
  static int sizecallers = 0;
1872
tailrecurse: 
1873
  mka.lab = exitlab;
1874
  mka.regmove = NOREG;
1875
  clear_INT64(constval);
1876
 
1877
  switch (name (e)) {
1878
    case ident_tag : {
1879
      where placew;
1880
      int   r = NOREG;
1881
      bool remember = 0;
1882
      placew = nowhere;
1883
 
1884
      if (name (sh (son (e))) == ptrhd && name (son (e)) != cont_tag) {
1885
	/* We should never be identifing a pointer to bits */
1886
	if (al1(sh(son(e))) == 1) {
1887
#if 0
1888
	  failer ("Identify REF BITS");
1889
#endif
1890
	}	
1891
      }
1892
      if(is_param_reg(no(e)) && is32(sh(son(e))) && 
1893
	 name(son(e))!=formal_callee_tag){
1894
	operate_fmt_immediate(i_addl,no(e),0,no(e));
1895
      }
1896
      if (props (e) & defer_bit){
1897
	/* the tag of this declaration is
1898
	   transparently identified with its
1899
	   definition, without reserving more
1900
	   space */
1901
	e = bro (son (e));
1902
	goto tailrecurse;
1903
      }
1904
      if (son (e) == nilexp) {
1905
	placew = nowhere;	/* is this needed? */
1906
      }
1907
      else if(name(son(e)) == caller_name_tag){
1908
	exp ote = find_ote(e,no(son(e)));
1909
	int disp = no(ote);
1910
	if(in_vcallers_apply) {
1911
	  /* bit of a hack here */
1912
	  if(is_floating(name(sh(son(e))))) {
1913
	    no(e) = (((disp-sizecallers)>>3)<<4) + SP;
1914
	  }
1915
	  else {
1916
	    no(e) = (((disp - 6*PTR_SZ)>>3)<<4)+SP;
1917
	  }
1918
	}
1919
	else {
1920
	  no(e) = (((disp-sizecallers)>>3)<<4) + SP;
1921
	}
1922
	placew = nowhere;
1923
      }
1924
      else {
1925
	ash a;
1926
	int   n = no (e);
1927
	a = ashof (sh (son (e)));
1928
	if(is_param_reg(n) && (props(e)&inreg_bits) && proc_has_vararg){
1929
	  props(e) &= (~inreg_bits);
1930
	}
1931
	if (((props (e) & inreg_bits) != 0)) {
1932
	  /* tag in some fixed pt reg */
1933
	  if (n == NO_REG) {	
1934
	    /* if it hasn't been already allocated
1935
	       into a s-reg (or r0) allocate tag into
1936
	       fixed t-reg ... */
1937
	    int   s = sp.fixed;
1938
	    if (props (e) & notparreg)/* ... but not a parameter reg */
1939
	      s |= PARAM_REGS;
1940
	    n = getreg(s);
1941
	    no (e) = n;
1942
	  }
1943
	  setregalt (placew.answhere, n);
1944
	}
1945
	else if ((props (e) & infreg_bits) != 0) {
1946
	  /* tag in some float reg */
1947
	  freg frg;
1948
	  if (n == NO_REG) {	
1949
	    /* if it hasn't been already allocated
1950
	       into a s-reg (or r0) allocate tag into
1951
	       float-reg ... */
1952
	    int s = sp.flt;
1953
	    if (props (e) & notparreg)
1954
	      s |= 0xc0;
1955
	    n = getfreg (s);
1956
	    no (e) = n;
1957
	  }
1958
	  frg.fr = n;
1959
	  if(a.ashsize == 64)
1960
	    frg.type = IEEE_double;
1961
	  else
1962
	    frg.type = IEEE_single;
1963
	  setfregalt (placew.answhere, frg);
1964
	}
1965
	else if (isparam(e)) {
1966
	  if(name(son(e)) != formal_callee_tag){
1967
	    instore is;
1968
	    int this_reg=-1;
1969
	    int comp_size;
1970
	    /* floating point registers are to be separated 
1971
	       from fixed point registers when saving to the 
1972
	       stack  */
1973
	    int n;
1974
	    int offset_adjustment;
1975
	    if(proc_has_vararg && !is_floating(name(sh(son(e))))) {
1976
	      offset_adjustment = 6 * PTR_SZ;
1977
	    }
1978
	    else {
1979
	      offset_adjustment = arg_stack_space *8;
1980
	    }
1981
 
1982
	    if(Has_fp){
1983
	      n = (no(son(e))>>3) - (offset_adjustment>>3);
1984
	    }
1985
	    else{
1986
	      n=(((no(son(e))+frame_size+callee_size-offset_adjustment)>>3));
1987
	    }
1988
 
1989
	    if(props(son(e))){
1990
	      this_reg = (props(son(e))-16)<<6;
1991
	    }
1992
	    /* save all parameters in 64 bit chunks */
1993
	    /* Byte disp of params */
1994
	    is.b.offset = n;
1995
	    is.b.base = (Has_fp)?FP:SP;
1996
	    is.adval =1;
1997
	    setinsalt(placew.answhere, is);
1998
	    if(Has_fp){
1999
	      if(Has_no_vcallers || is_floating(name(sh(son(e))))){
2000
		no(e) = ((no(son(e))+frame_size+callee_size-locals_offset-
2001
			  (offset_adjustment))<<1)+FP;
2002
	      }
2003
	      else{
2004
		no(e) = ((no(son(e)) + frame_size + callee_size -locals_offset
2005
			  - (arg_stack_space<<3))<<1)+FP;
2006
		no(e) = ((no(son(e)) + frame_size + callee_size -locals_offset
2007
			  - (offset_adjustment))<<1)+FP;
2008
	      }
2009
	    }
2010
	    else{
2011
	      no(e)=((no(son(e))+frame_size+callee_size-locals_offset - 
2012
		      (offset_adjustment))<<1)+SP;
2013
	    }
2014
 
2015
	    if((a.ashsize>64) && (this_reg != -1)){
2016
	      for(comp_size=a.ashsize;(comp_size>0)&&(this_reg<384);
2017
				      comp_size -= 64){
2018
		load_store(i_stq,16+ (this_reg>>6),is.b);
2019
		this_reg+=64;
2020
		is.b.offset+=8;
2021
	      }
2022
				      /*props(son(e))=0;*/ /* ensures it wont be saved again */
2023
	    }
2024
	    if(proc_has_vararg && last_param(e) && (this_reg>=0)){
2025
	      /* attempt to detect vararg */
2026
	      int r = rounder(no(son(e))+shape_size(sh(son(e))), REG_SIZE);
2027
	      setinsalt(placew.answhere,is);
2028
	      for(r=this_reg;r<=320;r+=64){
2029
		/* no need to save first freg */
2030
		is.b.offset = ((r+paramsdumpstart)>>3) - 
2031
		  ((is.b.base == FP)?(frame_size>>3):0);
2032
		float_load_store(i_stt,16+(r>>6),is.b);
2033
	      }
2034
	      for(r=this_reg;r<=320;r+=64){
2035
		is.b.offset = ((r+gpdumpstart)>>3) - 
2036
		  ((is.b.base == FP)?(frame_size>>3):0);;
2037
		load_store(i_stq,16+(r>>6),is.b);
2038
	      }
2039
	      is.b.offset = n;	
2040
	    }
2041
	    else{
2042
	      if((name(sh(son(e)))==cpdhd)&&(a.ashsize==64)){
2043
		/* the alignment of a complex shape is the 
2044
		   maximum of the alignments of its components.  
2045
		   This assignment overrides that rule in order 
2046
		   to simplify saving the parameter to the stack.
2047
		   */
2048
		a.ashalign=a.ashsize;
2049
	      }	
2050
	      is.b.offset = n;	
2051
	    }
2052
	    setinsalt(placew.answhere, is);
2053
	    remember =1;
2054
	  }
2055
	  else{
2056
	    no(e) = ((no(son(e)) + frame_size - locals_offset)<<1)+
2057
	      ((Has_vcallees)?local_reg:FP);
2058
	    if(!Has_vcallees){
2059
	      no(e) -= (arg_stack_space<<4);
2060
	    }
2061
	    placew = nowhere;
2062
	  }
2063
	}
2064
	else {		/* allocate on stack */
2065
	  int   base = n & 0x3f;
2066
	  instore is;
2067
	  is.b.base = base;
2068
	  is.b.offset = (n - base) >> 4;
2069
	  is.adval = 1;
2070
	  if(base == SP){
2071
	    is.b.offset += locals_offset >> 3;
2072
	  }
2073
	  else if((base == FP && Has_fp)){
2074
#if 1
2075
	    is.b.offset += (((locals_offset-callee_size-frame_size)>>3)
2076
			    /*- ((in_general_proc)?0:arg_stack_space)*/);
2077
#else
2078
	    is.b.offset += (((locals_offset-callee_size-frame_size)>>3)
2079
			    -arg_stack_space);
2080
#endif
2081
	  }
2082
	  else if((base == local_reg && Has_vcallees)){
2083
	    is.b.offset += ((locals_offset-frame_size)>>3);
2084
	  }
2085
	  setinsalt(placew.answhere,is);
2086
	  remember = 1;
2087
	}
2088
 
2089
	placew.ashwhere = a;
2090
      }
2091
      if (isparam(e) && name(son(e)) != formal_callee_tag) {
2092
	exp se = son(e);
2093
	exp d = e;
2094
	/* parameter fiddles */
2095
	if (props(se) == 0 && (props(d) & inanyreg) !=0) {
2096
	  /* not originally in required reg */
2097
	  ans a;
2098
	  instore is;
2099
	  is.b.base = (Has_fp)?FP:SP;
2100
	  is.b.offset = ((no(se)-(arg_stack_space<<3)) + 
2101
	    ((Has_fp)?0:((callee_size+frame_size))))>>3;
2102
 
2103
 
2104
	  is.adval = 0;
2105
	  setinsalt(a, is);
2106
	  (void)move(a,placew, sp, name(sh(se)) & 1);
2107
	}
2108
	else if (props(se) !=0 && (props(d) & inanyreg) ==0) {
2109
	  /* originally in reg and required in store */
2110
	  ans a;
2111
	  if (is_floating(name(sh(se))) ) {
2112
	    freg fr;
2113
	    fr.fr = props(se);
2114
	    if(name(sh(se))!=shrealhd)
2115
	      fr.type = IEEE_double;
2116
	    else
2117
	      fr.type = IEEE_single;
2118
	    setfregalt(a, fr);
2119
	  }	
2120
	  else { setregalt(a, props(se)); }
2121
	  r = move(a, placew, sp, 0);
2122
	}
2123
	else if (props(se) !=0 && props(se) != no(d) ) {
2124
	  /* in wrong register */
2125
	  int sr = no(d);
2126
	  int tr = props(se);
2127
	  if (is_floating(name(sh(se))) ) {
2128
	    if ((fltdone & (1<<(sr))) != 0) {
2129
	      float_op( (name(sh(se)) != shrealhd) ? i_cpys: i_cpys,
2130
			(int)props(se),(int)(props(se)),no(d));
2131
	    }		
2132
	    else { 
2133
	      props(se) = sr; no(d)= tr;
2134
	      sp = guardfreg(tr, sp); 
2135
	      /* !? swopped and moved in  dump_tag !? */
2136
	    }
2137
	  }
2138
	  else {
2139
	    if ( (fixdone & (1<<sr)) !=0 ) {
2140
	      /*	      operate_fmt(i_bis,no(d),no(d),(int)props(se));*/
2141
	      operate_fmt(i_bis,(int)props(se),(int)props(se),no(d));
2142
	    }
2143
	    else {
2144
	      props(se) = sr; no(d)= tr;
2145
	      sp = guardreg(tr,sp);
2146
	      /* !? swapped for dump_tag !? */
2147
	    }
2148
	  }
2149
	}	
2150
	/* maybe more about promotions */          
2151
      }
2152
      else if(isparam(e) && name(son(e)) == formal_callee_tag){
2153
	exp se = son(e);
2154
	exp d = e;
2155
	if ((props(d) & inanyreg) != 0) {
2156
	  /* callee parameter assigned to reg */
2157
	  ans a;
2158
	  instore is;
2159
	  is.b.base = FP;
2160
	  is.b.offset = (no(se) - callee_size)>>3;
2161
	  is.adval = 0;
2162
	  setinsalt(a, is);
2163
	  (void)move(a, placew, sp, is_signed(sh(se)));
2164
	}	 
2165
      }
2166
      else{
2167
	r = code_here (son (e), sp, placew);
2168
	/* evaluate the initialisation of tag, putting it into place
2169
	   allocated ... */
2170
      }
2171
      if (remember && r != NOREG && pt (e) != nilexp
2172
	  && eq_sze (sh (son (e)), sh (pt (e)))) {
2173
	/* ...if it was temporarily in a register, remember it */
2174
	if (isvar (e)) {
2175
	  keepcont (pt (e), r);
2176
	}	
2177
	else {
2178
	  keepreg (pt (e), r);
2179
	}
2180
      }
2181
      sp =  guard (placew, sp);
2182
      e = bro (son (e));
2183
      goto tailrecurse;		        	
2184
      /* and evaluate the body of the declaration */
2185
    }					/* end ident */
2186
    case clear_tag : {
2187
      return mka;
2188
    }	
2189
    case seq_tag : {
2190
      exp t = son (son (e));
2191
      for (;;) {
2192
	exp next = (last (t)) ? (bro (son (e))) : bro (t);
2193
	if (name (next) == goto_tag) {/* gotos end sequences */
2194
	  make_code (t, sp, nowhere, no (son (pt (next))));
2195
	}	
2196
	else {
2197
	  code_here (t, sp, nowhere);
2198
	}
2199
	if (last (t)) {
2200
	  e = bro (son (e));
2201
	  goto tailrecurse;
2202
	}
2203
	t = bro (t);
2204
      }
2205
    }				/* end seq */
2206
    case cond_tag : {
2207
      exp first = son (e);
2208
      exp second = bro (son (e));
2209
      exp test;
2210
      exp record;
2211
      record = getexp(f_bottom,nilexp,0,nilexp,nilexp,0,0,0);
2212
#if DO_SCHEDULE && ENCAPSULATE_LABELS
2213
      start_new_capsule(true);
2214
#endif     
2215
      if (dest.answhere.discrim == insomereg) {
2216
	/* must make choice of register to contain answer to cond */
2217
	int  *sr = someregalt (dest.answhere);
2218
	if (*sr != -1) {
2219
	  failer ("Somereg *2");
2220
	}	
2221
	*sr = getreg (sp.fixed);
2222
	setregalt (dest.answhere, *sr);
2223
      }
2224
      else if (dest.answhere.discrim == insomefreg) {
2225
	somefreg sfr;
2226
	freg fr;
2227
	sfr = somefregalt(dest.answhere);
2228
	if (*sfr.fr != -1) { failer ("Somefreg *2"); }
2229
	*sfr.fr = getfreg(sp.flt);
2230
	fr.fr = *sfr.fr;
2231
	fr.type = sfr.type;
2232
	setfregalt(dest.answhere, fr);
2233
      }
2234
 
2235
      if (name (first) == goto_tag && pt (first) == second) {
2236
	/* first is goto second */
2237
	no (son (second)) = 0;
2238
	mka = make_code (second, sp, dest, exitlab);
2239
#if DO_SCHEDULE && ENCAPSULATE_LABELS
2240
	close_capsule();
2241
#endif       
2242
	return mka;
2243
      }	
2244
      else if (name (second) == labst_tag && 
2245
	       name (bro (son (second))) == top_tag) {
2246
	/* second is empty */
2247
	int   endl = (exitlab == 0) ? new_label () : exitlab;
2248
	no (son (second)) = endl;
2249
	make_code (first, sp, dest, endl);
2250
	mka.lab = endl;
2251
#if DO_SCHEDULE && ENCAPSULATE_LABELS
2252
	close_capsule();
2253
#endif
2254
	return mka;
2255
      }
2256
      else if (name (second) == labst_tag &&
2257
	       name (bro (son (second))) == goto_tag) {
2258
	/* second is goto */
2259
	exp g = bro (son (second));
2260
	no (son (second)) = no (son (pt (g)));
2261
	mka = make_code (first, sp, dest, exitlab);
2262
#if DO_SCHEDULE && ENCAPSULATE_LABELS
2263
	close_capsule();
2264
#endif	     
2265
	return mka;
2266
      }
2267
      if ((test = testlast (first, second)) /* I mean it */ ) {
2268
	/* effectively an empty then part */
2269
	int   l = (exitlab != 0) ? exitlab : new_label ();
2270
	bool rev = IsRev(test);
2271
	ptno(test) = -l;	/* make test jump to exitlab - see
2272
				   test_tag: */
2273
	props (test) = notbranch[(props (test)&127) - 1];
2274
	if (rev) { SetRev(test); }
2275
	/* ... with inverse test */
2276
	no (son (second)) = new_label ();
2277
	make_code (first, sp, dest, l);
2278
	make_code (second, sp, dest, l);
2279
	mka.lab = l;
2280
#if DO_SCHEDULE && ENCAPSULATE_LABELS
2281
	close_capsule();
2282
#endif	 
2283
	return mka;
2284
      }
2285
      else {
2286
	int   fl;
2287
	no (son (second)) = new_label ();
2288
	fl = make_code (first, sp, dest, exitlab).lab;
2289
	{
2290
	  int l = (fl != 0) ? fl : ((exitlab != 0) ? exitlab : new_label ());
2291
	  if(name(sh(first))!=bothd) integer_branch(i_br,31,l);
2292
	  make_code (second, sp, dest, l);
2293
	  clear_all ();
2294
	  mka.lab = l;
2295
#if DO_SCHEDULE && ENCAPSULATE_LABELS
2296
	  close_capsule();
2297
#endif		   
2298
	  return mka;
2299
	}
2300
      }
2301
    }				/* end cond */
2302
    case labst_tag : {
2303
      if (no (son (e)) != 0) {
2304
	set_label (no (son (e)));
2305
      }
2306
      if (is_loaded_lv(e) && No_S) { 
2307
	/* can be target of long_jump; reset sp */
2308
	baseoff b;
2309
	b.base = FP;
2310
	if(Has_vcallees){
2311
#if 0
2312
	  b.offset = -arg_stack_space-(3* (PTR_SZ>>3));
2313
#endif
2314
	  b.offset = -(3*(PTR_SZ>>3));
2315
	  load_store(i_ldq,local_reg,b);
2316
	}
2317
	if (Has_tos) {
2318
	  b.offset = -(PTR_SZ>>3)-(arg_stack_space);
2319
	  load_store(i_ldq,SP,b);
2320
	}
2321
	else {
2322
	  comment("labst_tag:");
2323
	  operate_fmt_immediate(i_subq,FP,(frame_size+callee_size)>>3,SP);
2324
	}
2325
      }			
2326
      e = bro (son (e));
2327
      goto tailrecurse;
2328
    }				/* end labst */
2329
    case rep_tag : {
2330
      exp first = son (e);
2331
      exp second = bro (first);
2332
#if DO_SCHEDULE && ENCAPSULATE_LABELS
2333
      /* start_new_capsule(true);*/
2334
#endif       
2335
      code_here(first,sp,nowhere);
2336
      no (son (second)) = new_label ();
2337
      /*e = second;*/
2338
      mka = make_code(second,sp,dest,exitlab);
2339
#if DO_SCHEDULE && ENCAPSULATE_LABELS
2340
/*       close_capsule();*/
2341
#endif
2342
      return mka;
2343
      /*goto tailrecurse;*/
2344
    }				/* end rep */
2345
    case goto_tag : {
2346
      int   lab = no (son (pt (e)));
2347
      clear_all ();
2348
      integer_branch(i_br,31,lab);
2349
      return mka;
2350
    }				/* end goto */
2351
    case make_lv_tag : {
2352
      int r = regfrmdest(&dest,sp);
2353
      ans aa;
2354
      load_store_label(i_lda,r,no(son(pt(e))));
2355
      setregalt(aa,r);
2356
      move(aa,dest, guardreg(r,sp), 0);
2357
      mka.regmove = r;
2358
      return mka;
2359
    }
2360
 
2361
    case long_jump_tag : {
2362
      int fp = reg_operand(son(e), sp);
2363
      int labval = reg_operand(bro(son(e)), sp);
2364
      comment("long jump");
2365
      operate_fmt(i_bis,fp,fp,FP);	/* move fp into FP */
2366
      /* load labval into register*/
2367
      integer_jump(i_jmp,31,labval,0);
2368
      return mka;
2369
    }
2370
    /*
2371
      max(x,y) and min(x,y)
2372
      */
2373
    case offset_max_tag :
2374
    case max_tag :
2375
    case min_tag :{
2376
      exp l = son(e);
2377
      exp r = bro(l);
2378
      int a1= reg_operand(l,sp);
2379
      int a2 = reg_operand(r,sp);
2380
      int d = regfrmdest(&dest,sp);
2381
      int rtmp = getreg(guardreg(d,sp).fixed);
2382
      ans aa;
2383
 
2384
      operate_fmt(i_bis,a1,a1,d);
2385
      operate_fmt(is_signed(sh(l))?i_cmplt:i_cmpult,a1,a2,rtmp);
2386
      if((name(e) == max_tag) || (name(e) == offset_max_tag)){
2387
	operate_fmt(i_cmovne,rtmp,a2,d);
2388
      }
2389
      else{
2390
	operate_fmt(i_cmoveq,rtmp,a2,d);
2391
      }
2392
      setregalt(aa,d);
2393
      (void)move(aa,dest,guardreg(d,sp),0);
2394
      mka.regmove=d;
2395
      return mka;
2396
    }
2397
 
2398
    case fmax_tag : {
2399
      exp l = son(e);
2400
      exp r = bro(l);
2401
      int a1 = freg_operand(l,sp);
2402
      int a2 = freg_operand(r,sp);
2403
      freg rd;
2404
      int rtmp;
2405
      ans aa;
2406
      rd = fregfrmdest(&dest,sp);
2407
      rtmp = getfreg(guardreg(rd.fr,sp).fixed);
2408
      float_op(i_cpys,a1,a1,rd.fr);
2409
      float_op(i_cmptlt,a1,a2,rtmp);
2410
      float_op(i_fcmovne,rtmp,a2,rd.fr);
2411
      setfregalt(aa,rd);
2412
      mka.regmove = move(aa,dest,guardfreg(rd.fr,sp),1);
2413
      return mka;
2414
    }
2415
 
2416
    case abslike_tag :{
2417
      /* if (test x) then res = -x, else res = x *
2418
	 The code produced for this construct is:
2419
	 move x to res, neg x -> y, cmov(test) x,y,res.
2420
	 If the test is unsigned then we can optimise certain 
2421
	 cases, i.e. less-than and greater-than-or-equal are
2422
	 always false and true respectively
2423
	 */
2424
      exp l = son(son(e));
2425
      shape shl = sh(l);
2426
      instruction cmove_ins;
2427
      space nsp;
2428
      int test_num;
2429
      int dest_reg;
2430
      int uns;
2431
      ans aa;
2432
      int a1,rtmp;
2433
      nsp = sp;
2434
      test_num = props(son(e));
2435
      dest_reg = regfrmdest(&dest,nsp);
2436
      mka.regmove = dest_reg;
2437
      setregalt(aa,dest_reg);
2438
      uns = !is_signed(shl);
2439
      nsp = guardreg(dest_reg,nsp);
2440
      a1 = reg_operand(l,nsp);
2441
      nsp = guardreg(dest_reg,nsp);
2442
      rtmp = getreg(nsp.fixed);
2443
      operate_fmt(i_bis,a1,a1,dest_reg);
2444
      cmove_ins = condmove(test_num);
2445
      operate_fmt(i_subq,31,a1,rtmp);
2446
      operate_fmt(cmove_ins,a1,rtmp,dest_reg);
2447
      move(aa,dest,guardreg(dest_reg,nsp),0);
2448
      return mka;
2449
    }
2450
 
2451
 
2452
 
2453
    case absbool_tag : 
2454
    /*case abslike_tag:*/{
2455
      /*
2456
	need to clear up the distinctions between comparison and
2457
	conditional move.
2458
	*/
2459
      exp l = son (son (e));
2460
      exp r = bro (l);
2461
      shape shl = sh (l);
2462
      instruction compare_ins;
2463
      int   n = props (son (e));
2464
      int   d;
2465
      int   a1;
2466
      int   a2;
2467
      bool xlike = (name(e) != absbool_tag);
2468
      ans aa;
2469
      bool uns = (!is_signed(shl));
2470
      if (!xlike && name (l) == val_tag) {
2471
	/* put literal operand on right */
2472
	exp temp = l;
2473
	l = r;
2474
	r = temp;
2475
	if (n <= 2) {
2476
	  n += 2;
2477
	}
2478
	else
2479
	  if (n <= 4) {
2480
	    n -= 2;
2481
	  }
2482
      }
2483
 
2484
      (void)compares(&compare_ins,shl,n);
2485
      d = regfrmdest(&dest, sp);
2486
 
2487
      /* reg d will contain result of compare */
2488
 
2489
      a1 = reg_operand (l, sp);
2490
      sp = guardreg(a1,sp);
2491
      if (xlike && a1==d) {
2492
	d = getreg(sp.fixed);
2493
      }
2494
      if (name (r) == val_tag) {
2495
	if((n==1)||(n==2)){
2496
	  int rt = getreg(guardreg(d,sp).fixed);
2497
	  if(no(r)){
2498
	    INT64 res;
2499
	    if(isbigval(r)){
2500
	      INT64_assign(res,flt64_to_INT64(exp_to_f64(r)));
2501
	      /*res=flt64_to_INT64(exp_to_f64(r));*/
2502
	    }
2503
	    else{
2504
	      INT64_assign(res,make_INT64(0,no(r)));
2505
	    }	
2506
	    load_store_immediate(i_ldiq,rt,res);
2507
	  }
2508
	  else
2509
	    rt=31;
2510
	  if(name(e)!=absbool_tag){
2511
	    int rtmp;
2512
	    if(uns){
2513
	      rtmp = getreg(sp.fixed);
2514
	      operate_fmt(compare_ins,rt,a1,rtmp);
2515
	    }
2516
	    else{
2517
	      rtmp = rt;
2518
	    }
2519
	    compare_ins=condmove(n);
2520
	    operate_fmt(i_bis,rtmp,rtmp,d);
2521
	    operate_fmt(compare_ins,a1,a1,d);
2522
	  }
2523
	  else
2524
	    operate_fmt(compare_ins,rt,a1,d);
2525
	}
2526
	else{
2527
	  if(isbigval(r)){
2528
	    operate_fmt_big_immediate(compare_ins,a1,
2529
				      flt64_to_INT64(exp_to_f64(r)),d);
2530
	  }
2531
	  else{
2532
	    operate_fmt_immediate(compare_ins,a1,no(r),d);
2533
	  }
2534
	}
2535
	if(n==6)	/* ? */
2536
	  operate_fmt(i_cmpeq,d,31,d);
2537
	/* invert the result */
2538
      }
2539
      else {
2540
	space nsp;
2541
	nsp = guardreg (a1, sp);
2542
	a2 = reg_operand (r, nsp);
2543
	if (xlike && a2==d) {
2544
	  nsp = guardreg(a2, nsp);
2545
	  d = getreg(nsp.fixed);
2546
	}
2547
	if((n==1)||(n==2))
2548
	  operate_fmt(compare_ins,a2,a1,d);
2549
	else
2550
	  operate_fmt(compare_ins,a1,a2,d);
2551
	if(n==6) operate_fmt(i_cmpeq,d,31,d);
2552
      }
2553
      if (name(e)==maxlike_tag || name(e)==minlike_tag) {
2554
	instruction ins;
2555
	int l = new_label();
2556
	setnoreorder();
2557
	ins=(name(e)==maxlike_tag)?i_bne:i_beq;
2558
	/*operate_fmt(i_addu, d, a1, 0);*/
2559
	integer_branch(ins,d,l);
2560
	if (name(r)==val_tag) { 
2561
	  INT64 v;
2562
	  low_INT64(v) = no(r);
2563
	  load_store_immediate(i_ldil,d,v);
2564
	}
2565
	else operate_fmt(i_bis,no(r),no(r),d);
2566
	set_label_no_clear(l);
2567
	setreorder();
2568
      }	
2569
      else
2570
	if (name(e)==abslike_tag) {
2571
	  int l1 = new_label();
2572
	  int l2 = new_label();
2573
	  setnoreorder();
2574
	  integer_branch(i_bne,d,l2);
2575
	  operate_fmt(i_subq, 31, a1, d);
2576
	  integer_branch(i_br,31,l1);
2577
	  set_label(l2);
2578
	  operate_fmt(i_bis,a1,a1,d);
2579
 
2580
	  set_label_no_clear(l1);
2581
	  setreorder();		
2582
	}			
2583
      setregalt (aa, d);
2584
      move (aa,dest, guardreg (d, sp), 0);
2585
      mka.regmove = d;
2586
      return mka;
2587
    }			/* end absbool */
2588
 
2589
 
2590
    case test_tag : {
2591
      /*
2592
	Tests are performed by either a comparison or subraction
2593
	instruction, followed by a conditional branch.  If the
2594
	test is unsigned, or if a subtraction could cause an
2595
	overflow, then comparisons must be used.
2596
	*/
2597
      exp l = son (e);
2598
      exp r = bro (l);
2599
      int   lab = (ptno (e) < 0) ? -ptno (e) : no (son (pt (e))); /* !! */
2600
      /* see frig in cond_tag */
2601
      shape shl = sh (l);
2602
      instruction test_ins;
2603
      int   n = (props (e)) & 127; /* could have Rev bit in props*/
2604
      bool rev;
2605
      bool is_compare = ((!is_signed(shl)) && ((n-5)<0) && 
2606
			 (name(shl)!=ptrhd))||((is64(shl)));
2607
      is_compare = TRUE;
2608
      if (is_floating (name (sh (l)))) {
2609
	instruction compare_ins;
2610
	space nsp;
2611
	int rev;
2612
	int a1,a2,dest;
2613
	a1 = freg_operand(l,sp);
2614
	nsp = guardfreg(a1,sp);
2615
	a2 = freg_operand(r,nsp);
2616
	dest = getfreg(nsp.flt);
2617
	rev = fdouble_comparisons(&compare_ins,n);
2618
	float_op(compare_ins,a1,a2,dest);
2619
	float_branch(rev?i_fbeq:i_fbne,dest,lab);
2620
	return mka;
2621
      }           
2622
      else {
2623
	int   a1;
2624
	int   a2;
2625
	if (name (l) == val_tag) {/* put literal operand on right */
2626
	  exp temp = l;
2627
	  l = r;
2628
	  r = temp;
2629
	  if (n <= 2) {
2630
	    n += 2;
2631
	  }
2632
	  else
2633
	    if (n <= 4) {
2634
	      n -= 2;
2635
	    }
2636
	}
2637
	if(is_compare){
2638
	  rev = comparisons(&test_ins,shl, n);
2639
	}
2640
	else{
2641
	  rev = 0;
2642
	  test_ins = sbranches(n);
2643
	}
2644
	a1 = reg_operand (l, sp);
2645
	if (name (r) == val_tag) {	
2646
	  space nsp;
2647
	  int rtemp;
2648
 
2649
	  switch(name(sh(r))){
2650
	    case ucharhd :{
2651
	      no(r) = (unsigned char)no(r);
2652
	      break;
2653
	    }
2654
	    case scharhd :{
2655
	      no(r) = (char)no(r);
2656
	      break;
2657
	    }
2658
	    case swordhd :{
2659
	      no(r) = (short)no(r);
2660
	      break;
2661
	    }
2662
	    case uwordhd :{
2663
	      no(r) = (unsigned short)no(r);
2664
	      break;
2665
	    }
2666
	  }
2667
 
2668
 
2669
	  if((no(r)!=0)||(isbigval(r))){
2670
	    nsp=guardreg(a1,sp);
2671
	    rtemp=getreg(nsp.fixed);
2672
	    if(is_compare){
2673
	      if(isbigval(r)){
2674
		operate_fmt_big_immediate(test_ins,a1,exp_to_INT64(r),rtemp);
2675
	      }
2676
	      else{
2677
		operate_fmt_immediate(test_ins,a1,no(r),rtemp);
2678
	      }
2679
	      integer_branch(rev?i_beq:i_bne,rtemp,lab);
2680
	    }
2681
	    else{
2682
	      if(name(shl)==ulonghd){
2683
		operate_fmt_immediate(i_addl,a1,0,a1);
2684
	      }
2685
	      if(isbigval(r)){
2686
		INT64 res = flt64_to_INT64(exp_to_f64(r));
2687
		operate_fmt_big_immediate(i_subq,a1,res,rtemp);
2688
	      }
2689
	      else{
2690
		operate_fmt_immediate(i_subq,a1,no(r),rtemp);
2691
	      }
2692
	      integer_branch(test_ins,rtemp,lab);	
2693
	    }
2694
	  }
2695
	  else{
2696
	    if(is_compare){
2697
	      int rtmp=getreg(guardreg(a1,sp).fixed);
2698
	      if(is_signed(shl)){
2699
		test_ins = sbranches(n);
2700
		integer_branch(test_ins,a1,lab);
2701
	      }
2702
	      else{
2703
		operate_fmt(test_ins,a1,31,rtmp);
2704
		integer_branch(rev?i_beq:i_bne,rtmp,lab);
2705
	      }
2706
	    }
2707
	    else{
2708
	      int dreg=a1;
2709
	      integer_branch(test_ins,dreg,lab);
2710
	    }
2711
	  }
2712
	}
2713
	else {
2714
	  space nsp;
2715
	  int rtemp;
2716
	  nsp = guardreg (a1, sp);
2717
	  a2 = reg_operand (r, nsp);
2718
	  if(a2!=31){
2719
	    rtemp=getreg(guardreg(a2,nsp).fixed);
2720
	    if(is_compare){
2721
	      operate_fmt(test_ins,a1,a2,rtemp);
2722
	      integer_branch(rev?i_beq:i_bne,rtemp,lab);
2723
	    }
2724
	    else{
2725
	      operate_fmt(is64(sh(son(e)))?i_subq:i_subl,a1,a2,
2726
			  rtemp);	
2727
	      integer_branch(test_ins,rtemp,lab);	
2728
	    }
2729
	  }
2730
	  else{
2731
	    test_ins = sbranches(n);
2732
	    integer_branch(test_ins,a1,lab);
2733
	  }
2734
	}
2735
	return mka;
2736
      }		  /* end int test */
2737
    }			/* end test */
2738
 
2739
    case ass_tag : 
2740
    case assvol_tag : {
2741
      exp lhs = son (e);
2742
      exp rhs = bro (lhs);
2743
      where assdest;
2744
      space nsp;
2745
      ash arhs;
2746
 
2747
      int   contreg = NOREG;
2748
      if (name (e) == assvol_tag) {
2749
	clear_all ();
2750
	/*setvolatile ();*/
2751
      }
2752
 
2753
      arhs = ashof (sh (rhs));
2754
 
2755
      if (name (e) == ass_tag && name (rhs) == apply_tag &&
2756
	  (is_floating (name (sh (rhs))) || valregable (sh (rhs)))) {
2757
	/* if source is simple proc call, evaluate it first and do
2758
	   assignment */
2759
	ans aa;
2760
	code_here (rhs, sp, nowhere);
2761
	if (is_floating (name (sh (rhs)))) {
2762
	  freg frg;
2763
	  frg.fr = 0;
2764
	  if(arhs.ashsize==64)
2765
	    frg.type = IEEE_double;
2766
	  else
2767
	    frg.type = IEEE_single;
2768
	  setfregalt (aa, frg);
2769
	}
2770
	else {
2771
	  setregalt (aa, RESULT_REG);
2772
	}
2773
	assdest = locate (lhs, guardreg(RESULT_REG,sp), sh (rhs), NO_REG);
2774
	move (aa,assdest, sp, 1);
2775
	move (aa,dest, sp, 1);
2776
	clear_dep_reg (lhs);
2777
	return mka;
2778
      }
2779
 
2780
/*	if (al1(sh(lhs)) == 1 || arhs.ashalign == 1)
2781
	clear_reg (0);*/
2782
 
2783
      assdest = locate (lhs, sp, sh (rhs), NO_REG);
2784
      nsp = guard (assdest, sp);
2785
      /* evaluate address of destination */
2786
 
2787
      if (assdest.ashwhere.ashalign == 1) {
2788
	/* this is an assignment of a bitfield, so get address 
2789
	   in proper form */
2790
	instore is;
2791
	switch (assdest.answhere.discrim) {
2792
	  case inreg : {
2793
	    is.b.base = regalt (assdest.answhere);
2794
	    is.b.offset = 0;
2795
	    is.adval = 1;
2796
	    break;
2797
	  }
2798
	  case notinreg : {
2799
	    is = insalt (assdest.answhere);
2800
	    if (!is.adval) {
2801
	      int   r = getreg (nsp.fixed);
2802
	      load_store(i_ldq,r,is.b);
2803
	      nsp = guardreg (r, nsp);
2804
	      is.adval = 1;
2805
	      is.b.base = r;
2806
	      is.b.offset = 0;
2807
	    }
2808
	    else {
2809
	      is.b.offset = is.b.offset << 3;
2810
	    }
2811
	    break;
2812
	  }
2813
#if 0
2814
	  case bitad : {
2815
	    is = bitadalt (assdest.answhere);
2816
	    break;
2817
	  }
2818
#endif
2819
	  default: 
2820
	  failer ("Wrong assbits");
2821
	}	
2822
/*	  setbitadalt (assdest.answhere, is);*/
2823
      }	
2824
      else if (name (e) == ass_tag
2825
	       && assdest.answhere.discrim == notinreg
2826
	       && assdest.ashwhere.ashsize == assdest.ashwhere.ashalign) {
2827
	instore is;
2828
	is = insalt (assdest.answhere);
2829
	if (!is.adval) {	
2830
	  /* this is an indirect assignment, so make
2831
	     it direct by loading pointer into a register
2832
	     (and remember it) */
2833
	  int   r = getreg (nsp.fixed);
2834
	  load_store(i_ldq,r,is.b);
2835
	  nsp = guardreg (r, nsp);
2836
	  is.adval = 1;
2837
	  is.b.base = r;
2838
	  is.b.offset = 0;
2839
	  setinsalt (assdest.answhere, is);
2840
	  keepexp (lhs, assdest.answhere);
2841
	}
2842
      }
2843
 
2844
      contreg = code_here (rhs, guard(assdest,nsp), assdest);
2845
      /* 
2846
	 evaluate source into assignment destination  
2847
	 and move it into dest - could use assignment as value 
2848
	 */
2849
 
2850
      switch (assdest.answhere.discrim) {
2851
	case inreg : {
2852
	  int   a = regalt (assdest.answhere);
2853
	  keepreg (rhs, a);
2854
	  /* remember that source has been evaluated into a */
2855
	  clear_dep_reg (lhs);
2856
	  /* forget register dependencies on destination */
2857
	  move (assdest.answhere,dest, nsp, 1);
2858
	  break;
2859
	}
2860
	case infreg :{
2861
	  freg frg;
2862
	  int   r;
2863
	  frg = fregalt (assdest.answhere);
2864
	  r = frg.fr + 32;
2865
	  if (frg.type==IEEE_double) {
2866
	    r = -r;
2867
	  };
2868
	  keepreg (rhs, r);
2869
	  /* remember that source has been evaluated into a */
2870
	  clear_dep_reg (lhs);
2871
	  /* forget register dependencies on destination */
2872
	  move (assdest.answhere,dest, nsp, 1);
2873
	  break;
2874
	}
2875
	case notinreg : /*case bitad: */{
2876
	  if (contreg != NOREG && name (e) == ass_tag) {
2877
	    ans aa;
2878
	    space nnsp;
2879
	    if (contreg > 0 && contreg < 31) {
2880
	      setregalt (aa, contreg);
2881
	      nnsp = guardreg (contreg, sp);
2882
	    }
2883
	    else {
2884
	      freg frg;
2885
	      frg.fr = abs (contreg) - 32;
2886
	      if(contreg<0)
2887
		frg.type = IEEE_double;
2888
	      else 
2889
		frg.type = IEEE_single;
2890
	      nnsp = nsp;
2891
	      setfregalt (aa, frg);
2892
	    }
2893
	    move (aa,dest, nnsp, 1);
2894
	    clear_dep_reg (lhs);
2895
	    /* forget register dependencies on destination */
2896
	    if (name (lhs) == name_tag || !dependson (lhs, 0, lhs)) {
2897
	      /* remember that dest contains source, 
2898
		 provided that it is not dependent on it */
2899
	      keepcont (lhs, contreg);
2900
	    }
2901
	    return mka;
2902
	  }
2903
	  clear_dep_reg (lhs);
2904
	  /* forget register dependencies on destination */
2905
	  move (assdest.answhere,dest, nsp, 1);
2906
	  break;
2907
	  case insomereg : case insomefreg : {
2908
	    clear_dep_reg (lhs);
2909
	    /* forget register dependencies on destination */
2910
	    move (assdest.answhere,dest, guard (assdest, sp), 1);
2911
	  }
2912
	}	
2913
      }			/* end sw on answhere */
2914
 
2915
/*	if (name (e) == assvol_tag)*/
2916
      /*setnovolatile ();*/
2917
      return mka;
2918
    }				/* end ass */
2919
 
2920
    case compound_tag : {
2921
      exp t = son (e);
2922
      space nsp;
2923
      instore str;
2924
      int r;
2925
 
2926
      nsp = sp;	
2927
      switch(dest.answhere.discrim) {
2928
	case notinreg : {
2929
	  str = insalt (dest.answhere);/* it should be !! */
2930
	  if (!str.adval) {
2931
	    int   r = getreg (sp.fixed);
2932
	    nsp = guardreg (r, sp);
2933
	    load_store(i_ldq,r,str.b);
2934
	    str.adval = 1;
2935
	    str.b.base = r;
2936
	    str.b.offset = 0;
2937
	  }	
2938
	  for (;;) {
2939
	    where newdest;
2940
	    instore newis;
2941
	    newis = str;
2942
	    newis.b.offset += no(t);
2943
	    Assert(name(t)==val_tag && al2(sh(t)) >= 8);
2944
	    setinsalt (newdest.answhere, newis);
2945
	    newdest.ashwhere = ashof (sh(bro(t)));
2946
	    code_here (bro(t), nsp, newdest);
2947
	    if (last (bro(t))) {
2948
	      return mka;
2949
	    }	
2950
	    t = bro (bro(t));
2951
	  }	
2952
	}
2953
	case insomereg : {
2954
	  int * sr = someregalt(dest.answhere);
2955
	  if (*sr != -1) {
2956
	    failer ("Somereg *2");
2957
	  }		
2958
	  *sr = getreg (sp.fixed);
2959
	  setregalt (dest.answhere, *sr);
2960
	}                  
2961
	FALL_THROUGH;
2962
	case inreg : {
2963
	  code_here(bro(t), sp, dest);
2964
	  r = regalt(dest.answhere);
2965
	  Assert(name(t)==val_tag);
2966
	  if (no(t) !=0) {
2967
	    operate_fmt_immediate(i_sll, r, 
2968
				  (al2(sh(t)) >= 8)? (no(t)<<3):no(t),r);
2969
	  }	
2970
	  nsp = guardreg(r, sp);
2971
	  while(!last(bro(t))) {
2972
	    int z;
2973
	    t = bro(bro(t));
2974
	    Assert(name(t)==val_tag);
2975
	    z = reg_operand(bro(t), nsp);
2976
	    if (no(t) !=0) {
2977
	      operate_fmt_immediate
2978
		(i_sll, z, (al2(sh(t)) >= 8)? (no(t)<<3):no(t),z );
2979
	    }		
2980
	    operate_fmt(i_bis, z, z, r);
2981
	  }	
2982
	  return mka;
2983
	}
2984
	default: failer("No Tuples in freg");
2985
      }
2986
      break;
2987
    }				/* end tup */
2988
 
2989
    case nof_tag : 
2990
    case concatnof_tag :{
2991
      exp t = son (e);
2992
      space nsp;
2993
      instore str;
2994
      int r, disp = 0;
2995
 
2996
      nsp = sp;	
2997
      switch(dest.answhere.discrim) {
2998
	case notinreg : {
2999
	  str = insalt (dest.answhere);	/* it should be !! */
3000
	  if (!str.adval) {
3001
	    int   r = getreg (sp.fixed);
3002
	    nsp = guardreg (r, sp);
3003
	    load_store(i_ldq,r,str.b);
3004
	    str.adval = 1;
3005
	    str.b.base = r;
3006
	    str.b.offset = 0;
3007
	  }
3008
	  for (;;) {
3009
	    where newdest;
3010
	    instore newis;
3011
	    if(t == nilexp) return mka;
3012
	    newis = str;
3013
	    newis.b.offset += disp;
3014
	    setinsalt (newdest.answhere, newis);
3015
	    newdest.ashwhere = ashof (sh(t));
3016
	    code_here (t, nsp, newdest);
3017
	    if (last (t)) {
3018
	      return mka;
3019
	    }
3020
	    disp+=(rounder(shape_size(sh(t)), shape_align(sh(bro(t))))>>3);
3021
	    t =bro(t);
3022
	  }
3023
	}
3024
	case insomereg : {
3025
	  int * sr = someregalt(dest.answhere);
3026
	  if (*sr != -1) {
3027
	    failer ("Somereg *2");
3028
	  }
3029
	  *sr = getreg (sp.fixed);
3030
	  setregalt (dest.answhere, *sr);
3031
	  /* ,... */
3032
	}                  
3033
	FALL_THROUGH;
3034
	case inreg : {
3035
	  if(t == nilexp) return mka;
3036
	  code_here(t, sp, dest);
3037
	  r = regalt(dest.answhere);
3038
	  nsp = guardreg(r, sp);
3039
	  while(!last(t)) {
3040
	    int z;
3041
	    disp+=rounder(shape_size(sh(t)), shape_align(sh(bro(t))));
3042
	    t =bro(t);
3043
	    z = reg_operand(t, nsp);
3044
	    operate_fmt_immediate(i_sll, z,disp,z );
3045
	    operate_fmt(i_bis, z, z, r);
3046
	  }
3047
	  return mka;
3048
	}
3049
	default: failer("No Tuples in freg");
3050
      }
3051
      break;
3052
    }
3053
 
3054
    case ncopies_tag :{
3055
      exp t = son (e);
3056
      space nsp;
3057
      instore str;
3058
      int i, r, disp = 0;
3059
      nsp = sp;	
3060
      switch(dest.answhere.discrim) {
3061
	case notinreg : {
3062
	  str = insalt (dest.answhere); /* it should be !! */
3063
	  if (!str.adval) {
3064
	    int   r = getreg (sp.fixed);
3065
	    nsp = guardreg (r, sp);
3066
	    load_store(i_ldq,r,str.b);
3067
	    str.adval = 1;
3068
	    str.b.base = r;
3069
	    str.b.offset = 0;
3070
	  }	
3071
	  for (i=1;i<=no(e); i++) {
3072
	    where newdest;
3073
	    instore newis;
3074
	    newis = str;
3075
	    newis.b.offset += disp;
3076
	    setinsalt (newdest.answhere, newis);
3077
	    newdest.ashwhere = ashof (sh(t));
3078
	    code_here (t, nsp, newdest);
3079
	    disp+=(rounder(shape_size(sh(t)), shape_align(sh(t)))>>3);
3080
	  }	
3081
	  return mka;
3082
	}
3083
	case insomereg : {
3084
	  int * sr = someregalt(dest.answhere);
3085
	  if (*sr != -1) {
3086
	    failer ("Somereg *2");
3087
	  }		
3088
	  *sr = getreg (sp.fixed);
3089
	  setregalt (dest.answhere, *sr);
3090
	}                  
3091
	FALL_THROUGH;
3092
	case inreg: {
3093
	  code_here(t, sp, dest);
3094
	  r = regalt(dest.answhere);
3095
	  nsp = guardreg(r, sp);
3096
	  for(i=1; i<=no(e); i++) {
3097
	    int z;
3098
	    disp+=rounder(shape_size(sh(t)), shape_align(sh(t)));
3099
	    z = reg_operand(t, nsp);
3100
	    operate_fmt_immediate(i_sll, z,disp,z);
3101
	    operate_fmt(i_bis, z, z, r);
3102
	  }	
3103
	  return mka;
3104
	}
3105
	default: failer("No Tuples in freg");
3106
      }
3107
      break;
3108
    }           
3109
    case apply_tag :{
3110
      exp fn = son (e);
3111
      exp par = bro (fn);
3112
      exp list = par;
3113
      int   hda = name (sh (e));
3114
      int   disp;
3115
      int   spar;
3116
      int   fpar = 16;
3117
      ash ansash;
3118
      bool hadfixed;
3119
      instore is;
3120
      is.b.base = SP;
3121
      is.b.offset = 0;
3122
      is.adval = 1;
3123
 
3124
#ifdef DO_SPECIAL
3125
      if ((disp = specialfn (fn)) > 0) { /* eg function is strlen */
3126
	mka.lab = specialmake (disp, list, sp, dest, exitlab);
3127
	return mka;
3128
 
3129
      }
3130
#endif
3131
      ansash = ashof (sh (e));
3132
      disp = 0;
3133
      spar = FIRST_INT_ARG;/* register holding 1st integer parameter */
3134
      hadfixed = 0;
3135
 
3136
 
3137
      if (!last(fn)) {
3138
	for (;;) {		/* evaluate parameters in turn */
3139
	  int   hd = name (sh (list));
3140
	  where w;
3141
	  ash ap;
3142
	  int paral;
3143
	  int parsize;
3144
	  ap = ashof (sh (list));
3145
	  paral = (ap.ashalign < 32)?32:ap.ashalign;
3146
	  if(spar>21){
3147
	    ap.ashalign=64;
3148
	    paral = 64;
3149
	  }
3150
	  parsize = ap.ashsize;
3151
	  /* all parameters passed on stack are quadword aligned */
3152
	  w.ashwhere = ap;
3153
	  disp = rounder(disp,paral);
3154
	  spar = FIRST_INT_ARG+ (disp>>6);
3155
	  fpar = FIRST_FLOAT_ARG+ (disp>>6);
3156
	  if (disp>448) {spar =22; fpar = 22; }
3157
	  if (is_floating(hd) && disp+parsize <= 384) {
3158
	    freg frg;
3159
	    ans ansfr;
3160
	    frg.fr = fpar++;
3161
	    if(hd != shrealhd)
3162
	      frg.type = IEEE_double;
3163
	    else
3164
	      frg.type = IEEE_single;
3165
	    setfregalt (ansfr, frg);
3166
	    w.answhere = ansfr;
3167
	    code_here (list, sp, w);
3168
	    /* eval parameter into floating parameter register */
3169
	    sp = guardfreg(frg.fr, sp);
3170
	  }
3171
	  else if(((valregable(sh(list)) || (name(sh(list))==cpdhd)) ||
3172
		   (name(sh(list))==nofhd)) && spar<=21){	
3173
	    /* compound types are always passed in registers
3174
	       (given enough space). */
3175
	    ans ansr;
3176
	    int par_reg;
3177
	    int numleft = parsize-((LAST_INT_ARG-spar+1)<<6);
3178
	    int pregs_used = min((numleft>>6)+6,6);
3179
	    hadfixed=1;
3180
	    setregalt(ansr,spar);
3181
	    w.answhere=ansr;
3182
	    for(par_reg=spar;par_reg<spar+pregs_used;++par_reg){
3183
	      sp = guardreg(par_reg,sp);
3184
	    }
3185
 
3186
 
3187
	    sp = guardreg(spar,sp);
3188
	    code_here(list,sp,w);
3189
	    if(numleft>0){
3190
	      is.b.offset+=(numleft>>3); /* += number of bytes remaining */
3191
	    }
3192
	  }
3193
	  else {
3194
	    /* pass remaining parameters on the stack.  
3195
	       The parameters are aligned on 8 byte boundaries. 
3196
	       */
3197
	    setinsalt (w.answhere, is);
3198
	    is.b.offset+=(max(ap.ashsize,REG_SIZE)>>3);	
3199
	    /* 'size' was used here */
3200
	    code_here (list, sp, w);
3201
	    hadfixed = 1;
3202
	    /* eval parameter into argument space on stack */
3203
	  }	
3204
	  if(name(list) == caller_tag){
3205
	    no(list) = disp;
3206
	  }
3207
	  disp+=parsize;
3208
	  disp = rounder(disp, REG_SIZE);
3209
 
3210
 
3211
	  if (last (list)) break;
3212
	  list = bro (list);
3213
	} /* end for */
3214
      } /* end if list */
3215
 
3216
      if (name (fn) == name_tag && name (son (fn)) == ident_tag
3217
	  && (son (son (fn)) == nilexp || name (son (son (fn))) == proc_tag)) {
3218
	/* the procedure can be entered directly */
3219
	if (			/*!tlrecurse*/1) {
3220
	  baseoff a;
3221
	  integer_jump_external(i_jsr,26,boff(son(fn)));
3222
	  a.base = RA;
3223
	  a.offset=0;
3224
	  load_store(i_ldgp,GP,a);
3225
	} 
3226
	else {
3227
	  if (Has_fp) {
3228
	    baseoff b;
3229
	    b.base = FP;
3230
	    b.offset = (frame_size+ callee_size)>>3;
3231
	    restore_sregs(fixdone, fltdone);
3232
	    operate_fmt(i_bis,FP,FP,SP);
3233
	    load_store(i_ldq,FP,b);
3234
	  }	
3235
	  else {
3236
	    baseoff b;
3237
	    b.base=SP;
3238
	    b.offset=(frame_size+callee_size)>>3;
3239
 
3240
	    restore_sregs(fixdone, fltdone);
3241
	    load_store(i_lda,SP,b);
3242
	  }	
3243
	  integer_jump_external(i_jmp,31,boff(son(fn)));
3244
	  if(as_file){
3245
	    fprintf(as_file," # Tail recursion\n"); 
3246
	  }
3247
 
3248
	}	
3249
      }
3250
      else {			/* the address of the proc is evaluated
3251
				   and entered indirectly */
3252
	int destreg=reg_operand(fn,guardreg(26,sp));
3253
	operate_fmt(i_bis,destreg,destreg,PV);
3254
	integer_jump(i_jsr,RA,destreg,0);
3255
	load_store(i_ldgp,GP,procbase);
3256
      }
3257
      if(in_general_proc) {
3258
	/* Temporary */
3259
	/*	operate_fmt_immediate(i_addq,SP,(callee_size+frame_size)>>3,FP);*/
3260
      }
3261
      clear_all ();		/* forget all register memories */
3262
      {
3263
	ans aa;
3264
	if (is_floating (hda)) {
3265
	  freg frg;
3266
	  frg.fr = 0;
3267
	  if(hda != shrealhd)
3268
	    frg.type = IEEE_double;
3269
	  else
3270
	    frg.type = IEEE_single;
3271
	  setfregalt (aa, frg);
3272
	  move (aa,dest, sp, 1);
3273
	  /* move floating point result of application 
3274
	     to destination */
3275
	}
3276
	else {
3277
	  setregalt (aa, RESULT_REG);
3278
	  mka.regmove = 0;
3279
	  move (aa,dest, sp, 1);
3280
	  /* move floating point result of application to 
3281
	     destination */
3282
	}
3283
	/* else struct results are moved by body of proc */
3284
      }
3285
      return mka;
3286
    }				/* end apply */
3287
    case caller_tag : {
3288
      e = son(e);
3289
      goto tailrecurse;
3290
    }
3291
 
3292
    case apply_general_tag : {
3293
      exp fn = son(e);
3294
      exp callers = bro(fn);
3295
      exp cllees = bro(callers);
3296
      exp postlude = bro(cllees);
3297
      space nsp;
3298
      int postlude_arg_space;
3299
      nsp = sp;
3300
      if (no(callers) != 0){
3301
	nsp = do_callers(son(callers),sp,&sizecallers);
3302
      }
3303
      else {
3304
	sizecallers = 0;
3305
      }
3306
 
3307
      if((in_vcallers_apply = call_has_vcallers(cllees))) {
3308
	sizecallers = 12 * REG_SIZE;
3309
      }
3310
      else {
3311
	sizecallers = 6 * REG_SIZE;
3312
      }
3313
 
3314
      (void)make_code(cllees,nsp,nowhere,0);
3315
      if(name(fn) == name_tag && name(son(fn)) == ident_tag &&
3316
	 (son(son(fn)) == nilexp || name(son(son(fn))) == proc_tag ||
3317
	  name(son(son(fn))) == general_proc_tag)){
3318
	baseoff a;
3319
	a.base = RA;
3320
	a.offset = 0;
3321
	integer_jump_external(i_jsr,26,boff(son(fn)));
3322
	load_store(i_ldgp,GP,a);
3323
      }
3324
      else{
3325
	if (Has_fp) {
3326
	  baseoff b;
3327
	  b.base = FP;
3328
	  b.offset = (frame_size+callee_size)>>3;
3329
	  b.offset = -8;
3330
	}	
3331
	else {
3332
	  baseoff b;
3333
	  b.base=SP;
3334
	}	
3335
	integer_jump_fn(i_jmp,31,fn,sp);
3336
      }
3337
      clear_all();
3338
      {
3339
	int hda = name(sh(e));
3340
	ans aa;
3341
	if (is_floating (hda)) {
3342
	  freg frg;
3343
	  frg.fr = 0;
3344
	  if(hda != shrealhd)
3345
	    frg.type = IEEE_double;
3346
	  else
3347
	    frg.type = IEEE_single;
3348
	  setfregalt (aa, frg);
3349
	  move (aa,dest, sp, 1);
3350
	  /* move floating point result of application 
3351
	     to destination */
3352
	}
3353
	else {
3354
	  setregalt (aa, RESULT_REG);
3355
	  mka.regmove = RESULT_REG;
3356
	  move (aa,dest, sp, 1);
3357
	  /* move floating point result of application to destination */
3358
	}
3359
	/* else struct results are moved by body of proc */
3360
      }
3361
      if(in_vcallers_apply) {
3362
	postlude_arg_space = max(max_args,sizecallers);
3363
      }
3364
      else {
3365
	postlude_arg_space = max(max_args,6*PTR_SZ);
3366
      }
3367
 
3368
      if(call_is_untidy(cllees)) {
3369
	operate_fmt_immediate(i_subq,SP,postlude_arg_space>>3,SP);
3370
	reset_tos();
3371
	Assert(name(bro(cllees)) == top_tag);
3372
      }
3373
      else if(postlude_has_call(e)){
3374
	exp x = son(callers);
3375
	postlude_chain p;
3376
	for(;;) {
3377
	  if(name(x) == caller_tag) {
3378
	    no(x) += postlude_arg_space;
3379
	  }
3380
	  if(last(x))break;
3381
	  x = bro(x);
3382
	}
3383
	comment("In postlude, with call");
3384
	/*	operate_fmt_immediate(i_subq,SP,max_args>>3,SP);*/
3385
 
3386
	mka.regmove = NOREG;
3387
	update_plc(old_postludes,postlude_arg_space);
3388
	p.postlude = postlude;
3389
	p.outer = old_postludes;
3390
	old_postludes = &p;
3391
	operate_fmt_immediate(i_subq,SP,postlude_arg_space>>3,SP);
3392
	(void)make_code(postlude,sp,nowhere,0);
3393
	operate_fmt_immediate(i_addq,SP,postlude_arg_space>>3,SP);
3394
	old_postludes = p.outer;
3395
	update_plc(old_postludes,-postlude_arg_space);
3396
      }
3397
      else {
3398
	(void)make_code(postlude,sp,nowhere,0);
3399
      }
3400
      in_vcallers_apply = 0;
3401
      return mka;
3402
    }
3403
    case caller_name_tag : {
3404
      return mka;
3405
    }
3406
    case make_callee_list_tag : {
3407
      int size  = ((no(e)>>3) + 39) & ~7;
3408
      int alloc_size;
3409
      bool vc = call_has_vcallees(e);
3410
      exp list = son(e);
3411
      instore is;
3412
      where w;
3413
      baseoff b;
3414
      int disp=0;
3415
      ash ap;
3416
      exp anc = father(e);
3417
      if(call_has_vcallers(e)){
3418
	alloc_size = size + (12 * (PTR_SZ>>3));
3419
	sizecallers = (12*(PTR_SZ));
3420
      }
3421
      else{
3422
	alloc_size = size + ((name(anc)==tail_call_tag)?(6*PTR_SZ>>3):
3423
			     (sizecallers>>3));
3424
      }
3425
      b.base = SP;
3426
      operate_fmt_immediate(i_subq,SP,alloc_size,SP);
3427
 
3428
      if(name(anc) == tail_call_tag) {
3429
	/*b.offset = alloc_size - (PTR_SZ>>3) - arg_stack_space;*/
3430
	b.offset = alloc_size - (PTR_SZ>>3);
3431
	load_store(i_stq,FP,b);
3432
      }
3433
      else {
3434
	b.offset = alloc_size -(PTR_SZ>>3) - (sizecallers>>3);
3435
	load_store(i_stq,FP,b);
3436
      }
3437
#if 0      
3438
      if(!Has_fp)
3439
	operate_fmt_immediate(i_addq,SP,size,FP);
3440
#endif
3441
      update_plc(old_postludes,alloc_size<<3);
3442
      if(no(e)){
3443
	int lastpar = 0;
3444
	for(;!lastpar;list =  bro(list)){
3445
	  ap = ashof(sh(list));
3446
	  disp = rounder(disp,ap.ashalign);
3447
	  is.b.offset = disp>>3;
3448
	  is.b.base = SP;
3449
	  is.adval = 1;
3450
	  w.ashwhere = ap;
3451
	  setinsalt(w.answhere,is);
3452
	  code_here(list,sp,w);
3453
	  disp = rounder(disp+ap.ashsize,PTR_SZ);
3454
/*	disp = rounder(disp+ap.ashsize,is32(sh(list))?32:64);*/
3455
	  lastpar = last(list);
3456
	}
3457
      }
3458
      update_plc(old_postludes,-alloc_size<<3);
3459
#if 1
3460
      if(vc  && (name(anc) == apply_general_tag)){
3461
	operate_fmt_immediate(i_addq,SP,alloc_size,FP); 
3462
      }
3463
#endif
3464
      return mka;
3465
    }
3466
 
3467
    case same_callees_tag : {
3468
      baseoff b;
3469
      bool vc = call_has_vcallees(e);
3470
      space nsp;
3471
      if(Has_vcallees){
3472
	int rsize = getreg(sp.fixed);
3473
	int rsrc,rdest;
3474
	int le = new_label();
3475
	int lb = new_label();
3476
	int tmp;
3477
	nsp = guardreg(rsize,sp);
3478
	tmp = getreg(nsp.fixed);
3479
	nsp = guardreg(tmp,nsp);
3480
	rsrc = getreg(nsp.fixed);
3481
	nsp = guardreg(rsrc,nsp);
3482
	rdest = getreg(nsp.fixed);
3483
	nsp = guardreg(rdest,nsp);
3484
	operate_fmt(i_bis,SP,SP,tmp);
3485
	operate_fmt(i_subq,FP,local_reg,rsize);
3486
	if(!Has_no_vcallers && !call_has_vcallers(e)) {
3487
	  operate_fmt_immediate(i_subq,rsize,6*PTR_SZ>>3,rsize);
3488
	}
3489
 
3490
 
3491
	if((sizecallers>>3)>arg_stack_space) {
3492
	  operate_fmt_immediate(i_addq,rsize,
3493
				((sizecallers>>3)-arg_stack_space),rsize);
3494
	}
3495
	operate_fmt(i_subq,SP,rsize,SP);
3496
	b.base = tmp;
3497
	b.offset = -(PTR_SZ>>3) - (sizecallers>>3);
3498
	load_store(i_stq,FP,b);
3499
	operate_fmt_immediate(i_subq,FP,4*(PTR_SZ>>3)+(arg_stack_space),
3500
			      rsrc);
3501
	operate_fmt_immediate(i_subq,tmp,(4*(PTR_SZ>>3))+(sizecallers>>3),
3502
			      rdest);
3503
 
3504
	setnoat();
3505
	operate_fmt(i_cmpeq,rdest,SP,AT);
3506
	integer_branch(i_bne,AT,le);
3507
	setat();
3508
	set_label(lb);
3509
	b.base = rsrc;
3510
	b.offset = -(PTR_SZ>>3);
3511
	load_store(i_ldq,rsize,b);
3512
	b.base = rdest;
3513
	load_store(i_stq,rsize,b);
3514
	operate_fmt_immediate(i_subq,rsrc,PTR_SZ>>3,rsrc);
3515
	operate_fmt_immediate(i_subq,rdest,PTR_SZ>>3,rdest);
3516
	setnoat();
3517
	operate_fmt(i_cmpeq,rdest,SP,AT);
3518
	integer_branch(i_beq,AT,lb);
3519
	setat();
3520
	set_label(le);
3521
	if(vc) operate_fmt(i_bis,tmp,tmp,FP);
3522
      }
3523
      else{
3524
	int cs = callee_size>>3;
3525
	int i;
3526
	int tr = getreg(sp.fixed);
3527
	operate_fmt_immediate(i_subq,SP,cs + (sizecallers>>3),SP);
3528
	b.base = SP;
3529
	b.offset = cs - (PTR_SZ>>3) /*-arg_stack_space*//*-(sizecallers>>3)*/;
3530
	load_store(i_stq,FP,b);
3531
	for(i=cs - (4*8);i>0;i -= 8){
3532
	  b.base = FP;
3533
	  b.offset = i -cs -8 - (arg_stack_space);
3534
	  load_store(i_ldq,tr,b);
3535
	  b.base = SP;
3536
	  b.offset = i - 8;
3537
	  load_store(i_stq,tr,b);
3538
	}
3539
	if(vc) operate_fmt_immediate(i_addq,SP,cs + (sizecallers>>3),FP);
3540
      }
3541
      return mka;
3542
    }
3543
    case make_dynamic_callee_tag : {
3544
      bool vc = call_has_vcallees(e);
3545
      exp anc = father(e);
3546
      int extra_space;
3547
      int rptr,rsize,rdest,tempreg,ls,le;
3548
      space nsp;
3549
      baseoff b;
3550
      extra_space = (name(anc) == apply_general_tag)?(sizecallers>>3):
3551
	arg_stack_space;
3552
      rptr = getreg(sp.fixed);
3553
      load_reg(son(e),rptr,sp);
3554
      nsp = guardreg(rptr,sp);
3555
      rsize = getreg(nsp.fixed);
3556
      load_reg(bro(son(e)),rsize,sp);
3557
      nsp = guardreg(rsize,nsp);
3558
      rdest = getreg(nsp.fixed);
3559
      nsp = guardreg(rdest,nsp);
3560
      tempreg = getreg(nsp.fixed);
3561
      operate_fmt_immediate(i_addq,rsize,(4*(PTR_SZ>>3)+extra_space)+7,rdest);
3562
      operate_fmt_immediate(i_bic,rdest,7,rdest);
3563
      b.base = SP;
3564
      b.offset = -(PTR_SZ>>3) - (sizecallers>>3);
3565
      load_store(i_stq,FP,b);
3566
      if(vc) operate_fmt(i_bis,SP,SP,FP);
3567
      operate_fmt(i_subq,SP,rdest,SP);
3568
      operate_fmt(i_bis,SP,SP,rdest);
3569
      ls = new_label();
3570
      le = new_label();
3571
      integer_branch(i_ble,rsize,le);
3572
      b.offset = 0;
3573
      set_label(ls);
3574
      b.base = rptr;
3575
      load_store(i_ldq,tempreg,b);
3576
      b.base = rdest;
3577
      load_store(i_stq,tempreg,b);
3578
      operate_fmt_immediate(i_addq,rdest,(PTR_SZ>>3),rdest);
3579
      operate_fmt_immediate(i_addq,rptr,(PTR_SZ>>3),rptr);
3580
      operate_fmt_immediate(i_subq,rsize,(PTR_SZ>>3),rsize);
3581
      integer_branch(i_bgt,rsize,ls);
3582
      set_label(le);
3583
      return mka;
3584
    }
3585
 
3586
    case tail_call_tag : {
3587
      exp fn = son(e);
3588
      exp cllees = bro(fn);
3589
      exp bdy = son(crt_proc);
3590
      int stack_space;
3591
      int rsize = -1;
3592
      space nsp;
3593
      nsp = sp;
3594
      stack_space = max(arg_stack_space,6*(PTR_SZ>>3));
3595
 
3596
      if(name(cllees) == make_callee_list_tag){
3597
	code_here(cllees,sp,nowhere);
3598
      }
3599
      for(;name(bdy)==dump_tag || name(bdy)==diagnose_tag;bdy = son(bdy));
3600
 
3601
      while(name(bdy) == ident_tag && isparam(bdy)) {
3602
	/* go throught the current callers, making sure they are 
3603
	   in the right place */
3604
	exp sbody = son(bdy);
3605
	baseoff b;
3606
	if(Has_fp) {
3607
	  b.base = FP;
3608
	  b.offset = (no(sbody)>>3) - stack_space;
3609
	}
3610
	else {
3611
	  b.base = SP;
3612
	  b.offset = (no(sbody) + frame_size + callee_size)>>3;
3613
	}
3614
#if 0	
3615
 
3616
 
3617
	b.base = FP;
3618
	b.offset = (no(sbody)>>3) - (PTR_SZ>>3)  ;  /* This will work its 
3619
						       way through the 
3620
						       caller param area */
3621
	b.offset = no(sbody)>>3;
3622
#endif
3623
 
3624
	if(name(sbody) == formal_callee_tag) {
3625
	  if((props(bdy) & inanyreg)) {
3626
	    b.offset -= callee_size>>3;
3627
	    if(isvar(bdy)) {
3628
	      if(is_floating(name(sh(sbody)))) {
3629
		float_load_store((name(sh(sbody)) == shrealhd)?i_sts : i_stt,
3630
				 no(bdy),b);
3631
	      }
3632
	      else {
3633
		load_store(is64(sh(sbody))?i_stq : i_stl,no(bdy),b);
3634
	      }
3635
	    }
3636
	  }
3637
	}
3638
	else if(props(sbody)==0 && (props(bdy)&inanyreg)!=0){
3639
	  /* move from reg to store */
3640
	  if(isvar(bdy)){
3641
	    if(is_floating(name(sh(sbody)))){
3642
	      float_load_store((name(sh(sbody))==shrealhd)?i_sts:i_stt,
3643
			       no(bdy),b);
3644
	    }
3645
	    else{
3646
	      load_store(is64(sh(sbody))?i_stq:i_stl,props(sbody),b);
3647
	    }
3648
	  }
3649
	}
3650
	else if(props(sbody)!= 0 && (props(bdy) & inanyreg)==0){
3651
	  /* move from store to reg */
3652
	  if(is_floating(name(sh(sbody)))){
3653
	    float_load_store((name(sh(sbody))==shrealhd)?i_lds:i_ldt,
3654
			     props(sbody),b);
3655
	  }
3656
	  else{
3657
	    if(isvis(bdy) && last_param(bdy) && !Has_no_vcallers) {
3658
	      int this_reg = props(sbody);
3659
	      int r;
3660
	      Assert(this_reg>=16);
3661
	      b.offset = ((this_reg+1-16)<<3)+((gpdumpstart - frame_size)>>3);
3662
	      for(r = this_reg+1;r <= LAST_INT_ARG;++r) {
3663
		load_store(i_ldq,r,b);
3664
		b.offset += (REG_SIZE>>3);
3665
	      }
3666
	      b.offset = ((paramsdumpstart-frame_size)>>3);
3667
	      for(r = FIRST_FLOAT_ARG;r<= LAST_FLOAT_ARG;++r) {
3668
		float_load_store(i_ldt,r,b);
3669
		b.offset += (REG_SIZE>>3);
3670
	      }
3671
	      b.offset = ((this_reg-16)<<3) +((gpdumpstart-frame_size)>>3);
3672
	      load_store(is64(sh(sbody))?i_ldq:i_ldl,props(sbody),b);
3673
	    }
3674
	    else {
3675
	      load_store(is64(sh(sbody))?i_ldq:i_ldl,props(sbody),b);
3676
	    }
3677
 
3678
	  }
3679
	}
3680
	else if(props(sbody)!=0 && (props(sbody) != no(bdy))){
3681
	  /* move from reg to reg */
3682
	  if(is_floating(name(sh(sbody)))){
3683
	    float_op(i_cpys,no(bdy),no(bdy),props(sbody));
3684
	  }
3685
	  else{
3686
	    operate_fmt(i_bis,no(bdy),no(bdy),props(sbody));
3687
	  }
3688
	}
3689
	bdy = bro(sbody);
3690
      }
3691
      restore_sregs(fixdone,fltdone);
3692
 
3693
      /*
3694
	Allocate space on the frame for the number of callees used 
3695
	in the tail call which exceed the number of callees for 
3696
	this procedure 
3697
	*/
3698
      if(name(cllees) == make_callee_list_tag){
3699
	int x = (((no(cllees) >> 3) + 39) & ~7) + stack_space;
3700
	baseoff b;
3701
	int i;
3702
	int rndcllees = ((no(cllees)>>3)+7)&~7;
3703
	setnoat();
3704
	for(i=no(cllees)>>3;i>0;i -= (PTR_SZ>>3)){
3705
	  b.base = SP;
3706
	  b.offset = i - (PTR_SZ>>3);
3707
	  load_store(i_ldq,AT,b);
3708
	  b.base = FP;
3709
	  b.offset = i-(4*(PTR_SZ>>3)) - (rndcllees + (PTR_SZ>>3)) 
3710
	    - stack_space;
3711
	  load_store(i_stq,AT,b);
3712
	}
3713
	setat();
3714
	operate_fmt_immediate(i_subq,FP,x,SP);
3715
      }
3716
      else if(name(cllees) == make_dynamic_callee_tag){
3717
	int rdest,rsource,tempreg,le,ls;
3718
	space nsp;
3719
	baseoff b;
3720
	rdest = getreg(sp.fixed);
3721
	nsp = guardreg(rdest,sp);
3722
	rsource = getreg(nsp.fixed);
3723
	load_reg(son(cllees),rsource,sp);
3724
	nsp = guardreg(rsource,nsp);
3725
	rsize = getreg(nsp.fixed);
3726
	load_reg(bro(son(cllees)),rsize,nsp);
3727
	nsp = guardreg(rsize,nsp);
3728
	tempreg = getreg(nsp.fixed);
3729
	operate_fmt_immediate(i_subq,FP,4*(PTR_SZ>>3)+stack_space,rdest);
3730
	operate_fmt_immediate(i_addq,rsize,7,rsize);
3731
	operate_fmt_immediate(i_bic,rsize,7,rsize);
3732
	operate_fmt(i_addq,rsource,rsize,rsource);
3733
	le = new_label();
3734
	ls = new_label();
3735
	integer_branch(i_ble,rsize,le);
3736
	set_label(ls);
3737
	b.base = rsource;
3738
	b.offset = -(PTR_SZ>>3);
3739
	load_store(i_ldq,tempreg,b);
3740
	b.base = rdest;
3741
	load_store(i_stq,tempreg,b);
3742
	operate_fmt_immediate(i_subq,rdest,(PTR_SZ>>3),rdest);
3743
	operate_fmt_immediate(i_subq,rsource,(PTR_SZ>>3),rsource);
3744
	operate_fmt_immediate(i_subq,rsize,(PTR_SZ>>3),rsize);
3745
	integer_branch(i_bgt,rsize,ls);
3746
	set_label(le);
3747
	operate_fmt(i_bis,rdest,rdest,SP);
3748
      }
3749
      else{
3750
	if(Has_vcallees){
3751
	  operate_fmt(i_bis,local_reg,local_reg,SP);
3752
	}
3753
	else{
3754
	  operate_fmt_immediate(i_subq,FP,stack_space+(callee_size>>3),SP);
3755
	}
3756
      }
3757
      if(Has_vcallees){
3758
	baseoff b;
3759
	b.base = FP;
3760
	b.offset = (-4 * (PTR_SZ>>3)) - stack_space;
3761
	load_store(i_ldq,local_reg,b);
3762
      }
3763
 
3764
      if(!in_general_proc) {
3765
	baseoff b;
3766
	b.base = FP;
3767
	b.offset = -(PTR_SZ>>3)-arg_stack_space;
3768
	setnoat();
3769
	load_store(i_ldq,AT,b);
3770
	b.base = SP;
3771
	if(name(cllees)!=make_dynamic_callee_tag) {
3772
	  b.offset = (((no(cllees) >> 3) + 39) & ~7)-(PTR_SZ>>3);
3773
	}
3774
	else {
3775
	  load_reg(bro(son(cllees)),rsize,sp);
3776
	  operate_fmt_immediate(i_addq,rsize,7,rsize);
3777
	  operate_fmt_immediate(i_bic,rsize,7,rsize);
3778
	  operate_fmt_immediate(i_addq,rsize,(39&~7)-(PTR_SZ>>3),rsize);
3779
	  operate_fmt(i_addq,rsize,SP,rsize);
3780
	  b.base = rsize;
3781
	  b.offset = 0;
3782
	}
3783
 
3784
	load_store(i_stq,AT,b);
3785
	if(Has_vcallees) {
3786
	  operate_fmt(i_bis,FP,FP,local_reg);
3787
	}
3788
      }
3789
 
3790
      {
3791
	int rt = getreg(sp.fixed);
3792
	rt = reg_operand(fn,guardreg(RA,sp));
3793
	operate_fmt(i_bis,rt,rt,PV);
3794
	integer_jump(i_jmp,31,rt,0);
3795
	/*integer_jump_external(i_jmp,31,boff(son(fn)));*/
3796
      }
3797
      return mka;
3798
    }
3799
#ifdef return_to_label_tag
3800
    case return_to_label_tag : {
3801
      int r = getreg(sp.fixed);
3802
      where w;
3803
      w.ashwhere.ashsize = 64;
3804
      w.ashwhere.ashalign = 64;
3805
      setregalt(w.answhere,r);
3806
      code_here(son(e),sp,w);
3807
      clear_all();
3808
      if(Has_fp) {
3809
	baseoff b;
3810
	b.base = FP;
3811
	restore_sregs(fixdone,fltdone);
3812
	if(Has_vcallees) {
3813
	  b.offset = -4*(PTR_SZ>>3);
3814
	  load_store(i_ldq,local_reg,b);
3815
	}
3816
	b.offset = -(PTR_SZ>>3) - arg_stack_space;
3817
	operate_fmt(i_bis,FP,FP,SP);
3818
	load_store(i_ldq,FP,b);
3819
      }
3820
      else if(frame_size != 0) {
3821
	restore_sregs(fixdone,fltdone);
3822
	operate_fmt_immediate(i_addq,SP,frame_size>>3,SP);
3823
      }
3824
      integer_jump(i_jmp,31,r,0);
3825
      clear_all();
3826
      return mka;
3827
    }
3828
#endif    
3829
 
3830
    case untidy_return_tag :
3831
    case res_tag : {
3832
      where w;
3833
      w.answhere = procans;
3834
      w.ashwhere = ashof (sh (son (e)));
3835
      code_here (son (e), sp, w);
3836
      /* evaluate result value */
3837
      if(name(e) == untidy_return_tag) comment("untidy return");
3838
 
3839
      clear_all ();		/* clear all register memories */
3840
      if (rscope_level == 0) {/* normal proc body */
3841
	if (name(son(e)) == apply_tag && props(e)) return mka;
3842
	/* was a tail recursion */
3843
	if (frame_size == 0 && !Has_fp) {
3844
	  integer_jump(i_ret,31,RA,1);
3845
	}
3846
	if (result_label != 0) {
3847
	  integer_branch(i_br,31,result_label);
3848
	  comment(" Return ");
3849
	}
3850
	else{
3851
	  if ((fixdone|fltdone)==0) {
3852
	    result_label = new_label();
3853
	    set_label(result_label);
3854
	  }
3855
	  if (Has_fp) {
3856
	    baseoff b;
3857
	    b.base = FP;
3858
	    restore_sregs (fixdone, fltdone);
3859
	    if(Has_vcallees){
3860
	      b.offset = -4 * (PTR_SZ>>3) - arg_stack_space;
3861
	      load_store(i_ldq,local_reg,b);
3862
	    }
3863
	    b.offset = (in_general_proc)?(-PTR_SZ>>3):(-arg_stack_space-(PTR_SZ>>3));;
3864
	    b.offset = (-arg_stack_space-(PTR_SZ>>3));;
3865
#if 0
3866
	    if(arg_stack_space && in_general_proc && name(e) == res_tag){
3867
	      operate_fmt_immediate(i_addq,FP,arg_stack_space,SP);
3868
	    }
3869
 
3870
	    else 
3871
#endif
3872
	      if (name(e) == res_tag){
3873
		operate_fmt(i_bis,FP,FP,SP);
3874
	    }
3875
	    load_store(i_ldq,FP,b);
3876
	  }
3877
	  else {		
3878
	    baseoff a;
3879
	    restore_sregs (fixdone, fltdone);
3880
	    /* restore dumped value of s-regs on entry */
3881
	    a.base=SP;
3882
	    a.offset=(callee_size+frame_size)>>3;
3883
	    if(a.offset!=0 && name(e) == res_tag)
3884
	      load_store(i_lda,SP,a);
3885
	    /* reset stack ptr */
3886
	  }
3887
	  integer_jump(i_ret,31,RA,1);
3888
	}
3889
      }
3890
      else {			/* inlined result */
3891
	if (rscope_label == 0) rscope_label = new_label();
3892
	if (rscope_label != exitlab) {
3893
	  integer_branch(i_br,31,rscope_label);
3894
	  /*
3895
	    uncond_ins (i_b, rscope_label);*/
3896
	}
3897
      }
3898
      sizecallers = 0;
3899
      return mka;
3900
    }				/* end result */
3901
 
3902
    case diagnose_tag : {
3903
      output_diag(dno(e),0,e);
3904
/*      output_symbolic_diagnostic(as_file,dno(e));*/
3905
      mka = make_code (son (e), sp, dest, exitlab);
3906
      output_end_scope(dno(e),e);
3907
      return mka;
3908
    }
3909
    case solve_tag : {
3910
      exp m = bro (son (e));
3911
      int   l = exitlab;
3912
      if (dest.answhere.discrim == insomereg) {
3913
	/* choose register for result */
3914
	int  *sr = someregalt (dest.answhere);
3915
	if (*sr != -1) {
3916
	  failer ("Somereg *2");
3917
	}	
3918
	*sr = getreg (sp.fixed);
3919
	setregalt (dest.answhere, *sr);
3920
      }
3921
      else if (dest.answhere.discrim == insomefreg ){
3922
	somefreg sfr;
3923
	freg fr;
3924
	sfr = somefregalt(dest.answhere);
3925
	if (*sfr.fr != -1) { failer ("Somefreg *2"); }
3926
	*sfr.fr = getfreg(sp.flt);
3927
	fr.fr = *sfr.fr;
3928
	fr.type = sfr.type;
3929
	setfregalt(dest.answhere, fr);
3930
      }
3931
 
3932
      for (;;) {		/* set up all the labels in the component
3933
				   labst_tags */
3934
	no (son (m)) = new_label ();
3935
	if (last (m))
3936
	  break;
3937
	m = bro (m);
3938
      }
3939
 
3940
      m = son (e);
3941
      for (;;) {		/* evaluate all the component statements 
3942
				 */
3943
	int   fl = make_code (m, sp, dest, l).lab;
3944
	clear_all ();
3945
	if (fl != 0)
3946
	  l = fl;
3947
	if (!last (m)) {	/* jump to end of solve */
3948
	  if (l == 0)
3949
	    l = new_label ();
3950
	  if (name (sh (m)) != bothd) {
3951
	    integer_branch(i_br,31,l);
3952
	  }
3953
	}
3954
	if (last (m)) {
3955
	  mka.lab = l;
3956
	  return mka;
3957
	}
3958
	m = bro (m);
3959
      }
3960
    }				/* end solve */
3961
 
3962
      /*
3963
	case_tag now uses the INT64 type.
3964
	*/
3965
    case case_tag : {
3966
      char * outline = (char*)NULL;
3967
      int   r = reg_operand (son (e), sp);
3968
      /* evaluate controlling integer into reg r */
3969
      mm lims;
3970
      exp z = bro (son (e));
3971
      exp zt = z;
3972
      INT64  n;
3973
      INT64  l;
3974
      INT64  u;
3975
      INT64 xt,yt;
3976
      int control_sgned = is_signed(sh(son(e)));
3977
      u = make_INT64(0x80000000,0x00000000);
3978
      /*INT64_assign(u,smin);*/
3979
      comment(" begin case ");
3980
      INT64_assign(l,exp_to_INT64(zt));
3981
      for(n=make_INT64(0,1);;n=INT64_increment(n)){
3982
	/* calculate crude criterion for using
3983
	   jump vector or branches */
3984
	if(!(INT64_eq(INT64_increment(u),exp_to_INT64(zt))) &&
3985
	   (son(zt)!=nilexp)){
3986
	  n = INT64_increment(n);
3987
	}
3988
	if (last (zt)) {
3989
	  u = (son (zt) != nilexp) ? exp_to_INT64(son (zt)):exp_to_INT64(zt);
3990
	  break;
3991
	}
3992
	if (son (zt) != nilexp) {
3993
	  u = exp_to_INT64(son (zt));
3994
	}
3995
	else {
3996
	  if(INT64_eq(INT64_increment(u),exp_to_INT64(zt))){
3997
	    u = INT64_increment(u);
3998
	  }
3999
	}
4000
 
4001
	zt = bro (zt);
4002
      }
4003
 
4004
      /* now l is lowest controlling value and u is highest */
4005
      /*	 The above actually means: */
4006
      if(control_sgned){
4007
	xt = (INT64_subtract(INT64_shift_right(u,1,1),
4008
			     INT64_shift_right(l,1,1),1));
4009
	yt = (INT64_subtract(INT64_divide(INT64_mult(n,n,1),
4010
					  make_INT64(0,4),1),
4011
			     make_INT64(0,3),1));
4012
      }
4013
      else {
4014
	unsigned long uu = unsigned_rep (u,sh(son(e)));
4015
	unsigned long lu = unsigned_rep (l,sh(son(e)));
4016
	xt = (INT64_subtract(INT64_shift_right(uu,1,1),
4017
			     INT64_shift_right(lu,1,1),1));
4018
	yt = (INT64_subtract(INT64_divide(INT64_mult(n,n,1),
4019
					  make_INT64(0,4),1),
4020
			     make_INT64(0,3),1));
4021
      }
4022
 
4023
 
4024
       if( xt <= yt) {
4025
	/* space-time product criterion for jump vector instead 
4026
	   of tests  and branches */
4027
	/* use jump vector */
4028
	int   endlab = new_label ();
4029
	int   veclab = next_dlab_sym ();
4030
	baseoff zeroveclab;
4031
	baseoff zero3;
4032
	int  rtmp=getreg(guardreg(r,sp).fixed); /* could use AT */
4033
 
4034
 
4035
 
4036
	zero3.base = rtmp;
4037
	zero3.offset = 0;
4038
	zeroveclab.offset = 0;
4039
	zeroveclab.base = veclab;
4040
	n = l;
4041
	start_new_capsule(false);
4042
	if (as_file){
4043
#if !DO_SCHEDULE
4044
	  fprintf (as_file, "\t.rdata\n$$%d:\n", veclab);
4045
#else
4046
	  outline = (char*)xcalloc(30,sizeof(char));
4047
	  sprintf (outline, "\t.rdata\n$$%d:\n", veclab);
4048
#endif
4049
	}
4050
#if DO_SCHEDULE
4051
	output_instruction(class_null,outline,out_common(0,irdata));
4052
	output_instruction(class_null,(char*)NULL,
4053
			   out_common(tempsnos[veclab-32],ilabel));
4054
#else
4055
	out_common (0, irdata);
4056
	out_common (tempsnos[veclab - 32], ilabel);
4057
#endif
4058
	for (;;) {
4059
	  for (; INT64_lt(n,exp_to_INT64(z)); 
4060
		 n = INT64_increment(n)){
4061
	    /* o/p jump vector */
4062
	    if (as_file){
4063
#if !DO_SCHEDULE
4064
	      fprintf (as_file, "\t.gprel32\t$%d\n", endlab);
4065
#else
4066
	      outline = (char*)xcalloc(30,sizeof(char));
4067
	      sprintf (outline, "\t.gprel32\t$%d\n", endlab);
4068
#endif
4069
	    }
4070
#if DO_SCHEDULE
4071
	    output_instruction(class_null,outline,
4072
			       out_value(-endlab,igprel32,0,1));
4073
#else	     
4074
	    out_value (-endlab, igprel32, make_INT64(0,0), 1);
4075
#endif
4076
	  }
4077
	  u = (son (z) == nilexp) ? n : exp_to_INT64(son (z));
4078
	  for (; INT64_leq(n,u) /*n <= u*/; n=INT64_increment(n)/*n++*/){
4079
	    if (as_file){
4080
#if !DO_SCHEDULE
4081
	      fprintf (as_file, "\t.gprel32\t$%d\n", no (son (pt (z))));
4082
#else
4083
	      outline = (char*)xcalloc(30,sizeof(char));
4084
	      sprintf (outline, "\t.gprel32\t$%d\n", no (son (pt (z))));
4085
#endif
4086
	    }
4087
#if DO_SCHEDULE
4088
	    output_instruction(class_null,outline,
4089
			       out_value(-no(son(pt(z))),igprel32,0,1));
4090
#else	     
4091
	    out_value(-no(son(pt(z))),igprel32,make_INT64(0,0),1);
4092
#endif
4093
	  }
4094
	  if (last (z))
4095
	    break;
4096
	  z = bro (z);
4097
	}
4098
	set_text_section();
4099
	setnoat();
4100
	load_store (i_lda, AT, zeroveclab);
4101
	if (!INT64_eq(l,zero_int64) /*l != 0*/) {
4102
	  int rtmp2;
4103
	  INT64 lit;
4104
	  space newsp;
4105
	  newsp = guardreg(r,sp);
4106
	  newsp = guardreg(rtmp,newsp);
4107
	  rtmp2 = getreg(newsp.fixed);
4108
	  lit=INT64_subtract(make_INT64(0,0),l,1);
4109
	  operate_fmt_big_immediate (i_addq, r, lit,rtmp);
4110
	  lit = INT64_increment(INT64_subtract(u,l,1));
4111
	  operate_fmt_big_immediate(i_cmpult,rtmp,lit,rtmp2);
4112
	  integer_branch(i_beq,rtmp2,endlab);
4113
	  operate_fmt(i_s4addq,rtmp,AT,rtmp);
4114
	}
4115
	else {
4116
	  int rtmp2;
4117
	  space newsp;
4118
	  newsp = guardreg(r,sp);
4119
	  newsp = guardreg(rtmp,newsp);
4120
	  rtmp2 = getreg(newsp.fixed);
4121
	  load_store_immediate(i_ldiq,rtmp2,INT64_increment(u));
4122
 
4123
/*	   operate_fmt(i_subq,r,rtmp2,rtmp);	
4124
	   integer_branch(i_bge,rtmp,endlab); */
4125
	  operate_fmt(i_cmpule,rtmp2,r,rtmp);
4126
	  integer_branch(i_bne,rtmp,endlab);
4127
	  operate_fmt(i_s4addq,r,AT,rtmp);
4128
	}
4129
	setat();
4130
	load_store(i_ldl,rtmp,zero3);
4131
	operate_fmt(i_addq,rtmp,GP,rtmp);
4132
	integer_jump(i_jmp,31,rtmp,endlab); /* endlab is hint */
4133
	set_label (endlab);
4134
	close_capsule();
4135
	comment(" end case ");
4136
	return mka;
4137
      }
4138
      else {
4139
	int   over = 0;	/* use branches - tests are already
4140
			   ordered */
4141
	int rtmp = getreg(guardreg(r,sp).fixed);
4142
	bool usw;
4143
	lims = maxmin (sh (son (e)));
4144
	usw = !is_signed(sh(son(e)));
4145
	for (;;) {
4146
	  int lab = no(son(pt(z))); /* can this be big */
4147
	  l = exp_to_INT64(z);
4148
	  if(isbigval(son(pt(z))))
4149
	    alphafail(BIG_LABEL);
4150
	  if (son (z) == nilexp) { /* only single test required */
4151
	    operate_fmt_big_immediate(i_cmpeq,r,l,rtmp);
4152
	    integer_branch(i_bne,rtmp,lab);
4153
	    if(INT64_eq(l,lims.maxi)) {
4154
	      lims.maxi = INT64_decrement(lims.maxi);
4155
	    }
4156
	    else if (INT64_eq(l,lims.mini)) {
4157
	      lims.mini = INT64_increment(lims.mini);
4158
	    }
4159
	  }
4160
	  else if (u = exp_to_INT64(son (z)),
4161
		   INT64_leq(lims.mini,l)||usw) {
4162
/*	       if (INT64_lt(lims.maxi,INT64_and(INT64_not(usw),u))){ */
4163
	    if(INT64_leq(lims.maxi,u) && !usw){
4164
	      /* have already tested lower */
4165
	      operate_fmt_big_immediate(i_cmplt,r,l,rtmp);
4166
	      integer_branch(i_beq,rtmp,lab);
4167
	      lims.maxi = INT64_decrement(l);
4168
	    }
4169
	    else {
4170
	      if (over == 0) {
4171
		over = new_label ();
4172
	      }
4173
	      operate_fmt_big_immediate(i_cmplt,r,l,rtmp);
4174
	      integer_branch(i_bne,rtmp,over);
4175
	      operate_fmt_big_immediate(i_cmple,r,u,rtmp);
4176
	      integer_branch(i_bne,rtmp,lab);
4177
	      lims.mini = INT64_increment(u);
4178
	    }	
4179
	  }
4180
	  else if  (INT64_lt(u,lims.maxi)) {/*lower is <= lower limit 
4181
					      of shape*/
4182
	    operate_fmt_big_immediate(i_cmple,r,u,rtmp);
4183
	    integer_branch(i_bne,rtmp,lab);
4184
	    lims.mini = INT64_increment(u);
4185
	  }
4186
	  else {	/* upper is >= upper limit of shape */
4187
	    integer_branch(i_br,31,lab);
4188
	  }
4189
	  if (last (z)) {
4190
	    if (over != 0) {
4191
	      set_label (over);
4192
	    } 
4193
	    comment(" end case ");
4194
	    return mka;
4195
	  }
4196
	  z = bro (z);
4197
	}
4198
      }
4199
    } /* end case */
4200
 
4201
    case plus_tag : 
4202
    case offset_add_tag :{
4203
      if(optop(e)){
4204
	mka.regmove = comm_op(e,sp,dest,(dest.ashwhere.ashsize==32)?
4205
			      i_addl:i_addq);
4206
	return mka;
4207
      }
4208
#if 0
4209
      if(error_treatment_is_trap(e) /*&& is_signed(sh(e))*/){
4210
	mka.regmove = comm_op(e,sp,dest,(dest.ashwhere.ashsize==32)?
4211
			      i_addlv:i_addqv);
4212
	return mka;
4213
      }
4214
#endif       
4215
      else{
4216
	int r1 = reg_operand(son(e), sp);
4217
	int r2,r0;
4218
	int over = new_label();
4219
	int trap = trap_label(e);
4220
	space nsp;
4221
	ans aa;
4222
	nsp = guardreg(r1, sp);
4223
	r2 = reg_operand(bro(son(e)), nsp);
4224
	nsp = guardreg(r2, nsp);
4225
	r0 = getreg(nsp.fixed);
4226
	nsp = guardreg(r0, nsp);
4227
	operate_fmt(is64(sh(e))?i_addq:i_addl,r1,r2,r0);
4228
	switch(name(sh(e))){
4229
	  case s64hd :
4230
	  case slonghd :{
4231
	    int r3 = getreg(sp.fixed);
4232
	    operate_fmt(i_xor,r1,r2,r3);
4233
	    integer_branch(i_blt,r3,over);
4234
	    operate_fmt(i_xor,r0,r1,r3);
4235
	    if(error_treatment_is_trap(e)){
4236
	      integer_branch(i_bge,r3,over);
4237
	      do_exception(f_overflow);
4238
	    }
4239
	    else{
4240
	      integer_branch(i_blt,r3,trap);
4241
	    }
4242
	    set_label(over);
4243
	    break;
4244
	  }
4245
	  case ulonghd :
4246
	  case u64hd :{
4247
	    int r3 = getreg(sp.fixed);
4248
	    operate_fmt(i_cmpult,r0,r1,r3);
4249
	    if(error_treatment_is_trap(e)){
4250
	      int oklab = new_label();
4251
	      integer_branch(i_beq,r3,oklab);
4252
	      do_exception(f_overflow);
4253
	      set_label(oklab);
4254
	    }
4255
	    else{
4256
	      integer_branch(i_bne,r3,trap);
4257
	    }
4258
	    break;
4259
	  }
4260
	  case uwordhd :{
4261
	    if(error_treatment_is_trap(e)){
4262
	      test_unsigned_and_trap(r0,0xffff,f_overflow);
4263
	    }
4264
	    else{
4265
	      test_unsigned(r0,0xffff,trap);
4266
	    }
4267
	    break;
4268
	  }
4269
	  case swordhd :{
4270
	    if(error_treatment_is_trap(e)){
4271
	      test_signed_and_trap(r0,-0x8000L,0x7fff,f_overflow);
4272
	    }
4273
	    else{
4274
	      test_signed(r0,-0x8000L,0x7fff,trap);
4275
	    }
4276
	    break;
4277
	  }
4278
	  case ucharhd :{
4279
	    if(error_treatment_is_trap(e)){
4280
	      test_unsigned_and_trap(r0,255,f_overflow);
4281
	    }
4282
	    else{
4283
	      test_unsigned(r0,255,trap);
4284
	    }
4285
	    break;
4286
	  }
4287
	  case scharhd :{   
4288
	    if(error_treatment_is_trap(e)){
4289
	      test_signed_and_trap(r0,-128,127,f_overflow);
4290
	    }
4291
	    else{
4292
	      test_signed(r0,-128,127,trap);
4293
	    }
4294
	    break;
4295
	  }
4296
	  default:failer("illegal shape");
4297
	}
4298
	setregalt(aa,r0);
4299
	mka.regmove = move(aa,dest,nsp,0);
4300
	return mka;
4301
      }
4302
    } /* end plus */
4303
 
4304
    case chvar_tag : {
4305
      int   a;
4306
      int tmpreg;
4307
      int   d;
4308
      ans aa;
4309
      int   nsh = name (sh (e));
4310
      switch (dest.answhere.discrim) {
4311
	case inreg : {
4312
	  ash arga;
4313
	  arga = ashof (sh (son (e)));
4314
	  if (arga.ashsize <= dest.ashwhere.ashsize) {
4315
	    dest.ashwhere = arga;
4316
	  }
4317
	  a = regalt (dest.answhere);
4318
	  if (a == NO_REG) {
4319
	    a = getreg(sp.fixed);
4320
	    setregalt(dest.answhere,a);
4321
	    dest.ashwhere.ashsize = shape_size(sh(son(e)));
4322
	    dest.ashwhere.ashalign = dest.ashwhere.ashsize;
4323
	  }
4324
	  code_here (son (e), sp, dest);
4325
	  /* evaluate argument into reg */
4326
	  break;
4327
	}
4328
	default: 
4329
	a = reg_operand (son (e), sp);
4330
	/* evaluate arguement into a */
4331
      }	
4332
      setregalt (aa, a);
4333
      if(sh(son(e)) == sh(e)){
4334
	mka.regmove = move(aa,dest,sp,1);
4335
	return mka;
4336
      }
4337
 
4338
      if((dest.answhere.discrim == inreg) && 
4339
	 (dest.answhere.val.regans == a)){
4340
	tmpreg = a;
4341
      }
4342
      else{
4343
	tmpreg = getreg(sp.fixed);
4344
      }
4345
 
4346
      if(nsh >= s64hd){
4347
	/* destination is 64 bits wide, the only thing we have 
4348
	   to worry about is the conversion of unsigned 
4349
	   values to signed, which can be avoided by the 
4350
	   following code */
4351
	if(convert_shapes(nsh,name(sh(son(e))),a,tmpreg)){
4352
	  setregalt(aa,tmpreg);
4353
	}
4354
	mka.regmove = move(aa,dest,sp,1);
4355
	return mka;
4356
      }
4357
      if (sh (son (e)) == sh (e) /*|| nsh  >= slonghd*/) {
4358
	/* no changes required, so just move to dest*/
4359
 
4360
	mka.regmove = move (aa, dest, sp, 1);
4361
	return mka;
4362
      }
4363
      switch (dest.answhere.discrim) {
4364
	case insomereg : {
4365
	  int  *dr = someregalt (dest.answhere);
4366
	  d = getreg (sp.fixed);
4367
	  *dr = d;
4368
	  goto out;
4369
	}
4370
	case inreg : {
4371
	  d = regalt (dest.answhere);
4372
	  goto out;
4373
	}
4374
	default: {
4375
	  /* representation in store will be same so just move */
4376
	  move (aa, dest, sp, 1);
4377
	  return mka;
4378
	}
4379
      }
4380
  out: 			/* d is destination register - do
4381
			   appropriate ands etc */
4382
      if (d==NO_REG) return mka;
4383
/*       (void)convert_shapes(nsh,name(sh(son(e))),a,d);*/
4384
      switch(nsh){
4385
	case ucharhd :{
4386
	  if(is_signed(sh(son(e))) && !optop(e)) {
4387
	    if(error_treatment_is_trap(e)){
4388
	      int new_lab = new_label();
4389
	      integer_branch(i_bge,a,new_lab);
4390
	      do_exception(f_overflow);
4391
	      set_label(new_lab);
4392
	    }
4393
	    else{
4394
	      integer_branch(i_blt,a,trap_label(e));
4395
	    }
4396
 
4397
	  }
4398
	  if(!optop(e)){
4399
	    if(error_treatment_is_trap(e)){
4400
	      test_unsigned_and_trap(a,255,f_overflow);
4401
	    }
4402
	    else{
4403
	      test_unsigned(a,255,trap_label(e));
4404
	    }
4405
	  }
4406
	  operate_fmt_immediate(i_and,a,255,d);
4407
	  break;
4408
	}
4409
	case scharhd :{
4410
	  if(!is_signed(sh(son(e))) && !optop(e)) {
4411
	    setnoat();
4412
	    operate_fmt_immediate(i_cmpule,a,0x7f,AT);
4413
	    if(!error_treatment_is_trap(e)){
4414
	      integer_branch(i_beq,AT,trap_label(e));
4415
	    }
4416
	    else{
4417
	      int new_lab = new_label();
4418
	      integer_branch(i_bne,AT,new_lab);
4419
	      do_exception(f_overflow);
4420
	      set_label(new_lab);
4421
	    }
4422
	    setat();
4423
	  }
4424
	  if(!optop(e)){ 
4425
	    if(error_treatment_is_trap(e)){
4426
	      test_signed_and_trap(a,-128,127,f_overflow);
4427
	    }
4428
	    else{
4429
	      test_signed(a,-128,127,trap_label(e));
4430
	    }
4431
	  }
4432
	  operate_fmt_immediate(i_extqh,a,1,d);
4433
	  operate_fmt_immediate(i_sra,d,REG_SIZE-8,d);
4434
	  break;
4435
	}
4436
	case uwordhd :{
4437
	  if(is_signed(sh(son(e))) && !optop(e)) {
4438
	    if(error_treatment_is_trap(e)){
4439
	      int new_lab = new_label();
4440
	      integer_branch(i_bge,a,new_lab);
4441
	      do_exception(f_overflow);
4442
	      set_label(new_lab);
4443
	    }
4444
	    else{
4445
	      integer_branch(i_blt,a,trap_label(e));
4446
	    }
4447
	  }
4448
	  if(!optop(e)){
4449
	    if(error_treatment_is_trap(e)){
4450
	      test_unsigned_and_trap(a,0xffff,f_overflow);
4451
	    }
4452
	    else{
4453
	      test_unsigned(a,0xffff,trap_label(e));
4454
	    }
4455
	  }
4456
	  operate_fmt_immediate(i_and,a,(1<<16)-1,d);
4457
	  break;
4458
	}
4459
	case swordhd : {
4460
	  if(!is_signed(sh(son(e))) && !optop(e)) {
4461
	    setnoat();
4462
	    operate_fmt_immediate(i_cmpule,a,0x7fff,AT);
4463
	    if(error_treatment_is_trap(e)){
4464
	      int new_lab = new_label();
4465
	      integer_branch(i_bne,AT,new_lab);
4466
	      do_exception(f_overflow);
4467
	      set_label(new_lab);
4468
	    }
4469
	    else{
4470
	      integer_branch(i_beq,AT,trap_label(e));
4471
	    }
4472
	    setat();
4473
	  }
4474
	  if(!optop(e)){
4475
	    if(error_treatment_is_trap(e)){
4476
	      test_signed_and_trap(a,-0x8000L,0x7fff,f_overflow);
4477
	    }
4478
	    else{
4479
	      test_signed(a,-0x8000L,0x7fff,trap_label(e));
4480
	    }
4481
	  }
4482
	  operate_fmt_immediate(i_sll,a,48,d);
4483
	  operate_fmt_immediate(i_sra,d,48,d);
4484
	  break;
4485
	}
4486
	case ulonghd :{
4487
	  if(is_signed(sh(son(e))) && !optop(e)) {
4488
	    if(error_treatment_is_trap(e)){
4489
	      int new_lab = new_label();
4490
	      integer_branch(i_bge,a,new_lab);
4491
	      do_exception(f_overflow);
4492
	      set_label(new_lab);
4493
	    }
4494
	    else{
4495
	      integer_branch(i_blt,a,trap_label(e));
4496
	    }
4497
	  }
4498
	  if(!optop(e)){
4499
	    if(error_treatment_is_trap(e)){
4500
	      test_unsigned_and_trap(a,0xffffffff,f_overflow);
4501
	    }
4502
	    else{
4503
	      test_unsigned(a,0xffffffff,trap_label(e));
4504
	    }
4505
	  }
4506
	  operate_fmt_immediate(i_addl,a,0,d);
4507
	  /*operate_fmt_big_immediate(i_and,a,0xffffffff,d);*/
4508
	  break;
4509
	}
4510
	case slonghd :{
4511
	  if(!is_signed(sh(son(e))) && !optop(e)) {
4512
	    setnoat();
4513
	    operate_fmt_big_immediate(i_cmpule,a,0x7fffffff,AT);
4514
	    if(error_treatment_is_trap(e)){
4515
	      int new_lab = new_label();
4516
	      integer_branch(i_bne,AT,new_lab);
4517
	      do_exception(f_overflow);
4518
	      set_label(new_lab);
4519
	    }
4520
	    else{
4521
	      integer_branch(i_beq,AT,trap_label(e));
4522
	    }
4523
	    setat();
4524
	  }
4525
	  if(!optop(e)){
4526
	    if(error_treatment_is_trap(e)){
4527
	      test_signed_and_trap(a,-0x80000000L,0x7fffffff,f_overflow);
4528
	    }
4529
	    else{
4530
	      test_signed(a,-0x80000000L,0x7fffffff,trap_label(e));
4531
	    }
4532
	  }
4533
	  operate_fmt_immediate(i_sll,a,32,d);
4534
	  operate_fmt_immediate(i_sra,d,32,d);
4535
	  break;
4536
	}
4537
	case s64hd : {
4538
	  if(!is_signed(sh(e)) && !optop(e)) {
4539
	    setnoat();
4540
	    operate_fmt_big_immediate(i_cmpule,a,0x7fffffffffffffffL,AT);
4541
	    if(error_treatment_is_trap(e)){
4542
	      int new_lab = new_label();
4543
	      integer_branch(i_bne,AT,new_lab);
4544
	      do_exception(f_overflow);
4545
	      set_label(new_lab);
4546
	    }
4547
	    else{
4548
	      integer_branch(i_beq,AT,trap_label(e));
4549
	    }
4550
	    setat();
4551
	  }
4552
	  if(!optop(e)){
4553
	    if(error_treatment_is_trap(e)){
4554
	      test_signed_and_trap(a,-0x8000000000000000L,0x7fffffffffffffffL,
4555
				   f_overflow);
4556
	    }
4557
	    else{
4558
	      test_signed(a,-0x8000000000000000L,0x7fffffffffffffffL,
4559
				   trap_label(e));
4560
	    }
4561
	  }
4562
	  operate_fmt(i_bis,a,a,d);
4563
	  break;
4564
	}
4565
 
4566
	case u64hd :{
4567
	  if(is_signed(sh(e)) && !optop(e)){
4568
	    if(error_treatment_is_trap(e)){
4569
	      int new_lab = new_label();
4570
	      integer_branch(i_bge,a,new_lab);
4571
	      do_exception(f_overflow);
4572
	      set_label(new_lab);
4573
	    }
4574
	    else{
4575
	      integer_branch(i_blt,a,trap_label(e));
4576
	    }
4577
	  }
4578
	  operate_fmt(i_bis,a,a,d);
4579
	  break;
4580
	}
4581
	default:failer("Illegal shape in chvar");
4582
      }
4583
#if 0       
4584
      if (nsh == ucharhd) {
4585
	operate_fmt_immediate (i_and, a, 255,d);
4586
      }
4587
      else if (nsh == uwordhd) {
4588
	operate_fmt_immediate (i_and,a, (1 << 16) - 1,d);
4589
	}
4590
      else if (nsh == scharhd) {
4591
	/*	      operate_fmt_immediate (i_sll,a,REG_SIZE-8,d);*/
4592
	operate_fmt_immediate (i_extqh,a,1,d);
4593
	operate_fmt_immediate (i_sra,d,REG_SIZE-8,d);
4594
      }
4595
      else if (nsh == swordhd) {
4596
	operate_fmt_immediate (i_sll, a, 32,d);
4597
	operate_fmt_immediate (i_sra, d, 32,d);
4598
      }
4599
#endif
4600
      mka.regmove = d;
4601
      return mka;
4602
    } /* end chvar */
4603
 
4604
    case minus_tag : 
4605
    case offset_subtract_tag :{
4606
      if(optop(e)){
4607
	mka.regmove = non_comm_op (e,sp,dest,is64(sh(e))?i_subq:i_subl);
4608
	return mka;
4609
      }
4610
#if 0
4611
      if(error_treatment_is_trap(e) && is_signed(sh(e))){
4612
	mka.regmove = non_comm_op (e,sp,dest,is64(sh(e))?i_subqv:i_sublv);
4613
	return mka;
4614
      }
4615
#endif
4616
      else{
4617
/*	   if(!optop(e)) check_exception(e,sp);*/
4618
	int r1 = reg_operand(son(e), sp);
4619
	int r2, r3, r0;
4620
	int over = new_label();
4621
	int trap = trap_label(e);
4622
	space nsp;
4623
	ans aa;
4624
	nsp = guardreg(r1, sp);
4625
	r2 = reg_operand(bro(son(e)), nsp);
4626
	nsp = guardreg(r2, nsp);
4627
	r0 = getreg(nsp.fixed);
4628
	nsp = guardreg(r0,nsp);
4629
	operate_fmt((is64(sh(e)))?i_subq:i_subl, r1, r2,r0);  
4630
	switch(name(sh(e))) {
4631
	  case s64hd :  
4632
	  case slonghd : {
4633
	    r3 = getreg(nsp.fixed);
4634
	    operate_fmt(i_xor,r1, r2,r3);
4635
	    integer_branch(i_bge,r3,over);
4636
	    operate_fmt(i_xor,r0,r1,r3);
4637
	    if(error_treatment_is_trap(e)){
4638
	      integer_branch(i_bge,r3,over);
4639
	      do_exception(f_overflow);
4640
	    }
4641
	    else{
4642
	      integer_branch(i_blt,r3,trap);
4643
	    }
4644
	    set_label(over);
4645
	    break;
4646
	  }
4647
	  case u64hd :
4648
	  case ulonghd : {
4649
	    r3 = getreg(guardreg(r0, nsp).fixed);
4650
	    operate_fmt(i_cmpult,r1,r2,r3);
4651
	    if(error_treatment_is_trap(e)){
4652
	      int ok_lab = new_label();
4653
	      integer_branch(i_beq,r3,ok_lab);
4654
	      do_exception(f_overflow);
4655
	      set_label(ok_lab);
4656
	    }
4657
	    else{
4658
	      integer_branch(i_bne,r3,trap);
4659
	    }
4660
	    break;
4661
	  }
4662
	  case scharhd : {
4663
	    if(error_treatment_is_trap(e)){
4664
	      test_signed_and_trap(r0,-128,127,f_overflow);
4665
	    }
4666
	    else{
4667
	      test_signed(r0, -128, 127, trap);
4668
	    }
4669
	    break;
4670
	  }
4671
	  case ucharhd : {
4672
	    if(error_treatment_is_trap(e)){
4673
	      test_unsigned_and_trap(r0,255,f_overflow);
4674
	    }
4675
	    else{
4676
	      test_unsigned(r0, 255, trap);
4677
	    }
4678
	    break;
4679
	  }
4680
	  case swordhd : {
4681
	    if(error_treatment_is_trap(e)){
4682
	      test_signed_and_trap(r0,-0x8000L,0x7fff,f_overflow);
4683
	    }
4684
	    else{
4685
	      test_signed(r0, -0x8000L, 0x7fff, trap);
4686
	    }
4687
	    break;
4688
	  }
4689
	  case uwordhd : {
4690
	    if(error_treatment_is_trap(e)){
4691
	      test_unsigned_and_trap(r0,0xffff,f_overflow);
4692
	    }
4693
	    else{
4694
	      test_unsigned(r0, 0xffff, trap);
4695
	    }
4696
	    break;
4697
	  }
4698
	  default: failer("NOT integer in minus with o/f");
4699
	}
4700
	setregalt(aa, r0);
4701
	mka.regmove = move(aa, dest, nsp, 0);
4702
	return mka;	 
4703
      }
4704
      return mka;
4705
    }
4706
				/* end minus */
4707
    case mult_tag : 
4708
    case offset_mult_tag :{
4709
      exp rop = bro (son (e));
4710
      instruction mult_ins;
4711
      if(!optop(e) & error_treatment_is_trap(e)){
4712
	mult_ins = is64(sh(e))?i_mulqv : i_mullv;
4713
      }
4714
      else{
4715
	mult_ins = is64(sh(e))?i_mulq : i_mull;
4716
      }
4717
 
4718
      if (last (rop) && name (rop) == val_tag && optop(e)) {
4719
	/* multiplication by constant m */
4720
	int   m = no (rop);
4721
	int   p2;
4722
	if (m > 1 && (
4723
		      ((p2 = m) & (m - 1)) == 0 ||
4724
		      (m & (p2 = m + 1)) == 0 ||
4725
		      ((p2 = m - 1) & (m - 2)) == 0
4726
		      )) {
4727
	  /* m = 2^shleng   or  m = 2^(shleng +/- 1) 
4728
	   */
4729
	  int   r = reg_operand (son (e), sp);
4730
	  /* evaluate first arguement */
4731
	  int   rr;
4732
	  space nsp;
4733
	  int   shleng;
4734
	  ans aa;
4735
	  for (shleng = 0; p2 != 1; shleng++)
4736
	    p2 >>= 1;
4737
 
4738
	  switch (dest.answhere.discrim) {
4739
	    case inreg : {
4740
	      rr = regalt (dest.answhere);
4741
	      if (rr != r || (m & (m - 1)) == 0) {
4742
		nsp = sp;
4743
		break;
4744
	      }
4745
	    }
4746
	    FALL_THROUGH;
4747
	    default: {
4748
	      nsp = guardreg (r, sp);
4749
	      rr = getreg (nsp.fixed);
4750
	    }
4751
	  }	
4752
 
4753
	  operate_fmt_immediate (i_sll,r,shleng,rr);
4754
 
4755
	  if ((m & (m - 1)) != 0)
4756
	    if(optop(e)){
4757
	      operate_fmt (((m & (m + 1)) == 0) ? i_subq : i_addq, rr, r, rr);
4758
	    }
4759
	    else{
4760
	      operate_fmt (((m&(m+1))==0) ? i_subqv : i_addqv, rr, r, rr);
4761
	    }
4762
	  if(!optop(e) && !error_treatment_is_trap(e)){
4763
	    check_exception(e,sp);
4764
	  }
4765
	  setregalt (aa, rr);
4766
	  mka.regmove = move (aa, dest, guardreg (rr, sp), 1);
4767
	  return mka;
4768
	}
4769
      } /* else do straightforward mult */
4770
 
4771
      if(optop(e) /*|| error_treatment_is_trap(e)*/) {
4772
	mka.regmove = comm_op (e, sp, dest, mult_ins);
4773
      }
4774
      else /* if (!optop(e) && !error_treatment_is_trap(e)) */{
4775
	int r1 = reg_operand(son(e), sp);
4776
	int r2,r0;
4777
	/*int over = new_label();*/
4778
	space nsp;
4779
	ans aa;
4780
	int contlab = new_label();
4781
	int zerolab = new_label();
4782
	int mult_end_lab = new_label();
4783
	nsp = guardreg(r1, sp);
4784
	r2 = reg_operand(bro(son(e)), nsp);
4785
	nsp = guardreg(r2, nsp);
4786
	r0 = getreg(nsp.fixed);
4787
	nsp = guardreg(r0, nsp);
4788
	integer_branch(i_beq,r1,zerolab);
4789
	integer_branch(i_beq,r2,zerolab);
4790
	integer_branch(i_br,31,contlab);
4791
	set_label(zerolab);
4792
	operate_fmt(i_bis,31,31,r0);
4793
	integer_branch(i_br,31,mult_end_lab);
4794
	set_label(contlab);
4795
 
4796
	  /*	operate_fmt(is64(sh(e))?i_mulq:i_mull,r1,r2,r0);*/
4797
	if(error_treatment_is_trap(e)){
4798
	  operate_fmt(i_mulqv,r1,r2,r0);
4799
	}
4800
	else{
4801
	  operate_fmt(i_mulq,r1,r2,r0);
4802
	}
4803
	switch(name(sh(e))){
4804
	  case u64hd :
4805
	  case s64hd :{
4806
	    int r3 = getreg(sp.fixed);
4807
	    int oklab = new_label();
4808
	    integer_branch(i_beq,r1,oklab);
4809
	    integer_branch(i_beq,r2,oklab);
4810
	    if(error_treatment_is_trap(e)){
4811
	      int new_lab = new_label();
4812
	      integer_branch(i_bne,r0,new_lab);
4813
	      do_exception(f_overflow);
4814
	      set_label(new_lab);
4815
	    }
4816
	    else{
4817
	      integer_branch(i_beq,r0,trap_label(e));
4818
	    }
4819
	    set_label(oklab);
4820
	    operate_fmt(i_xor,r1,r2,r3);
4821
	    /*integer_branch(i_blt,r3,over);*/
4822
	    operate_fmt(i_xor,r3,r0,r3);
4823
	    if(error_treatment_is_trap(e)){
4824
	      int ok_lab = new_label();
4825
	      integer_branch(i_bge,r3,ok_lab);
4826
	      do_exception(f_overflow);
4827
	      set_label(ok_lab);
4828
	    }
4829
	    else{
4830
	      integer_branch(i_blt,r3,trap_label(e));
4831
	    }
4832
	    /*set_label(over);*/
4833
	    break;
4834
	  }
4835
	  case slonghd : {
4836
	    if(!error_treatment_is_trap(e)){
4837
	      int r3 = getreg(sp.fixed);
4838
	      operate_fmt(i_xor,r1,r2,r3);
4839
	      operate_fmt(i_xor,r3,r0,r3);
4840
	      integer_branch(i_blt,r3,trap_label(e));
4841
	      test_signed(r0,-0x80000000L,0x7fffffff,trap_label(e));
4842
	    }
4843
	    else{
4844
#if 1
4845
	      int oklab = new_label();
4846
	      int r3 = getreg(sp.fixed);
4847
	      operate_fmt(i_xor,r1,r2,r3);
4848
	      operate_fmt(i_xor,r3,r0,r3);
4849
	      integer_branch(i_bge,r3,oklab);
4850
	      do_exception(f_overflow);
4851
	      set_label(oklab);
4852
#endif
4853
	      test_signed_and_trap(r0,-0x80000000L,0x7fffffff,f_overflow);
4854
	    }
4855
	    break;
4856
	  }
4857
	  case ulonghd : {
4858
	    if(!error_treatment_is_trap(e)){
4859
	      int r3 = getreg(sp.fixed);
4860
	      operate_fmt(i_xor,r1,r2,r3);
4861
	      integer_branch(i_blt,r3,trap_label(e));
4862
	      test_unsigned(r0,0xffffffff,trap_label(e));
4863
	    }
4864
	    else{
4865
	      int r3 = getreg(sp.fixed);
4866
	      int oklab = new_label();
4867
	      operate_fmt(i_xor,r1,r2,r3);
4868
	      integer_branch(i_bge,r3,oklab);
4869
	      do_exception(f_overflow);
4870
	      set_label(oklab);
4871
	      test_unsigned_and_trap(r0,0xffffffff,f_overflow);
4872
	    }
4873
	    break;
4874
	  }
4875
	  case uwordhd :{
4876
	    if(error_treatment_is_trap(e)){
4877
	      test_unsigned_and_trap(r0,0xffff,f_overflow);
4878
	    }
4879
	    else{
4880
	      test_unsigned(r0,0xffff,trap_label(e));
4881
	    }
4882
	    break;
4883
	  }
4884
	  case swordhd :{
4885
	    if(error_treatment_is_trap(e)){
4886
	      test_signed_and_trap(r0,-0x8000L,0x7fff,f_overflow);
4887
	    }
4888
	    else{
4889
	      test_signed(r0,-0x8000L,0x7fff,trap_label(e));
4890
	    }
4891
	    break;
4892
	  }
4893
	  case ucharhd :{
4894
	    if(error_treatment_is_trap(e)){
4895
	      test_unsigned_and_trap(r0,255,f_overflow);
4896
	    }
4897
	    else{
4898
	      test_unsigned(r0,255,trap_label(e));
4899
	    }
4900
	    break;
4901
	  }
4902
	  case scharhd :{   
4903
	    if(error_treatment_is_trap(e)){
4904
	      test_signed_and_trap(r0,-128,127,f_overflow);
4905
	    }
4906
	    else{
4907
	      test_signed(r0,-128,127,trap_label(e));
4908
	    }
4909
	    break;
4910
	  }
4911
	  default:failer("illegal shape");
4912
	}
4913
	set_label(mult_end_lab);
4914
	setregalt(aa,r0);
4915
	mka.regmove = move(aa,dest,nsp,0);
4916
      }
4917
      return mka;
4918
    } /* end mult */
4919
 
4920
    case div1_tag :
4921
    case div2_tag : 
4922
    case offset_div_by_int_tag : 
4923
    case offset_div_tag : 
4924
    case div0_tag :{
4925
      exp rop = bro (son (e));
4926
      exp lop = son(e);
4927
      bool uns = (name (sh (e)) & 1) == 0; /* ?? */
4928
      space nsp;
4929
      int r0;
4930
      ans aa;
4931
      ash a;
4932
      instruction div_ins;
4933
      if (name (rop) == val_tag) { 
4934
	/* unsigned division by constant */
4935
	int   m = no (rop);
4936
	if((m == 0) && !optop(e)) {
4937
	  integer_branch(i_br,31,trap_label(e));
4938
	}
4939
 
4940
	if (m > 1 && (m & (m - 1)) == 0) {
4941
	  int   r = reg_operand (son (e), sp); 
4942
	  /* replace div by 2^shleng by arith sh right shleng */
4943
	  int   shleng;
4944
	  int   rr;
4945
	  for (shleng = 0; m != 1; shleng++)
4946
	    m >>= 1;
4947
 
4948
	  rr = regfrmdest(&dest, (guardreg(r,sp)));
4949
	  operate_fmt_immediate ((uns) ? i_srl : i_sra,r, shleng,rr);
4950
	  setregalt (aa, rr);
4951
	  mka.regmove = move (aa, dest, guardreg(r,guardreg (rr, sp)), 1);
4952
	  return mka; 
4953
	}
4954
	else if(use_umulh_for_div){
4955
	  if(m>0){		
4956
	    int r = reg_operand(son(e),sp);	
4957
	    int rr = regfrmdest(&dest,sp);	
4958
	    if(m!=1){		/* no point in dividing by 1 ! */
4959
#if DO_NEW_DIVISION
4960
	      divide_by_constant(e,lop,rop,rr,nsp);
4961
#else
4962
	      divide_by_constant(r,make_INT64(0,m),rr,guardreg(r,sp));
4963
#endif
4964
	    }
4965
	    else{
4966
	      rr=r;
4967
	    }
4968
	    setregalt (aa, rr);
4969
	    mka.regmove = move (aa, dest, guardreg (rr, sp), 1);
4970
	    return mka;
4971
	  }
4972
	}
4973
      }
4974
      a = ashof(sh(son(e)));
4975
      if (!optop(e) && !error_treatment_is_trap(e)) {/* test for (-inf)/-1 and /0 */
4976
	check_exception(e,sp);
4977
      }
4978
      nsp.fixed = (sp.fixed)|(1<<23)|(1<<24)|(1<<25)|(1<<27);
4979
      div_ins=(uns)?((a.ashsize==32)?i_divlu:i_divqu):
4980
	(a.ashsize==32)?i_divl:i_divq;
4981
      if(!optop(e) && !error_treatment_is_trap(e)){
4982
	int rd = reg_operand(rop,sp);
4983
	integer_branch(i_beq,rd,no(son(pt(e))));
4984
      }
4985
      r0 = divide_using_div(e,lop,rop,dest,nsp,div_ins);
4986
      setregalt(aa, r0);
4987
      clear_reg(AT);
4988
      clear_reg(23);
4989
      clear_reg(24);
4990
      clear_reg(25);
4991
      clear_reg(27);
4992
 
4993
      mka.regmove = move(aa, dest, guardreg(r0,sp), 0);
4994
      return mka;
4995
    }
4996
#if 0
4997
    case div1_tag: {  /* only applies to signed operands */
4998
      exp rop = bro (son (e));
4999
      exp lop = son(e);
5000
      int ne = name(e);
5001
      space nsp;
5002
      int r0, r1, r2;
5003
      int lab, treg;
5004
      ans aa;		
5005
      r2 = reg_operand(rop, sp);
5006
      nsp = guardreg(r2, sp);
5007
      r1 = reg_operand(lop, nsp);
5008
 
5009
 
5010
      if (!optop(e)) { /* test for (-inf)/-1 and /0 */
5011
	long over = new_label();
5012
	long trap = no (son (pt (e)));
5013
	ans aa;	   
5014
	set_label(over);      
5015
      }
5016
      r0 = regfrmdest(&dest,nsp);
5017
      treg = getreg(guardreg(r0,nsp).fixed);
5018
      lab = new_label();
5019
      operate_fmt(i_xor, treg, r2, treg);
5020
      operate_fmt(i_sra, treg, 31,treg);
5021
      operate_fmt(i_addq, r0,treg,r0);
5022
      set_label(lab);		
5023
      setregalt(aa, r0);
5024
      mka.regmove = move(aa, dest, guardreg(r0,sp), 0);
5025
      return mka;
5026
    }
5027
#endif
5028
 
5029
 
5030
    case neg_tag : 
5031
    case offset_negate_tag :{
5032
      if (optop(e) /* || (name(sh(e)) & 1) ==0 */ ) {
5033
	int r1=getreg(sp.fixed);
5034
	int a1;
5035
	space nsp;
5036
	a1 = reg_operand(son(e),sp);
5037
	if(dest.answhere.discrim == inreg) {
5038
	  int d = regalt(dest.answhere);
5039
	  operate_fmt(is64(sh(e))?i_subq:i_subl,31,a1,d);
5040
	  /*if (optop(e)) tidyshort(d,sh(e));*/
5041
	}
5042
	else {
5043
	  ans a;
5044
	  setregalt (a,r1);
5045
	  operate_fmt(is64(sh(e))?i_subq:i_subl,31,a1,r1);
5046
	  /*if (optop(e)) tidyshort(r1,sh(e));*/
5047
	  nsp=guardreg(r1,sp);
5048
	  move(a,dest,nsp,1);
5049
	  mka.regmove = r1;
5050
	}
5051
	return mka;
5052
      }	
5053
      else {
5054
	int r1 = reg_operand(son(e), sp);
5055
	space nsp;
5056
	/* int trap = trap_label(e); */
5057
	int r2;
5058
	ans aa;
5059
	nsp = guardreg(r1,sp);
5060
	r2 = getreg(nsp.fixed);
5061
	operate_fmt(i_subq,31,r1,r2);
5062
	switch(name(sh(e))){
5063
	  case ucharhd :{
5064
	    if(!optop(e)){
5065
	      if(error_treatment_is_trap(e)){
5066
		test_unsigned_and_trap(r2,255,f_overflow);
5067
	      }
5068
	      else{
5069
		test_unsigned(r2,255,trap_label(e));
5070
	      }
5071
	    }
5072
	    break;
5073
	  }
5074
	  case scharhd :{
5075
	    if(!optop(e)){
5076
	      if(error_treatment_is_trap(e)){
5077
		test_signed_and_trap(r2,-128,127,f_overflow);
5078
	      }
5079
	      else{
5080
		test_signed(r2,-128,127,trap_label(e));
5081
	      }
5082
	    }
5083
	    break;
5084
	  }
5085
	  case uwordhd :{
5086
	    if(!optop(e)){
5087
	      if(error_treatment_is_trap(e)){
5088
		test_unsigned_and_trap(r2,0xffff,f_overflow);
5089
	      }
5090
	      else{
5091
		test_unsigned(r2,0xffff,trap_label(e));
5092
	      }
5093
	    }
5094
	    break;
5095
	  }
5096
	  case swordhd : {
5097
	    if(!optop(e)){
5098
	      if(error_treatment_is_trap(e)){
5099
		test_signed_and_trap(r2,-0x8000L,0x7fff,f_overflow);
5100
	      }
5101
	      else{
5102
		test_signed(r2,-0x8000L,0x7fff,trap_label(e));
5103
	      }
5104
	    }
5105
	    break;
5106
	  }
5107
	  case ulonghd :{
5108
	    if(!optop(e)){
5109
	      if(error_treatment_is_trap(e)){
5110
		test_unsigned_and_trap(r2,0xffffffff,f_overflow);
5111
	      }
5112
	      else{
5113
		test_unsigned(r2,0xffffffff,trap_label(e));
5114
	      }
5115
	    }
5116
	    break;
5117
	  }
5118
	  case slonghd :{
5119
	    if(!optop(e)){
5120
	      if(error_treatment_is_trap(e)){
5121
		test_signed_and_trap(r2,-0x80000000L,0x7fffffff,f_overflow);
5122
	      }
5123
	      else{
5124
		test_signed(r2,-0x80000000L,0x7fffffff,trap_label(e));
5125
	      }
5126
	    }
5127
	    break;
5128
	  }
5129
	  case s64hd :{
5130
	    if(!optop(e)){
5131
	      if(error_treatment_is_trap(e)){
5132
		test_unsigned_and_trap(r1,0x7fffffffffffffffL,f_overflow);
5133
	      }
5134
	      else{
5135
		test_unsigned(r1,0x7fffffffffffffffL,trap_label(e));
5136
	      }
5137
	    }
5138
	    break;
5139
	  }
5140
	  case u64hd :{
5141
	    if(!optop(e)){
5142
	      if(error_treatment_is_trap(e)){
5143
		int new_lab = new_label();
5144
		integer_branch(i_ble,r1,new_lab);
5145
		do_exception(f_overflow);
5146
		set_label(new_lab);
5147
	      }
5148
	      else{
5149
		integer_branch(i_bgt,r1,trap_label(e));
5150
	      }
5151
	    }
5152
	    break;
5153
	  }
5154
 
5155
	  default:failer("Illegal shape in neg");
5156
	}
5157
 
5158
 
5159
	setregalt(aa, r2);
5160
	mka.regmove = move(aa, dest, guardreg(r2, nsp), 0);
5161
	return mka;
5162
      }
5163
 
5164
 
5165
    } /* end neg */
5166
 
5167
    case goto_lv_tag : {
5168
      int r = reg_operand(son(e),sp);
5169
      integer_jump(i_jmp,31,r,0);
5170
      clear_all();
5171
      return mka;
5172
    }
5173
    case movecont_tag :{
5174
      exp szarg = bro(bro(son(e)));
5175
      int dr, sr, szr, mr;
5176
      int lout = new_label();
5177
      space nsp;
5178
      int bytemove;
5179
      where w;
5180
 
5181
      sr = getreg(sp.fixed);
5182
      setregalt(w.answhere, sr);
5183
      w.ashwhere = ashof(sh(son(e)));
5184
      (void) make_code(son(e), sp, w , 0);
5185
      nsp = guardreg(sr, sp);
5186
      dr = getreg(nsp.fixed);
5187
      setregalt(w.answhere, dr);
5188
      (void)make_code(bro(son(e)), nsp, w, 0);
5189
      nsp = guardreg(dr, nsp);
5190
      w.ashwhere = ashof(sh(bro(bro(son(e)))));
5191
      szr = getreg(nsp.fixed);
5192
      setregalt(w.answhere, szr);
5193
      (void)make_code(szarg, nsp, w, 0);
5194
      nsp = guardreg(szr, nsp);
5195
      mr = getreg(nsp.fixed);
5196
      bytemove = al2(sh(szarg))>>3;
5197
 
5198
      if(name(szarg) != val_tag || no(szarg) == 0) {
5199
	integer_branch(i_beq,szr,lout);
5200
      } 
5201
      if (isnooverlap(e)) {
5202
	move_dlts(dr,sr,szr,mr, bytemove,sp);
5203
      }
5204
      else {
5205
	int gtlab = new_label();
5206
	int rtmp=getreg(nsp.fixed);
5207
	operate_fmt(i_cmple,dr,sr,rtmp);
5208
	integer_branch(i_beq,rtmp,gtlab);
5209
	move_dlts(dr,sr,szr, mr, bytemove,sp);
5210
	integer_branch(i_br,31,lout);
5211
	set_label(gtlab);
5212
	move_dgts(dr,sr,szr, mr, bytemove,sp);
5213
      }
5214
      set_label(lout);
5215
      return mka;
5216
    }
5217
    case set_stack_limit_tag : {
5218
      int reg = reg_operand(son(e),sp);
5219
      baseoff b;
5220
      /*      b = find_tag("__TDFstacklim");*/
5221
      b = find_tag("__alpha_stack_limit");
5222
      load_store(i_stq,reg,b);
5223
      return mka;
5224
    }
5225
    case give_stack_limit_tag : {
5226
      ans aa;
5227
      baseoff b;
5228
      int reg = regfrmdest(&dest,sp);
5229
      /*      b = find_tag("__TDFstacklim");*/
5230
      b = find_tag("__alpha_stack_limit");
5231
      load_store(i_ldq,reg,b);
5232
      setregalt(aa,reg);
5233
      move(aa,dest,guardreg(reg,sp),1);
5234
      return mka;
5235
    }
5236
    case shl_tag : 
5237
    case shr_tag :{
5238
      exp s = son (e);
5239
      exp b = bro (s);
5240
      int a;
5241
      int d; 
5242
      int src_reg;
5243
      ans aa;
5244
      space nsp;
5245
      bool sgned = is_signed(sh(e));
5246
      instruction shnat;
5247
      instruction shun;
5248
      a = reg_operand (s, sp);
5249
      /* choose which shift instruction */
5250
      if (name (e) == shr_tag) {
5251
	shnat = (sgned) ? i_sra : i_srl;
5252
	shun = i_sll;
5253
      }
5254
      else {
5255
	shnat = i_sll;
5256
	shun = (sgned) ? i_sra : i_srl;
5257
      }
5258
 
5259
      nsp = guardreg (a, sp);
5260
      d = regfrmdest(&dest, nsp);
5261
 
5262
      /* when applying right shifts to unsigned data which is less then
5263
	 the full (64 bit) register length, we must ensure that all the 
5264
	 unused bits in the upper part of the register are set to zero */
5265
     if(!is64(sh(son(e))) && !is_signed(sh(son(e))) 
5266
	 && ins_equal(i_srl,shnat)) {
5267
	src_reg = getreg(nsp.fixed);
5268
	if(name(sh(son(e))) == ulonghd)
5269
	  operate_fmt_immediate(i_zapnot,a,15,src_reg);
5270
	else if(name(sh(son(e))) == uwordhd) 
5271
	  operate_fmt_immediate(i_zapnot,a,3,src_reg);
5272
	else if (name(sh(son(e))) == ucharhd)
5273
	  operate_fmt_immediate(i_zapnot,a,1,src_reg);
5274
      }
5275
      else {
5276
	src_reg = a;
5277
      }
5278
      nsp = guardreg(src_reg,nsp);
5279
      if (name (b) == val_tag) {
5280
	/* if its a constant shift we dont have to choose shift
5281
	   dynamically ... */
5282
	if (no (b) >= 0) {
5283
#if 0
5284
	  if(!is64(sh(son(e))) && !is_signed(sh(son(e))) && 
5285
	     ins_equal(i_srl,shnat)){
5286
	    /* if quantity being shifted right is not 64 bits wide 
5287
	       then the top 32 bits of the register containing it
5288
	       must be set to zero.  This does not apply to 
5289
	       arithmetic shifts. */
5290
	    operate_fmt_immediate(i_zapnot,a,15,a);
5291
	  }
5292
#endif
5293
	  operate_fmt_immediate (shnat,src_reg, no (b),d);
5294
	}
5295
	else {
5296
	  operate_fmt_immediate (shun,src_reg, -no (b),d);
5297
	}
5298
      }
5299
      else {
5300
	int   sr = getreg (nsp.fixed);
5301
	int   ar = reg_operand (b, nsp);
5302
	if (!is_signed(sh(b))/* unsigned */
5303
	    || (name (b) == and_tag && name (bro (son (b))) == val_tag
5304
		&& no (bro (son (b))) > 0 && no (bro (son (b))) <= 31)
5305
	    ) {			/* ... similarly in these cases */
5306
	  operate_fmt (shnat,src_reg, ar,d);
5307
	}
5308
	else {		/* choose shift dynamically */
5309
	  int   l = new_label ();
5310
	  int   endl = new_label ();
5311
	  if(!is64(sh(son(e)))){
5312
	    operate_fmt_immediate(i_sll,src_reg,32,src_reg);
5313
	    operate_fmt_immediate(is_signed(sh(son(e)))?i_sra:i_srl,src_reg
5314
				  ,32,src_reg);
5315
	    /*operate_fmt_immediate(i_zap,a,240,a);*/	/* ?? */
5316
	  }
5317
	  integer_branch(i_bge,ar,l);
5318
	  operate_fmt(i_subq,31,ar,sr);
5319
	  operate_fmt(shun,src_reg, sr,d);
5320
	  integer_branch(i_br,31,endl);
5321
	  set_label (l);
5322
	  operate_fmt (shnat,src_reg, ar,d);
5323
	  set_label (endl);
5324
	}
5325
      }
5326
      if(is32(sh(e)) && (name(e) == shl_tag) ){
5327
	operate_fmt_immediate(i_addl,d,0,d);
5328
      }
5329
      setregalt (aa, d);
5330
      move (aa, dest, nsp, 1);
5331
      mka.regmove = d;
5332
      return mka;
5333
    } /* end shl */
5334
#if 0
5335
    case mod_tag :{
5336
      /* only applies to signed operands */
5337
      exp rop = bro (son (e));
5338
      exp lop = son(e);
5339
      int ne = name(e);
5340
      space nsp;
5341
      int r0, r1, r2;
5342
      int lab, treg;
5343
      ans aa;
5344
 
5345
      failer("mod_tag not implemented correctly");
5346
      r1 = reg_operand(lop, sp);
5347
      nsp = guardreg(r1, sp);
5348
      r2 = reg_operand(rop, nsp);
5349
 
5350
      if (!optop(e)) {		/* test for (-inf)/-1 and /0 */
5351
	long over = new_label();
5352
	long trap = no (son (pt (e)));
5353
	int rt = getreg(guardreg(r2,nsp).fixed);
5354
	ans aa;	   
5355
	integer_branch(i_beq,r2,trap);
5356
	operate_fmt_immediate(i_cmpeq,r2,-1,rt);
5357
	integer_branch(i_bne,r2,over);
5358
	operate_fmt_big_immediate(i_cmpeq,r1,maxmin(sh(e)).mini,rt);
5359
	integer_branch(i_beq,rt,trap);
5360
	set_label(over);       
5361
      }
5362
      r0 = regfrmdest(&dest, nsp);
5363
      failer("mod tag not implemented correctly");
5364
      /*	operate_fmt(i_rem, r0, r1, r2);*/
5365
      treg= getreg(guardreg(r0, nsp).fixed);
5366
      lab = new_label();
5367
      /*	condri_ins(i_beq, r0, 0, lab);*/
5368
      operate_fmt(i_xor, treg, r0, r2);
5369
      /*	condri_ins(i_bge, treg, 0, lab);*/
5370
      operate_fmt(i_addq, r0, r0, r2);
5371
      set_label(lab);		
5372
      setregalt(aa, r0);
5373
      mka.regmove = move(aa, dest, guardreg(r0,sp), 0);
5374
      return mka;
5375
    }    
5376
#endif     
5377
      /* Remainder operations have the same effect on the registers 
5378
	 AT,23,24,25 and 27 as the division operations, 
5379
	 so they must be treated in the same way.*/
5380
    case mod_tag :
5381
    case rem0_tag :
5382
    case rem2_tag :{
5383
      exp rop = bro (son (e));
5384
      exp lop = son(e);
5385
      bool uns = !is_signed(sh(e));
5386
      space nsp;
5387
      int r0,r1, r2;
5388
      ans aa;	
5389
#if 0
5390
      int size=dest.ashwhere.ashsize;
5391
#endif
5392
      nsp = sp;
5393
      if(name(rop)==val_tag){
5394
	/* if the second argument is a constant then we can 
5395
	   replace the rem* instruction by either an and 
5396
	   instruction, or an umulh and multiplication 
5397
	   followed by a subtraction */
5398
	int r = reg_operand(son(e),sp);
5399
	int m = no(rop);	/* value of constant */
5400
	int rres = regfrmdest(&dest,sp);
5401
	int rtmp = getreg(guardreg(rres,sp).fixed);
5402
 
5403
	if(m>1 && ((m&(m-1))==0)){
5404
	  /* if the constant is a power of 2 then use an and */
5405
	  ans aa;
5406
	  operate_fmt_immediate (i_and,r, no (rop) - 1,rres);
5407
	  setregalt (aa, rres);
5408
	  mka.regmove = move (aa, dest, guardreg (rres, sp), 1);
5409
	  return mka;
5410
	}
5411
	else{
5412
	  if(m!=1){
5413
	    if(use_umulh_for_div){
5414
#if DO_NEW_DIVISION
5415
	      divide_by_constant(e,lop,rop,rtmp,nsp);
5416
#else
5417
	      divide_by_constant(r,make_INT64(0,m),rtmp,guardreg(r,sp));
5418
#endif
5419
	    }
5420
	    else{
5421
	      if(!optop(e) && (m == 0)) {
5422
		if(error_treatment_is_trap(e)) {
5423
		  do_exception(f_overflow);
5424
		}
5425
		else {
5426
		  integer_branch(i_br,31,trap_label(e));
5427
		}
5428
	      }
5429
	      else {
5430
		operate_fmt_immediate(uns?i_divqu : i_divq,r,m,rtmp);
5431
	      }
5432
	    }
5433
	    operate_fmt_immediate(i_mulq,rtmp,m,rtmp);
5434
	    operate_fmt(i_subq,r,rtmp,rres);
5435
	  }
5436
	  else{
5437
	    load_store_immediate(i_ldiq,rres,make_INT64(0,0));
5438
	  }
5439
	  setregalt(aa,rres);
5440
	  mka.regmove = move(aa, dest, guardreg(rres,sp), 1);
5441
	  return mka;
5442
	}
5443
      }
5444
 
5445
      nsp.fixed |= ((1<<23)|(1<<24)|(1<<25)|(1<<27));
5446
      r1 = reg_operand(lop, nsp);
5447
      clear_reg(23);
5448
      clear_reg(24);
5449
      clear_reg(25);
5450
      clear_reg(27);
5451
      nsp = guardreg(r1, nsp);
5452
      r2 = reg_operand(rop, nsp);
5453
 
5454
      if (!optop(e)) {		/* test for (-inf)/-1 and /0 */
5455
	check_exception(e,nsp);
5456
      }
5457
      if ((r0 = regfrmdest(&dest, nsp)) == NO_REG) {
5458
	r0  = getreg(nsp.fixed);
5459
      }
5460
      nsp = guardreg(r0,nsp);
5461
      if(!optop(e)) {
5462
	integer_branch(i_beq,r2,trap_label(e));
5463
      }
5464
      operate_fmt((uns)?((is64(sh(e)))?i_remqu : i_remlu):
5465
		  ((is64(sh(e)))?i_remq : i_reml),r1,r2,r0);
5466
#if 0      
5467
      operate_fmt((uns)?((size==32)?i_remlu:i_remqu):
5468
		  ((size==32)?i_reml:i_remq),
5469
		  r1,r2,r0);
5470
#endif
5471
      if(name(e) == mod_tag){
5472
	int res_neg = new_label();
5473
	int exitlab = new_label();
5474
	integer_branch(i_beq,r0,exitlab);
5475
	integer_branch(i_blt,r0,res_neg);
5476
	integer_branch(i_bge,r2,exitlab);
5477
#if 0
5478
	operate_fmt((size == 32)?i_addl:i_addq,r0,r2,r0);
5479
#endif
5480
	operate_fmt(is64(sh(e))?i_addq : i_addl,r0,r2,r0);
5481
	integer_branch(i_br,31,exitlab);
5482
	set_label(res_neg);
5483
	integer_branch(i_ble,r2,exitlab);
5484
#if 0
5485
	operate_fmt((size == 32)?i_addl:i_addq,r0,r2,r0);
5486
#endif
5487
	operate_fmt(is64(sh(e))? i_addq : i_addl,r0,r2,r0);
5488
	set_label(exitlab);
5489
      }
5490
 
5491
 
5492
      setregalt(aa, r0);
5493
      if((r2 == 23) || (r2 == 24) || (r2 == 25) || (r2 == AT)){
5494
	clear_dep_reg(rop);
5495
      }
5496
      if((r1 == 23) || (r1 == 24) || (r1 == 25) || (r1 == AT)){
5497
	clear_dep_reg(lop);
5498
      }   
5499
      clear_reg(23);
5500
      clear_reg(24);
5501
      clear_reg(25);
5502
      clear_reg(27);       
5503
      mka.regmove = move(aa, dest, guardreg(r0,nsp), 0);
5504
      return mka;
5505
 
5506
    } /* end mod */
5507
 
5508
 
5509
    case offset_pad_tag :{
5510
      int rdest = regfrmdest(&dest,sp);
5511
      int roff = reg_operand(son(e),sp);
5512
      ans aa;
5513
      if (al2(sh(son(e))) >= al2(sh(e))){
5514
	if (al2(sh(e))!=1 || al2(sh(son(e)))==1){
5515
	  e = son(e);
5516
	  goto tailrecurse;
5517
	}
5518
	operate_fmt_immediate(i_sll,roff,3,rdest);
5519
      }
5520
      else{
5521
	int al = (al2(sh(son(e)))==1)?al2(sh(e)):(al2(sh(e))/8);
5522
	operate_fmt_immediate(i_addq,roff,al-1,rdest);
5523
	operate_fmt_immediate(i_and,rdest,-al,rdest);
5524
	if(al2(sh(son(e))) == 1){
5525
	  operate_fmt_immediate(i_sra,rdest,3,rdest);
5526
	}
5527
      }
5528
      setregalt(aa,rdest);
5529
      mka.regmove = move(aa,dest,guardreg(rdest,sp),0);
5530
      return mka;
5531
    }
5532
#ifdef make_stack_limit_tag       
5533
    case make_stack_limit_tag :
5534
#endif
5535
    case minptr_tag :{
5536
      mka.regmove = non_comm_op (e, sp, dest, i_subq);
5537
      return mka;
5538
    }
5539
    case abs_tag : {
5540
      int arg = reg_operand(son(e),sp);
5541
      int rtmp = getreg(guardreg(arg,sp).fixed);
5542
      int destreg;
5543
      ans tmp;
5544
      switch(dest.answhere.discrim){
5545
        case inreg :{
5546
	  destreg = regalt(dest.answhere);
5547
	  break;
5548
	}
5549
        default:{
5550
	  destreg = getreg(sp.fixed);
5551
	  break;
5552
	}
5553
      }
5554
      if (destreg == NO_REG) destreg = getreg(sp.fixed);
5555
 
5556
      operate_fmt(i_bis,arg,arg,destreg);
5557
      operate_fmt(i_subq,31,arg,rtmp);
5558
      operate_fmt(i_cmovgt,rtmp,rtmp,destreg);
5559
      if(!optop(e) /*&& !error_treatment_is_trap(e)*/) {
5560
	int rt = getreg(sp.fixed);
5561
	operate_fmt_big_immediate(i_subq,destreg,maxmin(sh(e)).maxi,rt);
5562
	if(error_treatment_is_trap(e)){
5563
	  int newl = new_label();
5564
	  integer_branch(i_ble,rt,newl);
5565
	  do_exception(f_overflow);
5566
	  set_label(newl);
5567
	}
5568
	else{
5569
	  integer_branch(i_bgt,rt,trap_label(e));
5570
	}
5571
      }
5572
      setregalt(tmp,destreg);
5573
      mka.regmove = move(tmp,dest,sp,1);
5574
      return mka;
5575
    }
5576
    case fplus_tag :{
5577
      mka.regmove =
5578
	fop (e, sp, dest, (name (sh (e)) != shrealhd) ? i_addt : i_adds);
5579
      if((name(sh(e))!=shrealhd) && 
5580
	 (fregalt(dest.answhere).type==IEEE_single) && 
5581
	 dest.answhere.discrim==infreg){
5582
      }
5583
      if (!optop(e)) check_exception(e, sp);	  
5584
      return mka;
5585
    }
5586
 
5587
    case fminus_tag :{
5588
      mka.regmove =
5589
	fop (e, sp, dest, (name (sh (e)) != shrealhd) ? i_subt : i_subs);
5590
      if (!optop(e)) check_exception(e,sp);	  
5591
      return mka;
5592
    }
5593
 
5594
    case fmult_tag :{
5595
      instruction mult_ins;
5596
      mult_ins = (name(sh(e)) != shrealhd)?i_mult:i_muls;
5597
      mka.regmove = fop (e, sp, dest, mult_ins);
5598
      if (!optop(e) && !error_treatment_is_trap(e)) check_exception(e,sp);
5599
      return mka;
5600
    }
5601
 
5602
    case fdiv_tag :{
5603
      instruction div_ins;
5604
      div_ins = (name(sh(e)) != shrealhd)?i_divt:i_divs;
5605
      /*
5606
	if(!optop(e)){
5607
	div_ins = (name(sh(e)) != shrealhd)?i_divtsu:i_divssu;
5608
	}
5609
	else{
5610
	div_ins = (name(sh(e)) != shrealhd)?i_divt:i_divs;
5611
	}
5612
	*/
5613
      if(!optop(e) && !error_treatment_is_trap(e)){
5614
	int fr = freg_operand(bro(son(e)),sp);
5615
	float_branch(i_fbeq,fr,no(son(pt(e))));
5616
      }
5617
      mka.regmove = fop (e, sp, dest, div_ins);
5618
      if (!optop(e) && !error_treatment_is_trap(e)) check_exception(e,sp);	  
5619
      return mka;
5620
    }
5621
 
5622
    case fneg_tag : 
5623
    case fabs_tag :{
5624
      instruction ins;
5625
      freg fr;
5626
      int arg=freg_operand(son(e),sp);
5627
      if(name(e) == fneg_tag){
5628
	if(optop(e)) ins = (name(sh(e)) != shrealhd)?i_subt:i_subs;
5629
	else
5630
	  ins = (name(sh(e)) != shrealhd)?i_subtsu:i_subssu;
5631
      }
5632
      else{
5633
	ins = i_cpys;
5634
      }
5635
      switch(dest.answhere.discrim){
5636
	case infreg :{
5637
	  fr=fregalt(dest.answhere);
5638
	  float_op(ins,31,arg,fr.fr);
5639
	  break;
5640
	}
5641
	default :{
5642
	  ans tmp;
5643
	  fr.type=(dest.ashwhere.ashsize==32)?IEEE_single:IEEE_double;
5644
	  fr.fr=getfreg(sp.flt);
5645
	  setfregalt(tmp,fr);
5646
	  float_op(ins,31,arg,fr.fr);
5647
	  move(tmp,dest,sp,1);
5648
	}
5649
      }
5650
      if (!optop(e) && (name(e)==fneg_tag) && !error_treatment_is_trap(e)) 
5651
	check_exception(e,sp);	
5652
      mka.regmove=((fr.type==IEEE_double)? -(fr.fr+32):(fr.fr+32));
5653
      return mka;
5654
    }
5655
 
5656
    case float_tag : {
5657
      exp in = son (e);
5658
      where w;
5659
      int r;
5660
      int   f
5661
	=     (dest.answhere.discrim == infreg) ? regalt (dest.answhere)
5662
	:     getfreg (sp.flt);
5663
      freg frg;
5664
      ans aa;
5665
      ash ain;
5666
      bool quad;
5667
      ain = ashof (sh (in));
5668
      quad = (ain.ashsize!=32);
5669
      frg.fr = f;
5670
      frg.type = IEEE_single;
5671
      if(ain.ashsize<32){
5672
	/* go via fixed point register for bytes and words */
5673
	where tmp;
5674
	ans src;
5675
	r=reg_operand(in,sp);
5676
	setregalt(tmp.answhere,r);
5677
	tmp.ashwhere=ashof(sh(in));
5678
	/*code_here(in,sp,tmp);*/	/* move it into fixed pt reg r */
5679
	setregalt(src,r);
5680
	frg.type=IEEE_double;
5681
	setfregalt(tmp.answhere,frg);
5682
	move(src,tmp,sp,0);
5683
      }
5684
      else{
5685
	switch(name(sh(in))){
5686
	  case swordhd :
5687
	  case uwordhd :
5688
	  case slonghd :
5689
	  case ulonghd :
5690
	  case s64hd :
5691
	  case u64hd :{
5692
	    freg load_reg;
5693
	    load_reg.type = IEEE_double; /* so we load in an octaword */
5694
	    load_reg.fr=f;
5695
	    setfregalt(w.answhere,load_reg);
5696
	    w.ashwhere=ashof(sh(in));
5697
	    code_here(in,sp,w);
5698
	    break;
5699
	  }
5700
	  default:
5701
	  setfregalt(w.answhere,frg);
5702
	  w.ashwhere = ashof(sh(in));
5703
	  code_here(in,sp,w);
5704
	  break;
5705
	}	
5706
      }
5707
      if(!quad){
5708
	float_convert(i_cvtlq,f,f);
5709
      }
5710
      float_convert((name(sh(e))==shrealhd)?i_cvtqs:i_cvtqt,f,f);
5711
      if (name (sh (e)) != shrealhd) {
5712
	frg.type = IEEE_double;
5713
      }
5714
      setfregalt (aa, frg);
5715
      move (aa, dest, sp, 1);
5716
      if(name(sh(in))==u64hd||(name(sh(in))==ulonghd)){
5717
	fix_unsigned(frg,sp,name(sh(in)));
5718
      }
5719
      mka.regmove = (frg.type==IEEE_double) ? -(f + 32) : (f + 32);
5720
      return mka;
5721
    }
5722
    case chfl_tag :{
5723
      int   to = name (sh (e));
5724
      int   from = name (sh (son (e)));
5725
      bool dto = (to != shrealhd) ? 1 : 0;
5726
      bool dfrom = (from != shrealhd) ? 1 : 0;
5727
      if (!dto && !dfrom) {	/* no change in representation */
5728
	return make_code (son (e), sp, dest, exitlab);
5729
      }
5730
      else {
5731
	freg frg;
5732
	ans aa;
5733
	where w;
5734
	if (dest.answhere.discrim == infreg) {
5735
	  frg = fregalt (dest.answhere);
5736
	}
5737
	else {
5738
	  frg.fr = getfreg (sp.flt);
5739
	}
5740
	if(dto)		/* was dfrom */
5741
	  frg.type = IEEE_double;
5742
	else
5743
	  frg.type = IEEE_single;
5744
	setfregalt (aa, frg);
5745
	w.answhere = aa;
5746
	w.ashwhere = ashof (sh (son (e)));
5747
	code_here (son (e), sp, w);
5748
	if(dto)
5749
	  frg.type = IEEE_double;
5750
	else
5751
	  frg.type = IEEE_single;
5752
	if((!dto) && dfrom){
5753
	  /* If converting from double to single then we 
5754
	     need to use a conversion */
5755
	  float_convert(i_cvtts,frg.fr,frg.fr);
5756
	}
5757
	setfregalt (aa, frg);
5758
	move (aa, dest, sp, 1);
5759
	mka.regmove = (frg.type==IEEE_double)?-(frg.fr + 32):(frg.fr + 32);
5760
	if (!optop(e) && !dto && !error_treatment_is_trap(e)) check_exception(e,sp);	  
5761
	return mka;
5762
      }
5763
    }
5764
 
5765
    case and_tag : {
5766
      if(use_andcomp && name(bro(son(e))) == not_tag){
5767
	bro(son(e)) = son(bro(son(e)));
5768
	mka.regmove = comm_op (e,sp,dest,i_bic);
5769
      }
5770
      else if(use_andcomp && name(son(e)) == not_tag){
5771
	exp tmp = copyexp(son(e));
5772
	son(e) = bro(son(e));
5773
	bro(son(e)) = son(tmp);
5774
	/*retcell(tmp)*/;
5775
	mka.regmove = comm_op (e,sp,dest,i_bic);
5776
      }
5777
      else
5778
	mka.regmove = comm_op (e, sp, dest, i_and);
5779
      return mka;
5780
    }
5781
    case andcomp_tag :{
5782
      mka.regmove = comm_op(e,sp,dest,i_bic);
5783
      return mka;
5784
    }
5785
    case or_tag : {
5786
      mka.regmove = comm_op (e, sp, dest, i_bis);
5787
      return mka;
5788
    }
5789
 
5790
    case xor_tag :{
5791
      mka.regmove = comm_op (e, sp, dest, i_xor);
5792
      return mka;
5793
    }
5794
 
5795
    case not_tag : {
5796
      int arg=reg_operand(son(e),sp);
5797
      switch(dest.answhere.discrim){
5798
	case inreg :{
5799
	  int the_dest = regalt(dest.answhere);
5800
	  operate_fmt(i_ornot,31,arg,the_dest);
5801
	  break;
5802
	}
5803
	default:{
5804
	  ans a;
5805
	  space nsp;
5806
	  int reg=getreg(sp.fixed);
5807
	  setregalt(a,reg);
5808
	  operate_fmt(i_ornot,31,arg,reg);
5809
	  tidyshort(reg,sh(e));
5810
	  nsp=guardreg(reg,sp);
5811
	  move(a,dest,nsp,is_signed(sh(e)));
5812
	}
5813
      }
5814
      return mka;
5815
    }
5816
    case locptr_tag : {
5817
      int ptr = reg_operand(son(e),sp);
5818
      int ansr = regfrmdest(&dest,sp);
5819
      baseoff b;
5820
      ans aa;
5821
      b.base = ptr;
5822
      b.offset = -arg_stack_space -3*(PTR_SZ>>3);
5823
      load_store(i_ldq,ansr,b);
5824
      setregalt(aa,ansr);
5825
      mka.regmove = move(aa,dest,guardreg(ansr,sp),0);
5826
      return mka;
5827
    }
5828
 
5829
    case cont_tag : 
5830
    case name_tag : 
5831
    case field_tag : 
5832
    case reff_tag : 
5833
    case addptr_tag : 
5834
    case subptr_tag :  
5835
    case contvol_tag : {
5836
      where w;
5837
      bool sgned;
5838
      ash desper;
5839
      int dr=(dest.answhere.discrim == inreg)?dest.answhere.val.regans:NO_REG;
5840
      desper = ashof (sh (e));
5841
 
5842
      if (name (e) == contvol_tag) {
5843
	clear_all ();
5844
	/*setvolatile ();*/
5845
      }
5846
      clear_dep_reg(e);
5847
 
5848
      w = locate (e, guardreg(dr,sp), sh (e), dr);
5849
      /* 'address of argument */
5850
      /*sgned = ((w.ashwhere.ashsize >= 64) 
5851
	|| name (sh (e)) & 1) ? 1 : 0;*/
5852
      sgned = is_signed(sh(e));
5853
      mka.regmove = move (w.answhere, dest, (guard (w, sp)), sgned);
5854
      clear_dep_reg(e);
5855
      if (name (e) == contvol_tag) {
5856
	mka.regmove = NOREG;
5857
	/* setnovolatile ();*/
5858
      }
5859
      return mka;
5860
    } /* end cont */
5861
 
5862
#if (FBASE != 10)
5863
    case real_tag :
5864
#endif
5865
    case string_tag :{
5866
      instore isa;
5867
      ans aa;
5868
      bool sgned = ((ashof (sh (e)).ashsize >= 32) || name (sh (e)) & 1) ? 1 : 0;
5869
      if(name(e)==real_tag){
5870
	bool is_denorm = is_denormal(e);
5871
	if(is_fzero(flptnos[no(e)]) || (is_denorm && treat_denorm_specially)){
5872
	  freg frg;
5873
	  frg.fr = 31;
5874
	  frg.type = (shape_size(sh(e)) == 32)?IEEE_single:IEEE_double;
5875
	  setfregalt(aa,frg);
5876
	  mka.regmove = move(aa,dest,sp,sgned);
5877
	  if(is_denorm){
5878
	    if(fail_with_denormal_constant){
5879
	      failer("Denormalised constant encountered");
5880
	      exit(EXIT_FAILURE);
5881
	    }
5882
	    alphawarn("Replaced IEEE denormal with 0.0!");
5883
	    comment("Replaced IEEE denormal with 0.0");
5884
	  }
5885
	  return mka;
5886
	}
5887
      }
5888
#if DO_SCHEDULE
5889
      start_new_capsule(false);
5890
#endif       
5891
      isa=evaluated(e,0);
5892
      set_text_section();
5893
#if DO_SCHEDULE
5894
      close_capsule();
5895
#endif
5896
      setinsalt(aa,isa);
5897
      mka.regmove=move(aa,dest,sp,sgned);
5898
      return mka;
5899
    }
5900
#if (FBASE == 10)	/* now defunct */
5901
    case real_tag :{
5902
      instore isa;
5903
      ans aa;
5904
      char *flt_string;	/* a string representing the real literal */
5905
      char *ld_ins;		
5906
      freg fr;
5907
      int use_fzero;		/* set if value of real is 0.0 */
5908
 
5909
      bool sgned = ((ashof (sh (e)).ashsize >= 32) || name (sh (e)) & 1) ? 1 : 0;
5910
      flt_string = floating_value(e);
5911
      use_fzero = !strcmp(flt_string,"0.0");
5912
      switch(dest.answhere.discrim){
5913
	case infreg :
5914
	fr.fr = regalt(dest.answhere);
5915
	fr.type = (dest.ashwhere.ashsize==32)?IEEE_single:IEEE_double;
5916
	break;
5917
	case insomefreg :
5918
	if(!use_fzero){
5919
	  fr.fr = getfreg(sp.flt);
5920
	  fr.type = (dest.ashwhere.ashsize==32)?IEEE_single:IEEE_double;
5921
	}
5922
	break;
5923
	case notinreg :
5924
	fr.fr=getfreg(sp.flt);
5925
	fr.type=(dest.ashwhere.ashsize==32)?IEEE_single:IEEE_double;
5926
	break;
5927
	default:
5928
	  failer("dubious target for real_tag ");
5929
	}
5930
      ld_ins = (fr.type==IEEE_single)?i_ldis:i_ldit;
5931
      if(use_fzero){
5932
	if(dest.answhere.discrim==insomefreg){
5933
	  *dest.answhere.val.somefregans.fr=31;
5934
	  return mka;
5935
	}
5936
	else
5937
	  float_op(i_cpys,31,31,fr.fr);
5938
      }
5939
      else
5940
	float_load_store_immediate(ld_ins,fr.fr,flt_string);
5941
      if(dest.answhere.discrim==insomefreg)
5942
	*dest.answhere.val.somefregans.fr = fr.fr;
5943
      if(dest.answhere.discrim==notinreg){
5944
	/* put reg contents into memory */
5945
	ans src;
5946
	setfregalt(src,fr);
5947
	mka.regmove=move(src,dest,sp,sgned);
5948
      }
5949
      return mka;
5950
    } /* end eval */
5951
#endif /* (FBASE==10) */
5952
 
5953
    case val_tag : {
5954
      if (no (e) == 0 && !isbigval(e)) {
5955
	goto null_tag_case;
5956
      }
5957
      else {
5958
	ash a;
5959
	a = ashof (sh (e));
5960
	switch(a.ashsize)	{
5961
	  case 8 :{
5962
	    low_INT64(constval) = no(e)&255;
5963
	    if(is_signed(sh(e)))
5964
	      low_INT64(constval) -= (low_INT64(constval)&128)<<1;
5965
	    break;
5966
	  }
5967
	  case 32 :{
5968
	    low_INT64(constval) = no(e);
5969
	  }
5970
 
5971
#if 0	   
5972
	    if(is_signed(sh(e))){
5973
	      low_INT64(constval) = no(e);
5974
	    }
5975
	    else{
5976
	      low_INT64(constval) = uno(e);
5977
	    }
5978
#endif
5979
	    break;
5980
	  case 64 :{
5981
	    int findex = no(e);
5982
	    int ov;
5983
	    if(isbigval(e)){
5984
	      flt64 res;
5985
	      res = flt_to_f64(findex,is_signed(sh(e)),&ov);
5986
	      INT64_assign(constval, flt64_to_INT64(res));
5987
	    }
5988
	    else low_INT64(constval) = no(e);
5989
	    break;
5990
	  }
5991
	  default:{
5992
	    low_INT64(constval)  = no(e)&65535;
5993
	    if(is_signed(sh(e)))
5994
	      low_INT64(constval)  -= (low_INT64(constval)&32768)<<1 ;
5995
	    break;
5996
	  }
5997
	}
5998
 
5999
	goto moveconst;
6000
      }
6001
    }
6002
    case prof_tag :
6003
    case top_tag : {
6004
      return mka;
6005
    }
6006
    case dump_tag : {
6007
      int fxd = no(e);
6008
      int fld = no(pt(e));
6009
      int old_fixdone = fixdone;
6010
      int old_fltdone = fltdone;
6011
      int old_result_label = result_label;
6012
      exp l;
6013
      result_label=0;
6014
      dump_sregs(fxd, fld);
6015
      if ((fxd &(1<<RA))) sp.fixed &= ~(1<<RA); 
6016
      for(l=son(crt_proc); name(l)==ident_tag && isparam(l); ){
6017
	/* move any pars still in registers which go into dump regs */
6018
	int sr = props(son(l));
6019
	int tr = no(l);
6020
	if ((props(l) & inanyreg)!=0 && (tr !=sr) && sr != 0) {
6021
	  if ((props(l) & infreg_bits)!=0 && 
6022
	      (fld &(1<<(sr))) !=0 ) {
6023
	    if (name(sh(son(l))) != shrealhd) {
6024
	      float_op(i_cpys,tr,tr,sr);
6025
	    }
6026
	    else {
6027
	      float_op(i_cpys,tr,tr,sr);
6028
	    }
6029
	    sp.flt &= ~(1<<tr); /* release fpar reg */
6030
	    no(l) = sr; props(son(l)) = tr;
6031
	  }
6032
	  else
6033
	    if (((fxd & (1<<sr)) !=0) && (props(l) & inreg_bits) ) {
6034
	      operate_fmt(i_bis,tr,tr,sr);
6035
	      sp.fixed &= ~(1<<tr); /* release par reg */
6036
	      no(l)=sr; props(son(l)) = tr;
6037
	    }
6038
	}
6039
	l = bro(son(l));
6040
	if (name(l)==dump_tag) l = son(l);
6041
      }
6042
      code_here(son(e), sp, dest);
6043
      for(l=son(crt_proc); name(l)==ident_tag && isparam(l); ){
6044
	/* restore structure of moved pars */
6045
	int sr = props(son(l));
6046
	int tr = no(l);
6047
	if ((props(l) & inanyreg)!=0 && (tr !=sr) && sr != 0) {
6048
	  if ((props(l) & infreg_bits)!=0 && 
6049
	      (fld &(1<<(tr<<1))) !=0 ) {
6050
	    no(l) = sr; props(son(l)) = tr;
6051
	  }
6052
	  else
6053
	    if ((fxd & (1<<tr)) !=0 ) {
6054
	      no(l)=sr; props(son(l)) = tr;
6055
	    }
6056
	}
6057
	l = bro(son(l));
6058
	if (name(l)==dump_tag) l = son(l);
6059
      }        
6060
      if (name(sh(e)) != bothd) {
6061
	restore_sregs(fxd, fld);
6062
      }
6063
      fixdone = old_fixdone;
6064
      fltdone = old_fltdone;
6065
      result_label = old_result_label;
6066
      return mka;
6067
    }	
6068
 
6069
    case env_size_tag : {
6070
      exp tg = son(son(e));
6071
      procrec *pr = &procrecs[no(son(tg))];
6072
      constval = (pr->frame_size+pr->callee_size) >> 3;
6073
      goto moveconst;
6074
    }
6075
 
6076
    case general_proc_tag :
6077
    case proc_tag : {
6078
      /* 
6079
	 set up locals_offset, fixdump, floatdump, 
6080
	 frame_size, dumpstart
6081
	 dec stack  ; output frame and mask 
6082
	 code here;
6083
 
6084
	 The standard stack layout for a make_proc is as follows:
6085
 
6086
	 -------------------------------------  Bottom of env
6087
	 space for caller params to be passed on stack
6088
	 (If containing apply or apply_general)
6089
 
6090
	 space for dumped s registers
6091
	 locals
6092
	 space for dumped arguments (first 6)
6093
	 -------------------------------------- Top of env
6094
	 remaining arguments (in callers frame)
6095
 
6096
 
6097
	 for general procs the frame will be set up as follows:
6098
 
6099
	 ----------------------------  Bottom of callee env
6100
	 extra caller parameters (If containing apply or apply_general)
6101
	 callee parameters (1,2,,,,,) 
6102
	 space for dumped s registers
6103
	 locals				
6104
	 caller local reg
6105
	 callee local reg
6106
	 callee top of stack
6107
	 caller frame pointer		
6108
	 Up to 6 caller parameters
6109
	 --------------------------- Top of callee env
6110
	 Any remaining caller parameters
6111
	 */
6112
 
6113
      procrec * pr = & procrecs[no(e)];			 
6114
      needs * ndpr = & pr->needsproc;
6115
      long pprops = (ndpr->propsneeds);
6116
      bool leaf = (pprops & anyproccall) == 0; 
6117
      space tbd;
6118
      space pars;
6119
      long st;
6120
      exp l;
6121
      int i;
6122
      int has_va;
6123
      setframe_flags(e, leaf); 	
6124
      has_va = has_c_vararg(e) || ((name(e) == general_proc_tag) && 
6125
				   (!Has_no_vcallers));
6126
      in_general_proc = ( name(e)==general_proc_tag );
6127
      old_postludes = (postlude_chain*)NULL;
6128
      crt_proc = e;
6129
      frame_size = pr->frame_size;
6130
      locals_offset = pr->locals_offset;
6131
      max_args = pr->max_args;
6132
      param_stack_space = (min(max_args,
6133
			       (Has_no_vcallers)?6*PTR_SZ : 12*PTR_SZ))>>3;
6134
      arg_stack_space = min(pr->needsproc.numparams,
6135
			    (has_va)?12*PTR_SZ : 6*PTR_SZ)>>3;
6136
#if 0
6137
      if(pr->needsproc.numparams > 11 * PTR_SZ) {
6138
	arg_stack_space = 12*PTR_SZ;
6139
      }
6140
      else {
6141
	arg_stack_space = max(pr->needsproc.numparams,
6142
			      (Has_no_vcallers?6*PTR_SZ : 12*PTR_SZ));
6143
      }
6144
#endif      
6145
 
6146
      /* this doesn't actually waste much space, and simplifies matters 
6147
	 later */
6148
      if(name(e) == general_proc_tag /* || proc_has_gen_call(e)*/) {
6149
	int old_arg_count = arg_stack_space;
6150
	arg_stack_space = ((has_va)?12*PTR_SZ : 6*PTR_SZ)>>3;
6151
	if(arg_stack_space > old_arg_count)
6152
	  frame_size += ((arg_stack_space - old_arg_count)<<3);
6153
      }
6154
 
6155
      /*
6156
	param_stack_space contains the maximum number of bytes 
6157
	that will be required to save the registers used by this
6158
	proc when passing parameters to other procedures.  As
6159
	the space is actually allocated in the callee frame, this
6160
	is only needed for apply_general_proc.  arg_stack_space
6161
	contains the number of arguments passed to this proc, 
6162
	and for which space must be reserved within the current
6163
	frame. 
6164
	*/
6165
      for(i=0;i<min(pr->needsproc.numparams>>6,NUM_PARAM_REGS);++i){
6166
	sp = guardreg(FIRST_INT_ARG+i,sp);
6167
      }
6168
 
6169
      paramsdumpstart = pr->paramsdumpstart;
6170
      /* the fixed point registers will be stored in the space 
6171
	 starting from gpdumpstart */
6172
      gpdumpstart = (has_va)?paramsdumpstart+384:paramsdumpstart;
6173
      proc_has_vararg = (has_va)?1:0;
6174
      fixdump = pr->fixdump;
6175
      floatdump = pr->floatdump;
6176
      dumpstart = pr->dumpstart;
6177
      fldumpstart = pr->fldumpstart;
6178
      callee_size = pr->callee_size;
6179
      stack_top=(locals_offset>>3)-8;
6180
 
6181
 
6182
      st = (frame_size+callee_size) >> 3;
6183
      fixdone = fltdone = 0;	/* no s-regs have been dumped yet */
6184
 
6185
 
6186
      tbd.fixed = fixdump;
6187
      tbd.flt = floatdump;
6188
 
6189
      pars.fixed = (leaf)?0:(1<<RA); 
6190
      pars.flt = 0;
6191
      for (l = son(e); name(l) == ident_tag && isparam(l) &&
6192
			 name(son(l))!=formal_callee_tag; l = bro(son(l))) {
6193
	if ((props(l) & infreg_bits)!= 0) {
6194
	  int n = props(son(l));
6195
	  if (n != no(l) && n != 0) {
6196
	    pars.flt |= (1<<no(l));
6197
	  }
6198
	}
6199
	else if ((props(l) & inreg_bits)!=0) {
6200
	  int n = props(son(l));
6201
	  if (n != no(l) && n != 0) {
6202
	    pars.fixed |= (1<<no(l));
6203
	  }
6204
	}
6205
      }	
6206
 
6207
      dump_opt(e, &tbd, &pars);
6208
      set_global_pointer();
6209
 
6210
      if (name(e)==general_proc_tag) {	
6211
	if (Has_vcallees) {
6212
	  baseoff b;
6213
	  b.base = FP;
6214
	  b.offset = (-4 * PTR_SZ>>3) - arg_stack_space;
6215
	  load_store(i_stq, local_reg, b); 
6216
	  operate_fmt(i_bis,SP,SP,local_reg);
6217
	  if(!leaf) {
6218
	    b.offset = (-3*PTR_SZ>>3) - arg_stack_space;
6219
	    load_store(i_stq, local_reg, b);
6220
	  }
6221
	}
6222
	else if (Has_fp && name(e)==general_proc_tag) {
6223
	  operate_fmt_immediate(i_addq,SP, arg_stack_space+
6224
				(callee_size>>3),FP);
6225
	}
6226
#if DO_SCHEDULE
6227
	close_capsule();
6228
	start_new_capsule(true);
6229
#endif
6230
	if(frame_size != 0 || callee_size!=0){
6231
	  operate_fmt_immediate(i_subq,SP,(frame_size+callee_size)>>3,SP);
6232
	}
6233
      }
6234
      else{
6235
	if (st != 0) {
6236
	  baseoff a;
6237
	  a.base = SP;
6238
	  a.offset=-st;
6239
	  load_store(i_lda,SP,a);
6240
	}
6241
	setframe (st,0);
6242
	/* I'm not sure that this is the right order for these -
6243
	   diagnostics ? */
6244
 
6245
	setprologue(2);
6246
#if DO_SCHEDULE
6247
	close_capsule();
6248
	start_new_capsule(true);
6249
#endif
6250
	if (Has_fp) {
6251
	  baseoff b;
6252
	  b.base = SP;
6253
#if 0
6254
	  b.offset = ((callee_size+frame_size)>>3)-
6255
	    arg_stack_space-(PTR_SZ>>3);
6256
#endif
6257
	  b.offset = ((callee_size+frame_size-PTR_SZ)>>3) - 
6258
	    ((in_general_proc)?0:arg_stack_space);
6259
 
6260
	  b.offset = ((callee_size+frame_size-PTR_SZ)>>3) - 
6261
	    (arg_stack_space);
6262
 
6263
	  load_store(i_stq,FP,b);
6264
	  operate_fmt_immediate(i_addq,SP,st,FP);
6265
	  /*operate_fmt(i_bis,SP,SP,FP);*/
6266
	  if (Has_tos) {
6267
	    b.base = FP;
6268
	    b.offset = -((PTR_SZ>>3)*2)-(arg_stack_space);
6269
	    load_store(i_stq,SP,b);
6270
	  }
6271
	}
6272
      }
6273
 
6274
      if(proc_has_checkstack(e)){
6275
	baseoff b;
6276
	int rtmp = getreg(sp.fixed);
6277
	/*	b = find_tag("__TDFstacklim");*/
6278
	b = find_tag("__alpha_stack_limit");
6279
	stackerr_lab = new_label();
6280
	load_store(i_ldq,rtmp,b);
6281
	setnoat();
6282
	operate_fmt(i_cmplt,SP,rtmp,AT);
6283
	integer_branch(i_bne,AT,stackerr_lab);
6284
	setat();
6285
      }
6286
      else{
6287
	stackerr_lab = 0;
6288
      }
6289
 
6290
 
6291
      if ((pprops & realresult_bit) != 0) {
6292
	/* proc has real result */
6293
 
6294
	/* add an entry for complex result : returned in f0/f1 */
6295
 
6296
	freg frg;
6297
	frg.fr = 0;
6298
	if(pprops & longrealresult_bit)
6299
	  frg.type = IEEE_double;
6300
	else
6301
	  frg.type = IEEE_single;
6302
	setfregalt (procans, frg);
6303
      }
6304
      else if ((pprops & has_result_bit) != 0) {
6305
	/* proc has fixed pt result */
6306
	setregalt (procans, RESULT_REG);
6307
      }	
6308
      else {			/* proc has no result */
6309
	setregalt (procans, NO_REG);
6310
      }	
6311
      result_label = 0;
6312
      aritherr_lab = 0;
6313
      /* fix up integers passed in registers */
6314
      for(l = son(e);name(l) == ident_tag && isparam(l);l=bro(son(l))){
6315
	if(props(l) & inreg_bits){
6316
	  int n = props(son(l));
6317
	  Assert((n>=FIRST_INT_ARG) && (n<=LAST_INT_ARG));
6318
	  if(is32(sh(son(l)))) operate_fmt_immediate(i_addl,n,0,n);
6319
	}
6320
      }
6321
      code_here (son(e), guardreg(RA,sp), nowhere);
6322
      param_stack_space = arg_stack_space = sizecallers = 0;
6323
      /* evaluate body of proc */
6324
      if(stackerr_lab){
6325
	set_label(stackerr_lab);
6326
	operate_fmt_immediate(i_addq,SP,frame_size>>3,SP);
6327
	do_exception(f_stack_overflow);
6328
      }
6329
      if(aritherr_lab){
6330
	set_label(aritherr_lab);
6331
	do_exception(f_overflow);
6332
      }
6333
      return mka;
6334
    } /* end proc */
6335
 
6336
    case alloca_tag : {
6337
      exp s = son(e);
6338
      int r = regfrmdest(&dest, sp);
6339
      int rd;
6340
      ans aa;
6341
      comment("alloca");
6342
      if(checkalloc(e)){
6343
	rd = getreg(sp.fixed);
6344
	operate_fmt(i_bis,SP,SP,rd);
6345
      }
6346
      else{
6347
	rd = SP;
6348
      }
6349
      if (name(s)==val_tag) {
6350
	operate_fmt_immediate(i_subq, rd,(no(s)+7 )&~7,rd);
6351
      }
6352
      else {  
6353
	int tmp = getreg(sp.fixed);
6354
	int rop = reg_operand(s,sp);
6355
	operate_fmt_immediate(i_addq,rop,7,tmp);
6356
	operate_fmt_immediate(i_bic,tmp,7,tmp);
6357
	operate_fmt(i_subq,rd,tmp,rd);
6358
      }
6359
      if(checkalloc(e)){
6360
	int rt = getreg(sp.fixed);
6361
	baseoff b;
6362
	b = find_tag("__alpha_stack_limit");
6363
	load_store(i_ldq,rt,b);
6364
	setnoat();
6365
	operate_fmt(i_cmple,rt,SP,AT);
6366
	if(stackerr_lab == 0) stackerr_lab = new_label();
6367
	integer_branch(i_beq,AT,stackerr_lab);
6368
	setat();
6369
	operate_fmt(i_bis,rd,rd,SP);
6370
      }
6371
 
6372
      reset_tos();
6373
      operate_fmt_immediate(i_addq,SP,max(0,(max_args-6*(PTR_SZ))>>3),r);
6374
      /*operate_fmt(i_bis,SP,SP,r);*/
6375
      setregalt(aa, r);
6376
      mka.regmove = move(aa, dest, sp, 1);
6377
      return mka;
6378
    }
6379
 
6380
    case last_local_tag : {
6381
      int r = regfrmdest(&dest, sp);
6382
      ans aa;
6383
      /*operate_fmt_immediate(i_addq,SP,max_args>>3,r);*/
6384
      operate_fmt(i_bis,SP,SP,r);
6385
      setregalt(aa, r);
6386
      mka.regmove = move(aa, dest, sp, 1);
6387
      return mka;
6388
    }
6389
 
6390
    case local_free_tag : {
6391
      exp s = son(e);
6392
      int r = reg_operand(s, sp);
6393
      exp off = bro(s);
6394
      comment("local_free_tag");
6395
      if(name(off) == val_tag){
6396
	operate_fmt_immediate(i_addq, r, ((no(off)>>3)+7 )&~7,r);
6397
      }
6398
      else{
6399
	int rtmp = reg_operand(off,guardreg(r,sp));
6400
	operate_fmt_immediate(i_addq,rtmp,7,rtmp);
6401
	operate_fmt_immediate(i_bic,rtmp,7,rtmp);
6402
	operate_fmt(i_addq,r,rtmp,r);
6403
      }
6404
      if(Has_fp){
6405
	/*operate_fmt_immediate(i_subq,r,max_args>>3,SP);*/
6406
	operate_fmt(i_bis,r,r,SP);
6407
	reset_tos();
6408
      }
6409
      return mka;
6410
    }
6411
 
6412
    case local_free_all_tag : {
6413
      if (Has_fp) {
6414
	operate_fmt_immediate(i_subq,FP,(frame_size+callee_size)>>3,SP);
6415
	reset_tos();
6416
      }
6417
      return mka;
6418
    }        	    	    	    	
6419
 
6420
    case current_env_tag : {
6421
      int r = regfrmdest(&dest, sp);
6422
      ans aa;
6423
      if (Has_fp) {
6424
	operate_fmt(i_bis,FP,FP,r);
6425
      }
6426
      else {
6427
	operate_fmt_immediate(i_addq, SP, (frame_size+callee_size)>>3,r);
6428
      }
6429
      setregalt(aa, r);
6430
      mka.regmove = move(aa, dest, sp, 1);
6431
      return mka;
6432
    } 
6433
    case general_env_offset_tag :
6434
    case env_offset_tag : {
6435
      low_INT64(constval) = frame_offset(son(e));
6436
      goto moveconst;
6437
    }   	
6438
 
6439
    case null_tag : 
6440
null_tag_case : {
6441
      ans aa;
6442
      setregalt (aa, 31);
6443
      mka.regmove = move (aa, dest, sp, 1);
6444
      return mka;
6445
    }
6446
 
6447
    case round_tag :{
6448
      int   r = (dest.answhere.discrim == inreg) ? regalt (dest.answhere)
6449
	:getreg (sp.fixed);
6450
      int   sfr = freg_operand (son (e), sp);
6451
      int   dfr = getfreg (guardfreg (sfr, sp).flt);
6452
      ash a;
6453
      ans aa;
6454
      int   s;
6455
      instruction ins;
6456
      int truncate = (round_number(e)!=f_to_nearest);
6457
      a = ashof (sh (son (e)));
6458
      s = a.ashsize;
6459
      if(r == NO_REG) {
6460
	Assert(!optop(e));
6461
	r = getreg(sp.fixed);
6462
      }
6463
 
6464
      /* start of round */
6465
      /* simply do a conversion: double->long or float->int */
6466
      /* need to check FPCR for possible [over/under]flow */
6467
      ins = (truncate)?i_cvttqc:i_cvttq;
6468
      if(round_number(e) == f_toward_zero){
6469
	ins = i_cvttqc;
6470
      }
6471
      else if (round_number(e) == f_toward_smaller){
6472
	ins = i_cvttqm;
6473
      }
6474
      else if (round_number(e) == f_toward_larger){
6475
	set_up_rounding_mode(PLUS_INFINITY);
6476
	ins = i_cvttqd;
6477
      }
6478
      else{
6479
	ins = i_cvttq;
6480
      }
6481
 
6482
      float_convert(ins,sfr,dfr); /* convert to integer QW */
6483
      /* now move the result into register r */
6484
      {
6485
	ans source;
6486
	where d;
6487
	freg fr;
6488
	fr.fr=dfr;
6489
	fr.type=(s==32)?IEEE_single:IEEE_double;
6490
	setfregalt(source,fr);
6491
	setregalt(d.answhere,r);
6492
	d.ashwhere=a;
6493
	move(source,d,sp,0);
6494
      }
6495
 
6496
      /* we may have to cope with overflow a la C */
6497
      if (name (sh (e)) == ucharhd) {
6498
	if(!optop(e) && !error_treatment_is_trap(e)){
6499
	  test_unsigned(r,255,trap_label(e));
6500
	}
6501
	else if (error_treatment_is_trap(e)){
6502
	  test_unsigned_and_trap(r,255,f_overflow);
6503
	}
6504
	operate_fmt_immediate (i_and, r, 255,r);
6505
      }
6506
      else if (name (sh (e)) == uwordhd) {
6507
	if(!optop(e) && !error_treatment_is_trap(e)){
6508
	  test_unsigned(r,0xffff,trap_label(e));
6509
	}
6510
	else if(error_treatment_is_trap(e)){
6511
	  test_unsigned_and_trap(r,0xffff,f_overflow);
6512
	}
6513
	operate_fmt_immediate (i_and, r,(1 << 16) - 1,r);
6514
      }
6515
      else if (name (sh (e)) == scharhd) {
6516
	if(!optop(e) && !error_treatment_is_trap(e)){
6517
	  test_signed(r,-128,127,trap_label(e));
6518
	}
6519
	else if (error_treatment_is_trap(e)){
6520
	  test_signed_and_trap(r,-128,127,f_overflow);
6521
	}
6522
	operate_fmt_immediate (i_sll, r,56, r);
6523
	operate_fmt_immediate (i_sra, r, 56, r);
6524
      }
6525
      else if (name (sh (e)) == swordhd) {
6526
	if(!optop(e) && !error_treatment_is_trap(e)){
6527
	  test_signed(r,-0x8000L,0x7fff,trap_label(e));
6528
	}
6529
	else if (error_treatment_is_trap(e)){
6530
	  test_signed_and_trap(r,-0x8000L,0x7fff,f_overflow);
6531
	}
6532
	operate_fmt_immediate (i_sll, r, 48,r);
6533
	operate_fmt_immediate (i_sra, r, 48,r);
6534
      }
6535
      else if (name(sh(e)) == slonghd) {
6536
	if(!optop(e) && !error_treatment_is_trap(e)){
6537
	  test_signed(r,-0x80000000L,0x7fffffff,trap_label(e));
6538
	}
6539
	else if (error_treatment_is_trap(e)){
6540
	  test_signed_and_trap(r,-0x80000000L,0x7fffffff,f_overflow);
6541
	}
6542
	operate_fmt_immediate(i_sll,r,32,r);
6543
	operate_fmt_immediate(i_sra,r,32,r);
6544
      }
6545
      else if (name(sh(e)) == ulonghd) {
6546
	if(!optop(e) && !error_treatment_is_trap(e)){
6547
	  test_unsigned(r,0xffffffff,trap_label(e));
6548
	}
6549
	else if (error_treatment_is_trap(e)){
6550
	  test_unsigned(r,0xffffffff,f_overflow);
6551
	}
6552
	operate_fmt_immediate(i_zap,r,240,r);
6553
      }
6554
      setregalt (aa, r);
6555
      mka.regmove = move (aa, dest, sp, 1);
6556
      return mka;
6557
      /* end of round */
6558
    }
6559
 
6560
    case int_to_bitf_tag :{
6561
      int   r;
6562
      where w;
6563
      ash a;
6564
       ash ai;
6565
       ans aa;
6566
       space nsp;
6567
       a = ashof (sh (e));
6568
       ai = ashof (sh (son (e)));
6569
       r = regfrmdest(&dest, sp);
6570
 
6571
       setregalt (w.answhere, r);
6572
       w.ashwhere = a;
6573
       code_here (son (e), sp, w);
6574
       if (a.ashsize != ai.ashsize) {
6575
	 operate_fmt_immediate (i_and, r,(1 << a.ashsize) - 1,r);
6576
       }
6577
       nsp = guardreg (r, sp);
6578
       setregalt (aa, r);
6579
       move (aa, dest, nsp, 0);
6580
       return mka;
6581
     }
6582
 
6583
 
6584
     case bitf_to_int_tag : {
6585
       ash a;
6586
       int   r;
6587
       where w;
6588
       a = ashof (sh (son (e)));
6589
       r = regfrmdest(&dest, sp);
6590
 
6591
       setregalt (w.answhere, r);
6592
       w.ashwhere = a;
6593
       code_here (son (e), sp, w);
6594
       if (a.ashsize != 64) {		
6595
	 if ((name ((sh (e))) & 1) == 1) {
6596
	   operate_fmt_immediate (i_sll, r,64 - a.ashsize,r);
6597
	   operate_fmt_immediate (i_sra, r,64 - a.ashsize,r);
6598
	 }
6599
	 else {
6600
	   operate_fmt_immediate (i_and,r, ((1 << a.ashsize) - 1),r);
6601
	 }
6602
       }
6603
 
6604
       move (w.answhere, dest, guardreg (r, sp), 0);
6605
       keepreg (e, r);
6606
       return mka;
6607
     }
6608
#ifdef trap_tag
6609
    case trap_tag : {
6610
      if(no(e) == f_overflow) {
6611
	do_exception(f_overflow);
6612
      }
6613
      else if(no(e) == f_nil_access) {
6614
	do_exception(f_nil_access);
6615
      }
6616
      else {
6617
	do_exception(f_stack_overflow);
6618
      }
6619
      return mka;
6620
    }
6621
#endif    
6622
 
6623
    case special_tag :{
6624
      if(no(e) == 0){
6625
	no_parameter_instructions(i_trapb); 
6626
      }
6627
      return mka;
6628
    }
6629
 
6630
#if 1
6631
     case condassign_tag :{
6632
       /*
6633
	 This handles a conditional assignment of the form:
6634
	 IF ( A .rel. B) THEN X = Y, using conditional moves.
6635
	 son(e) is the test_tag and bro(son(e)) is the assignment.
6636
	 Note that the test condition is the opposite of the 
6637
	 condition for the conditional move (because the original
6638
	 test is a jump over the assigment).
6639
	*/
6640
       where assdest;
6641
       instruction cinst;
6642
       exp ctest = son(e);
6643
       exp cass = bro(ctest);
6644
       exp ltest = son(ctest);	/* lhs of test */
6645
       exp rtest = bro(ltest);	/* rhs of test */
6646
       int testid = props(ctest) & 127;
6647
       int targ1,targ2;		/* arguments of test */
6648
       int aarg1,aarg2;		/* arguments of assignment */
6649
       int rev = 0;		/* set if test is reversed */
6650
       ans aa;
6651
       exp rhs = bro(son(cass));
6652
       failer("ERROR: condassign_tag should not be encountered");
6653
       assdest = locate(son(cass),sp,sh(rhs),NO_REG);
6654
       if(((is_floating(name(sh(ltest)))) && 
6655
	   (!is_floating(name(sh(son(cass))))))
6656
	  || ((!is_floating(name(sh(ltest)))) 
6657
	      && (is_floating((name(sh(son(cass)))))))){
6658
	 return make_code(ctest,sp,dest,exitlab);
6659
       }
6660
       if(is_floating(name(sh(ltest)))){
6661
	 bool fcompare = (name(sh(ltest)) != shrealhd);
6662
	 instruction compare_ins;
6663
	 space nsp;
6664
	 int rdest  = getfreg(sp.flt);
6665
	 freg frg;
6666
	 targ1 = freg_operand(ltest,sp);
6667
	 nsp = guardreg(targ1,sp);
6668
	 targ2 = freg_operand(rtest,nsp);
6669
	 if(fcompare){
6670
	   rev = fdouble_comparisons(&compare_ins,testid);
6671
	   float_op(compare_ins,targ1,targ2,rdest);
6672
	 }
6673
	 else {
6674
	   float_op(i_subs,targ1,targ2,rdest);
6675
	 }
6676
	 aarg1 = freg_operand(son(cass),sp);
6677
	 nsp = guardreg(aarg1,sp);
6678
	 aarg2 = freg_operand(bro(son(cass)),nsp);
6679
	 frg.fr = aarg1;
6680
	 frg.type = (name(sh(ltest)) == shrealhd)?IEEE_single:IEEE_double;
6681
	 float_op(rev?i_fcmovne:i_fcmoveq,rdest,aarg2,aarg1);
6682
	 setfregalt(aa,frg);
6683
       }
6684
       else { /* integer */
6685
	 bool is_compare = ((!is_signed(sh(ltest))) && ((testid-5)<0) && 
6686
			    (name(sh(ltest))!=ptrhd))||((is64(sh(ltest))));      
6687
	 instruction compare_ins;
6688
	 int rres;	/* the result of the test */
6689
	 if(is_compare){
6690
	   rev = comparisons(&compare_ins,sh(ltest),testid);
6691
	 }
6692
 
6693
	 targ1 = reg_operand(ltest,sp);
6694
	 if(name(rtest) == val_tag){
6695
	   space nsp;
6696
	   if(no(rtest) || (isbigval(rtest))){
6697
	     nsp = guardreg(targ1,sp);
6698
	     rres = getreg(nsp.fixed);
6699
	     if(is_compare){
6700
	       if(isbigval(rtest)){
6701
		 operate_fmt_big_immediate(compare_ins,targ1,
6702
					   exp_to_INT64(rtest),rres);
6703
	       }
6704
	       else{
6705
		 operate_fmt_immediate(compare_ins,targ1,no(rtest),rres);
6706
	       }
6707
	     }
6708
	     else{
6709
	       if(name(sh(ltest)) == ulonghd){
6710
		 operate_fmt_immediate(i_addl,targ1,0,targ1);
6711
	       }
6712
	       if(isbigval(rtest)){
6713
		 operate_fmt_big_immediate(i_subq,targ1,exp_to_INT64(rtest),
6714
					   rres);
6715
	       }
6716
	       else{
6717
		 operate_fmt_immediate(i_subq,targ1,no(rtest),rres);
6718
	       }
6719
	     }
6720
	   }
6721
	   else{	/* test against zero */
6722
	     rev = 0;
6723
	     rres = targ1;
6724
	   }
6725
	 }
6726
	 else{
6727
	   space nsp;
6728
	   nsp = guardreg(targ1,sp);
6729
	   targ2 = reg_operand(rtest,nsp);
6730
	   if (targ2 == 31){
6731
	     rev = 0;
6732
	     rres = targ1;
6733
	   }
6734
	   else{
6735
	     rres = getreg(nsp.fixed);
6736
	     if(is_compare){
6737
	       operate_fmt(compare_ins,targ1,targ2,rres);
6738
	     }
6739
	     else{
6740
	       operate_fmt(i_subq,targ1,targ2,rres);
6741
	     }
6742
	   }
6743
	 }
6744
	 aarg1 = regfrmdest(&assdest,sp);
6745
	 cinst = condmove((!rev)?testrev[testid-1]:testid);
6746
 
6747
	 if(is_compare){
6748
	   cinst = rev?i_cmovne:i_cmoveq;
6749
	 }
6750
	 else{
6751
	   cinst = condmove((!rev)?testrev[testid-1]:testid);
6752
	 }
6753
 
6754
	 if(name(rhs) == val_tag){
6755
	   if(isbigval(rhs)){
6756
	     operate_fmt_big_immediate(cinst,rres,exp_to_INT64(rhs),aarg1);
6757
	   }
6758
	   else{
6759
	     if(no(rhs) == 0 && (testid == 5)){
6760
	       operate_fmt_immediate(i_cmpeq,rres,31,aarg1);
6761
	     }
6762
	     else{
6763
	       operate_fmt_big_immediate(cinst,rres,exp_to_INT64(rhs),aarg1);
6764
	     }
6765
	     	   }	
6766
	 }
6767
	 else{
6768
	   int r2 = reg_operand(rhs,sp);
6769
	   operate_fmt(cinst,rres,r2,aarg1);
6770
	 }
6771
	 setregalt(aa,aarg1);
6772
       }
6773
       (void)move(aa,assdest,sp,1);
6774
       (void)move(aa,dest,sp,1);
6775
       clear_dep_reg(son(cass));
6776
       return mka;
6777
     }
6778
#endif
6779
    default: 
6780
      alphafail(TAG_NOT_IMPLEMENTED);
6781
    }				/* end outer switch */
6782
 
6783
moveconst:{
6784
  int   r = regfrmdest(&dest, sp);
6785
  ans aa;
6786
  if(r==NO_REG)
6787
    r=getreg(sp.fixed);
6788
  if (r != 31) {		/* somewhere! */
6789
    if(INT64_eq(constval,zero_int64))
6790
      operate_fmt(i_bis,31,31,r);
6791
    else{
6792
      load_store_immediate(is64(sh(e))?i_ldiq:i_ldil,r,constval);
6793
    }
6794
    setregalt (aa, r);
6795
    move (aa, dest, guardreg (r, sp), 1);
6796
  }
6797
  mka.regmove = r;
6798
  return mka;
6799
 }
6800
 
6801
}					/* end make_code */
6802
 
6803
 
6804