Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
	(1) Its Recipients shall ensure that this Notice is
14
	reproduced upon any copies or amended versions of it;
15
 
16
	(2) Any amended version of it shall be clearly marked to
17
	show both the nature of and the organisation responsible
18
	for the relevant amendment or amendments;
19
 
20
	(3) Its onward transfer from a recipient to another
21
	party shall be deemed to be that party's acceptance of
22
	these conditions;
23
 
24
	(4) DERA gives no warranty or assurance as to its
25
	quality or suitability for any purpose and DERA accepts
26
	no liability whatsoever in relation to any use to which
27
	it may be put.
28
*/
29
 
30
 
31
/*
32
$Log: makecode.c,v $
33
 * Revision 1.1.1.1  1998/01/17  15:56:03  release
34
 * First version to be checked into rolling release.
35
 *
36
 * Revision 1.20  1996/11/25  13:43:20  wfs
37
 *    Fixed the comm_op register tracking bug in "oprators.c" and removed a
38
 * few superfluous "#if 0"s.
39
 *
40
 * Revision 1.19  1996/11/20  17:26:49  wfs
41
 *    Fixed bug in makecode.c's case_tag involving unsigned control variable.
42
 *
43
 * Revision 1.18  1996/11/14  15:22:19  wfs
44
 *    Fixed a bug in regexps.c which was common to most of the installers and
45
 * has only just come to light due to PWE's work on powertrans. (There was
46
 * previously only a patch.) Cosmetic changes to other files.
47
 *
48
 * Revision 1.17  1996/11/07  14:48:21  wfs
49
 * A bug fix to "round_tag" - was clearing wrong freg. Cosmetic changes to
50
 * "inst_fmt.c".
51
 *
52
 * Revision 1.16  1996/10/24  15:51:17  wfs
53
 * Added "~alloc_size" special token. Minor change to alloca_tag - only need
54
 * one word for storage of pointer. Major change to round_tag (rounding to
55
 * unsigned chars) in the fix of avs bug.
56
 *
57
 * Revision 1.15  1996/08/30  09:02:22  wfs
58
 * Various fixes of bugs arising from avs and pl_tdf tests.
59
 *
60
 * Revision 1.14  1996/03/22  16:02:34  wfs
61
 * bigval bug fix.
62
 *
63
 * Revision 1.13  1996/03/15  15:04:16  wfs
64
 * 64 bit int corrections.
65
 *
66
 * Revision 1.12  1996/03/14  17:21:02  wfs
67
 * Bug in apply_general_tag case - when postlude_has_call(e) it was being
68
 * assumed there was at least one caller.
69
 *
70
 * Revision 1.11  1996/02/14  17:19:15  wfs
71
 * "next_caller_offset" and "next_callee_offset" have become special tokens
72
 * defined in "spec_tok.c". Bug fix to a "and_tag" optimization in
73
 * "oprators.c". A few bug fixes in "makecode.c" arising from the variable
74
 * caller tests. "promote_pars" defined in "config.h".
75
 *
76
 * Revision 1.10  1996/01/22  17:25:57  wfs
77
 * Bug fix to "make_stack_limit_tag".
78
 *
79
 * Revision 1.9  1996/01/17  13:50:57  wfs
80
 * Another adjustment to "round_tag" - avoid "_U_Qfcnvfxt_dbl_to_sgl" if the
81
 * error_treatment is "continue".
82
 *
83
 * Revision 1.8  1996/01/15  10:26:46  wfs
84
 * Fixed another "round_tag" bug.
85
 *
86
 * Revision 1.7  1996/01/12  15:26:56  wfs
87
 * Tightened up shl_tag and shr_tag to avoid assembler warnings of "extru"
88
 * instructions with len field = 0.
89
 *
90
 * Revision 1.6  1996/01/12  13:01:52  wfs
91
 * Fixed "round_tag" bug which surfaced from running "cover".
92
 *
93
 * Revision 1.5  1996/01/11  14:46:25  wfs
94
 * Fixed bug in "ass_tag" case of scan(). Removed superfluous macro and comment.
95
 *
96
 * Revision 1.4  1996/01/08  12:01:53  wfs
97
 * Cosmetic changes to usage message in "hppatrans.c". "issparc" set to 0 in
98
 * "config.h". Change to "scan()" regarding the passing of 64 bit int params.
99
 *
100
 * Revision 1.3  1996/01/04  16:45:11  wfs
101
 * "ManualPages put under cvs control. Bug fix in "makecode.c" which prevents
102
 * unused 64 bit procedure results being stored "nowhere".
103
 *
104
 * Revision 1.2  1995/12/18  13:11:54  wfs
105
 * Put hppatrans uder cvs control. Major Changes made since last release
106
 * include:
107
 * (i) PIC code generation.
108
 * (ii) Profiling.
109
 * (iii) Dynamic Initialization.
110
 * (iv) Debugging of Exception Handling and Diagnostics.
111
 *
112
 * Revision 5.17  1995/11/09  14:01:36  wfs
113
 * Bugs fixed in "case same_callees_tag".
114
 *
115
 * Revision 5.16  1995/10/27  13:45:43  wfs
116
 * Removed a few "#if 0"'s.
117
 *
118
 * Revision 5.15  1995/10/23  15:45:17  wfs
119
 * A bug in the code responsible for moving parameters from the stack to
120
 * an allocated register.
121
 *
122
 * Revision 5.14  1995/10/20  14:01:22  wfs
123
 * Removed "valid_ptr" - when compiled with gcc -Wl,-z, eqntott crashed - it
124
 * is wrong. Made several changes to stop complaints during gcc
125
 * compilation.
126
 *
127
 * Revision 5.13  1995/10/19  13:51:07  wfs
128
 * Temporary fix of use of "vaild_ptr".
129
 *
130
 * Revision 5.12  1995/10/18  13:45:01  wfs
131
 * Undid a "#if 0" which was corrupting the passing of byte + halfword
132
 * parameters.
133
 *
134
 * Revision 5.11  1995/10/13  10:42:58  wfs
135
 * Partial fix of a "round_with_mode" bug.
136
 *
137
 * Revision 5.10  1995/10/12  17:24:10  wfs
138
 * Fixed several bugs in "do_callers" which were fouling "plumhall".
139
 *
140
 * Revision 5.9  1995/10/11  15:55:36  wfs
141
 * Moved "apply_tag" stuff from "proc.c" to this file. Fixed a bug in
142
 * "round_tag" case.
143
 *
144
 * Revision 5.8  1995/10/09  13:00:40  wfs
145
 * Cosmetic changes.
146
 *
147
 * Revision 5.7  1995/09/26  11:10:38  wfs
148
 * "long_jump.pl" bug fix. The stack pointer was not being properly
149
 * adjusted after an untidy return.
150
 *
151
 * Revision 5.6  1995/09/25  13:10:06  wfs
152
 * Added a "reset_tos()" after untidy calls in "Has_tos" procedures.
153
 *
154
 * Revision 5.5  1995/09/25  10:35:38  wfs
155
 * Fixed a bug in "round_tag" which was causing problems with "ghostscr
156
 * "ghostscript".
157
 *
158
 * Revision 5.4  1995/09/15  14:45:54  wfs
159
 * Removed "include "extra_expmacs.h".
160
 *
161
 * Revision 5.3  1995/09/15  12:47:21  wfs
162
 * Some "#include"'s added. Finished implementing the exception token
163
 * and stack limit stuff. Major change to "tail_call_tag". Changes to
164
 * "quad_op" and "trap_handler" calls. Changes to "round_tag" and
165
 * "do_callers. Minor changes to stop gcc compiler from complaining.
166
 *
167
 * Revision 5.2  1995/09/07  15:40:54  wfs
168
 * Removed "extra_expmacs.h" include
169
 *
170
 * Revision 5.0  1995/08/25  13:42:58  wfs
171
 * Preperation for August 25 Glue release
172
 *
173
 * Revision 3.4  1995/08/25  09:52:27  wfs
174
 * Major revision. Many 3.1 and 4.0 constructs added.
175
 *
176
 * Revision 3.4  1995/08/25  09:52:27  wfs
177
 * Major revision. Many 3.1 and 4.0 constructs added.
178
 *
179
 * Revision 3.1  95/04/10  16:27:14  16:27:14  wfs (William Simmonds)
180
 * Apr95 tape version.
181
 * 
182
 * Revision 3.0  95/03/30  11:18:11  11:18:11  wfs (William Simmonds)
183
 * Mar95 tape version with CRCR95_178 bug fix.
184
 * 
185
 * Revision 2.0  95/03/15  15:28:02  15:28:02  wfs (William Simmonds)
186
 * spec 3.1 changes implemented, tests outstanding.
187
 * 
188
 * Revision 1.11  95/03/15  15:20:58  15:20:58  wfs (William Simmonds)
189
 * *** empty log message ***
190
 * 
191
 * Revision 1.10  95/02/22  11:30:29  11:30:29  wfs (William Simmonds)
192
 * Implemented last_local, local_free_all and local_free tags,
193
 * 
194
 * Revision 1.9  95/02/20  16:13:48  16:13:48  wfs (William Simmonds)
195
 * Implemented offset_pad_tag.
196
 * 
197
 * Revision 1.8  95/02/10  11:47:25  11:47:25  wfs (William Simmonds)
198
 * Removed calls to evaluated() - initialising expressions are now
199
 * stored in a linked list and written to outf after the procedure
200
 * body has been translated (c.f. translate_capsule).
201
 * 
202
 * Revision 1.7  95/01/27  16:30:17  16:30:17  wfs (William Simmonds)
203
 * Rather primitive first attempt at implementing chvar_tag error_jump.
204
 * It should be refined.
205
 * 
206
 * Revision 1.6  95/01/25  15:36:10  15:36:10  wfs (William Simmonds)
207
 * Installed fabs_tag's and fneg_tag's error_jump.
208
 * 
209
 * Revision 1.5  95/01/24  14:00:23  14:00:23  wfs (William Simmonds)
210
 * Implemented error_jump of abs_tag and neg_tag.
211
 * 
212
 * Revision 1.4  95/01/23  18:52:49  18:52:49  wfs (William Simmonds)
213
 * Implemented error_jump of plus_tag and minus_tag.
214
 * 
215
 * Revision 1.3  95/01/19  15:28:10  15:28:10  wfs (William Simmonds)
216
 * Dumped input registers on stack following find of a tdf vararg.
217
 * 
218
 * Revision 1.2  95/01/17  17:26:26  17:26:26  wfs (William Simmonds)
219
 * Changed the take_out_of_line code, real_inverse_ntest[] had to
220
 * be modified.
221
 * 
222
 * Revision 1.1  95/01/11  13:12:25  13:12:25  wfs (William Simmonds)
223
 * Initial revision
224
 * 
225
*/
226
 
227
 
228
#define HPPATRANS_CODE
229
#include "config.h"
230
#include "myassert.h"
231
#include "addrtypes.h"
232
#include "tags.h"
233
#include "new_tags.h"
234
#include "expmacs.h"
235
#include "installtypes.h"
236
#include "exp.h"
237
#include "exptypes.h"
238
#include "externs.h"
239
#include "check.h"
240
#include "maxminmacs.h"
241
#include "shapemacs.h"
242
#include "basicread.h"
243
#include "proctypes.h"
244
#include "eval.h"
245
#include "move.h"
246
#include "oprators.h"
247
#include "comment.h"
248
#include "getregs.h"
249
#include "guard.h"
250
#include "locate.h"
251
#include "codehere.h"
252
#include "inst_fmt.h"
253
#include "hppains.h"
254
#include "bitsmacs.h"
255
#include "labels.h"
256
#include "regexps.h"
257
#include "regmacs.h"
258
#include "regable.h"
259
#include "muldvrem.h"
260
#include "proc.h"
261
#include "flags.h"
262
#include "install_fns.h"
263
#include "hppadiags.h"
264
#include "translat.h"
265
#include "frames.h"
266
#include "out.h"
267
#include "makecode.h"
268
#include "extratags.h" 
269
#include "f64.h"
270
#include "misc_c.h"
271
#include "special.h"
272
#include "xalloc.h"
273
#include "loc_signal.h"
274
 
275
#define outp fprintf
276
#define isdbl(e) ( ( bool ) ( name ( e ) != shrealhd ) )
277
 
278
int repeat_level;                 /* init by proc */
279
outofline *odd_bits;             /* init by proc */
280
int last_odd_bit;
281
int doing_odd_bits;
282
static exp crt_proc;
283
where nowhere;
284
 
285
extern char export[128];
286
extern int leaf;
287
extern labexp current,first;
288
extern int RSCOPE_LEVEL,RSCOPE_LABEL;
289
extern exp find_named_tg PROTO_S ((char *, shape));
290
extern baseoff find_tg PROTO_S ((char* s));
291
extern int reg_result PROTO_S ((shape));
292
 
293
#define GETREG( d, s )  ( discrim ( ( d ).answhere ) == inreg ?\
294
			  regalt ( ( d ).answhere ) :\
295
			  getreg ( ( s ).fixed ) )
296
 
297
#define GETFREG( d, s ) ( discrim ( ( d ).answhere ) == infreg ?\
298
			  regalt ( ( d ).answhere ) :\
299
			  getfreg ( ( s ).flt ) )
300
 
301
#define TARGET( f ) ( main_globals[(-boff(son(f)).base)-1]->dec_u.dec_val.dec_id )
302
 
303
baseoff zero_exception_register
304
    PROTO_N ( (sp) )
305
    PROTO_T ( space sp )
306
{
307
   baseoff b;
308
   int r = getreg(sp.fixed);
309
   ld_ins(i_lo,0,mem_temp(0),r);    
310
   b.base = r;  b.offset = 0;
311
   st_ins(i_sw,GR0,b);
312
   ldf_ins(i_fldw,b,0);         
313
   return b;
314
}
315
 
316
void trap_handler
317
    PROTO_N ( (b,trap,excep) )
318
    PROTO_T ( baseoff b X int trap X int excep )
319
{ 
320
   stf_ins(i_fstw,0,b);         
321
   ld_ins(i_lb,0,b,b.base);
322
   ir_ins(i_ldi,fs_,empty_ltrl,excep,GR1);
323
   rrr_ins(i_and,c_eq,b.base,GR1,0);
324
   ub_ins(cmplt_N,trap);
325
}
326
 
327
long trap_label
328
    PROTO_N ( (e) )
329
    PROTO_T ( exp e )
330
{
331
   if ( (errhandle(e)&3)==3 )
332
   {
333
      if ( aritherr_lab==0 )
334
	 aritherr_lab = new_label();
335
      return aritherr_lab;
336
   }
337
   else
338
      return no(son(pt(e))); 
339
}
340
 
341
void reset_tos
342
    PROTO_Z ()
343
{
344
   st_ins(i_sw,SP,SP_BOFF);
345
}
346
 
347
void test_if_outside_of_var
348
    PROTO_N ( (v,r,trap) )
349
    PROTO_T ( unsigned char v X int r X int trap )
350
{
351
   if ( v==ucharhd)
352
   {
353
      riir_ins(i_extru,c_,r,31,8,1);
354
      cj_ins(c_neq,1,r,trap);
355
   }
356
   else
357
   if (v==scharhd)
358
   {
359
      riir_ins(i_extrs,c_,r,31,8,1);
360
      cj_ins(c_neq,1,r,trap);
361
   }
362
   else
363
   if (v==uwordhd)
364
   {
365
      riir_ins(i_extru,c_,r,31,16,1);
366
      cj_ins(c_neq,1,r,trap);
367
   }
368
   else
369
   if (v==swordhd)
370
   {
371
      riir_ins(i_extrs,c_,r,31,16,1);
372
      cj_ins(c_neq,1,r,trap);
373
   }
374
}
375
 
376
 
377
typedef struct postl_ {exp pl; struct postl_ * outer; } postl_chain;
378
static postl_chain * old_pls;
379
 
380
void update_plc
381
    PROTO_N ( (ch,ma) )
382
    PROTO_T ( postl_chain * ch X int ma )
383
{
384
   while (ch != (postl_chain*)0) 
385
   {
386
      exp pl= ch->pl;
387
      while ( name(pl)==ident_tag && name(son(pl))==caller_name_tag )
388
      {
389
	 no(pl) += ma;
390
	 pl = bro(son(pl));
391
      }
392
      ch = ch->outer;
393
   }
394
}
395
 
396
 
397
/* ensure everywhere has a checknan() that needs one (cf. mips) */
398
void checknan 
399
    PROTO_N ( ( e, fr ) )
400
    PROTO_T ( exp e X int fr )
401
{
402
#if 0
403
  long trap = no(son(pt(e)));
404
  int t = (ABS_OF(fr) - 32) << 1;
405
 
406
  FULLCOMMENT2("checknan: %%f%d trap=%d", t, trap);
407
  fail("checknan");
408
#endif
409
}
410
 
411
/* start of volatile use */
412
void setvolatile 
413
    PROTO_Z ()
414
{
415
/*    outs(";\t.volatile\n" ) ;  */
416
    return ;
417
}
418
 
419
/* end of volatile use */
420
void setnovolatile 
421
    PROTO_Z ()
422
{
423
/*    outs(";\t.nonvolatile\n" ) ;  */
424
    return ;
425
}
426
 
427
/* unsigned branch table */
428
static CONST char *(usbranch_tab[]) =
429
{
430
   c_,  /* never branch (shouldn't be used) */
431
   c_gequ,
432
   c_gu,
433
   c_lequ,
434
   c_lu,
435
   c_neq,
436
   c_eq,
437
};
438
 
439
 
440
 
441
#define usbranches(i) (usbranch_tab[i])
442
 
443
/* signed branch table */
444
CONST char *(sbranch_tab[]) =
445
{
446
   c_,  /* never branch (shouldn't be used) */
447
   c_geq,
448
   c_g,
449
   c_leq,
450
   c_l,
451
   c_neq,
452
   c_eq,
453
   c_TR,
454
};
455
 
456
#define sbranches(i) (sbranch_tab[i])
457
 
458
static CONST char *(fbranch_tab[]) =
459
{
460
   c_,  /* never branch (shouldn't (be used) */
461
   c_g,
462
   c_geq,
463
   c_l,
464
   c_leq,
465
   c_eq,
466
   c_neq,
467
};
468
 
469
#define fbranches(i) (fbranch_tab[i])
470
 
471
/* used to invert TDF tests */
472
long notbranch[]={7,4,3,2,1,6,5,0};
473
 
474
 
475
int bitsin
476
    PROTO_N ( (b) )
477
    PROTO_T ( long b )
478
{
479
   /* counts the bits in b */
480
   int n = 0;
481
   long mask = 1;
482
   for (; b != 0;)
483
   {
484
      n += ((b & mask) != 0) ? 1 : 0;
485
      b &= ~mask;
486
      mask = mask << 1;
487
   }
488
   return n;
489
}
490
 
491
 
492
/* find the last test in sequence e which is a branch to second, if any, otherwise nil */
493
static exp testlast 
494
    PROTO_N ( ( e, second ) )
495
    PROTO_T ( exp e X exp second )
496
{
497
  if (name(e) == test_tag && pt(e) == second)
498
  {
499
    return (e);
500
  }
501
  if (name(e) == seq_tag)
502
  {
503
    if (name(bro(son(e))) == test_tag && pt(bro(son(e))) == second)
504
    {
505
      return bro(son(e));
506
    }
507
    else if (name(bro(son(e))) == top_tag)
508
    {
509
      exp list = son(son(e));
510
 
511
      for (;;)
512
      {
513
	if (last(list))
514
	{
515
	  if (name(list) == test_tag && pt(list) == second)
516
	  {
517
	    return list;
518
	  }
519
	  else
520
	  {
521
	    return 0;
522
	  }
523
	}
524
	else
525
	{
526
	  list = bro(list);
527
	}
528
      }
529
    }
530
  }
531
  return 0;
532
}
533
 
534
 
535
bool last_param 
536
    PROTO_N ( ( e ) )
537
    PROTO_T ( exp e )
538
{
539
  if (!isparam(e))
540
    return 0;
541
  e = bro(son(e));
542
aa:if (name(e) == ident_tag && isparam(e)
543
			    && name(son(e)) != formal_callee_tag )
544
    return 0;
545
  if (name(e) == diagnose_tag)
546
  {
547
    e = son(e);
548
    goto aa;
549
  }
550
  return 1;
551
}
552
 
553
/* Does e, or components of e, contain a bitfield? */
554
/* +++ should detect this earlier && record in props(e) once-and-for-all */
555
static int has_bitfield 
556
    PROTO_N ( ( e ) )
557
    PROTO_T ( exp e )
558
{
559
  if (e == nilexp)
560
    return 0;
561
  switch (name(e))
562
  {
563
  case compound_tag:
564
    {
565
 
566
       /*
567
       *   (compound_tag <offset> <initialiser> ... )
568
	*/
569
      /* look at alignment of initialisers */
570
      e = bro(son(e));
571
      while (1)
572
      {
573
	if (has_bitfield(e))
574
	  return 1;		/* found bitfield */
575
 
576
	if (last(e))
577
	  return 0;		/* all done, no bitfield */
578
 
579
	e = bro(bro(e));	/* try next initialiser */
580
      }
581
      /* NOTREACHED */
582
  default:
583
      return (ashof(sh(e)).ashalign == 1);	/* found bitfield */
584
    }
585
    /* NOTREACHED */
586
  }
587
  /* NOTREACHED */
588
}
589
 
590
/* Convert all NON-bitfields from byte-offsets back to bit-offsets, so
591
 * the compound can be output correctly by eval().
592
 * Permanently undoes the needscan.c:scan() case val_tag:.
593
 *
594
 * NB must do this EXACTLY ONCE.
595
 */
596
static void fix_nonbitfield 
597
    PROTO_N ( ( e ) )
598
    PROTO_T ( exp e )
599
{
600
  if (name(e) == compound_tag)
601
  {
602
    e = son(e);
603
    while (1)
604
    {
605
      if (name(e) == val_tag && name(sh(e)) == offsethd && al2(sh(e)) >= 8)
606
	  no(e) = no(e) << 3;	/* fix it */
607
 
608
      fix_nonbitfield(bro(e));	/* recursively fix the rest of the struct */
609
 
610
      if (last(bro(e)))
611
	  return;		/* all done */
612
 
613
      e = bro(bro(e));	/* next pair */
614
    }
615
  }
616
  return;
617
}
618
 
619
 
620
void restore_callees
621
    PROTO_Z ()
622
{
623
   /*    Puts back on the stack those callees, if any, which were kept in
624
   **  registers  **/
625
 
626
   exp bdy = son(crt_proc);
627
   while( name(bdy)==dump_tag || name(bdy)==diagnose_tag )
628
       bdy = son(bdy);
629
   while (name(bdy)==ident_tag && isparam(bdy) && name(son(bdy)) !=formal_callee_tag )  
630
   {
631
      bdy = bro(son(bdy));
632
   }
633
   while (name(bdy)==ident_tag && isparam(bdy) )  
634
   {
635
      exp sbdy = son(bdy);
636
      baseoff b;
637
      b.base = Has_vcallees ? FP : EP;
638
      b.offset = (no(sbdy)-callees_offset)>>3;
639
      if (props(bdy) & infreg_bits)
640
      {
641
      }
642
      else
643
      if (props(bdy)&inreg_bits)
644
      {
645
	 st_ins(i_sw,no(bdy),b);
646
      }
647
      bdy = bro(sbdy);
648
   }
649
}
650
 
651
 
652
exp find_ote
653
    PROTO_N ( (e, n) )
654
    PROTO_T ( exp e X int n )
655
{
656
   exp d = father(e);
657
   while ( name(d)!=apply_general_tag )
658
      d = father(d);
659
   d = son(bro(son(d))); /* list otagexps */
660
   while ( n !=0 )
661
   {
662
      d = bro(d);
663
      n--;
664
   }
665
   assert( name(d)==caller_tag );
666
   return d;
667
}		
668
 
669
 
670
void do_exception
671
    PROTO_N ( (e) )
672
    PROTO_T ( int e )
673
{
674
   baseoff b;
675
   ir_ins(i_ldi,fs_,"",e,ARG0);
676
   b = boff( find_named_tg("__hppahandler",f_pointer(f_alignment(f_proc))));
677
   ld_ins( i_lw, 1, b, GR22 ) ;
678
   call_millicode( MILLI_DYNCALL, RP, "", 1 );
679
}
680
 
681
space do_callers
682
    PROTO_N ( (list,sp,stub) )
683
    PROTO_T ( exp list X space sp X char *stub )
684
{
685
   int off = 8<<5;
686
   int fixpar,fltpar;
687
   char s[16];
688
   instore is;
689
   is.b.base = SP;
690
   is.adval = 1;
691
   stub[0]='\t';
692
   stub[1]=0;
693
   for (;;)
694
   {
695
      /* Evaluate parameters in turn. */
696
      where w;
697
      ash ap;
698
      int par_al;
699
      int par_sz;
700
      exp par = (name(list)==caller_tag) ? son(list) : list;
701
      int hd = name(sh(list)) ;
702
      ap = ashof(sh(list));
703
      w.ashwhere = ap;
704
      par_sz = (ap.ashsize > 32) ? 64 : 32;
705
      off+=par_sz;
706
      if ( par_sz==64 && !is_floating(name(sh(list))) && !valregable(sh(list)) )
707
	 par_al = 64;
708
      else
709
	 par_al = (ap.ashalign < 32) ? 32 : ap.ashalign;
710
      off = rounder(off,par_al);
711
      is.b.offset = -(off>>3);
712
      if ( is_floating(hd) && off<(13<<5) )
713
      {
714
	 freg frg;
715
	 ans ansfr;
716
	 frg.fr = (fltpar = (off>>5)-5);
717
	 if ( hd==shrealhd )
718
	 {
719
	    frg.dble = 0;
720
	    sprintf(s,"ARGW%d=FR ",fltpar-4);
721
	    strcat(stub,s);
722
	 }
723
	 else
724
	 {
725
	    frg.dble = 1;
726
	    if (off==(10<<5))
727
	       strcat(stub,"ARGW0=FR ARGW1=FU ");
728
	    else
729
	       strcat(stub,"ARGW2=FR ARGW3=FU ");
730
	 }
731
	 setfregalt(ansfr,frg);
732
	 w.answhere = ansfr;
733
	 /* Evaluate parameter into floating parameter register. */
734
	 code_here(par,sp,w);
735
	 sp = guardfreg(frg.fr, sp);
736
#if 1
737
	 /*    This "#if" statement copies parameters passed in floating
738
	 *   point registers to the corresponding fixed point registers. It
739
	 *   is neccessary to ensure that possible varargs are correctly
740
	 *   dumped on the stack.  */
741
	 fixpar = ARG0+(off>>5)-9;
742
	 if ( hd == shrealhd )
743
	 {
744
	    stf_ins(i_fstw,(frg.fr*3),is.b);
745
	    ld_ins(i_ldw,1,is.b,fixpar);
746
	    sp = guardreg(fixpar,sp);
747
	 }
748
	 else
749
	 {
750
	    stf_ins(i_fstd,(frg.fr*3)+1,is.b);
751
	    ld_ins(i_ldw,1,is.b,fixpar);
752
	    sp = guardreg(fixpar,sp);
753
	    is.b.offset += 4;
754
	    fixpar -= 1;
755
	    ld_ins(i_ldw,1,is.b,fixpar);
756
	    sp = guardreg(fixpar,sp);
757
	 }
758
#endif
759
      }
760
      else 
761
      if ( valregable(sh(list)) && off<(13<<5) )
762
      {
763
	 ans ansr;
764
	 setregalt(ansr,fixpar = ARG0+(off>>5)-9);
765
	 w.answhere = ansr;
766
	 /* Evaluate parameter into fixed parameter register. */
767
	 code_here(par,sp,w);
768
	 sp = guardreg(fixpar,sp);
769
	 sprintf(s,"ARGW%d=GR ",fixpar-ARG0);
770
	 strcat(stub,s);
771
      }
772
      else
773
      {
774
	 /* Evaluate parameter into argument space on stack. */
775
#if 1
776
	 if ( valregable(sh(list)) && ap.ashsize<32 )
777
	 {
778
 	     /*   Byte or 16bit scalar parameter - convert to integer.
779
	    *   We must expand source to a full word to conform to HP PA
780
	    *   conventions. We do this by loading into a reg. 
781
	     */
782
	    int r = reg_operand(par,sp);
783
	    st_ins(i_sw,r,is.b);
784
	 }
785
	 else
786
#endif
787
	 {
788
	    setinsalt(w.answhere,is);
789
	    code_here(par,sp,w);
790
	    fixpar = ARG0+((-is.b.offset)>>2)-9;
791
	    while(par_sz)
792
	    {
793
	       /*    Copy (parts of) compound paramater into vacant parameter
794
	       *   registers.  */
795
	       if (fixpar<ARG3+1)
796
	       {
797
		  ld_ins(i_lw,0,is.b,fixpar);
798
		  sprintf(s,"ARGW%d=GR ",fixpar-ARG0);
799
		  strcat(stub,s);
800
		  sp = guardreg(fixpar,sp);
801
	       }
802
	       fixpar--;
803
	       is.b.offset+=4;
804
	       par_sz-=32;
805
	    }
806
	 }
807
      }
808
      if ( name(list) == caller_tag ) 
809
      {
810
#if 1    
811
	 if (shape_size(sh(list))<32 && valregable(sh(list)))
812
	    no(list) = off-32+shape_size(sh(list));
813
	 else
814
#endif
815
	    no(list) = off;
816
      }
817
      if (last(list))
818
	 return sp;
819
      else
820
	 list = bro(list);
821
   }
822
   /* End "for" */
823
}
824
 
825
 
826
void do_callee_list
827
    PROTO_N ( ( e, sp ) )
828
    PROTO_T ( exp e X space sp )
829
{
830
   long disp = 18<<5;
831
   if (no(e)!= 0)
832
   {
833
      exp list = son(e);
834
      where w;
835
      ash ap;
836
      instore is;
837
      is.b.base = SP;
838
      is.adval = 1;
839
      for(;;)
840
      {
841
	 ap = ashof(sh(list));
842
	 disp = rounder(disp, ap.ashalign);
843
	 is.b.offset = disp>>3;
844
	 w.ashwhere = ap;
845
	 setinsalt(w.answhere, is);
846
    	 code_here(list,sp,w);
847
	 disp = rounder(disp+ap.ashsize,32);
848
    	 if (last(list)) break;
849
	 list = bro(list);
850
      }
851
   }
852
}
853
 
854
 
855
void load_reg
856
    PROTO_N ( (e,r,sp) )
857
    PROTO_T ( exp e X int r X space sp )
858
{
859
   where w;
860
   w.ashwhere = ashof(sh(e));
861
   setregalt(w.answhere,r);
862
   code_here(e,sp,w);
863
}
864
 
865
 
866
/*
867
 * Produce code for expression e, putting its result in dest using t-regs
868
 * given by sp. If non-zero, exitlab is the label of where the code is to
869
 * continue.
870
 */
871
makeans make_code 
872
    PROTO_N ( ( e, sp, dest, exitlab ) )
873
    PROTO_T ( exp e X space sp X where dest X int exitlab )
874
{
875
  long constval=0;
876
  makeans mka;
877
  FULLCOMMENT3("make_code: %s,\t%s,\tprops=%#x",
878
	       (int)SH_NAME(name(sh(e))), (int)TAG_NAME(name(e)), props(e));
879
  FULLCOMMENT3("           space=(%ld,%ld) (%s)", sp.fixed, sp.flt, (int)ANSDISCRIM_NAME( discrim ( dest.answhere ) ));
880
 
881
 tailrecurse:
882
  mka.lab = exitlab;
883
  mka.regmove = NOREG;
884
 
885
  insection(text_section);
886
  fflush(outf);
887
  switch (name(e))
888
  {
889
 
890
 
891
    /*
892
     * Procedure related code selection is handled by make_XXX_tag_code()
893
     * functions in proc.c.
894
     */
895
 
896
  case env_size_tag:
897
  {
898
     exp tg = son(son(e));
899
     procrec * pr = &procrecs[no(son(tg))];
900
     constval = (pr->frame_sz+0) >> 3;
901
     goto moveconst;         		    		
902
  }	
903
 
904
 
905
  case proc_tag: case general_proc_tag:
906
  {
907
     crt_proc = e;
908
     old_pls = (postl_chain*)0;
909
     return make_proc_tag_code(e, sp, dest, exitlab);
910
  }
911
 
912
 
913
  case untidy_return_tag:
914
#if 1
915
  case return_to_label_tag:
916
#endif
917
  case res_tag:
918
  {		
919
     /* procedure result */
920
     return make_res_tag_code(e,sp,dest,exitlab);
921
  }
922
 
923
  case tail_call_tag:
924
  {
925
     exp fn = son(e);
926
     exp cees = bro(fn);
927
     bool glob = is_fn_glob(fn);
928
     exp bdy = son(crt_proc);
929
     space nsp;
930
     nsp = sp;
931
 
932
     if ( name(cees) == make_callee_list_tag )
933
     { 
934
	do_callee_list( cees, sp );
935
     }
936
     else
937
     if ( name(cees) == make_dynamic_callee_tag )
938
     {
939
	baseoff b;
940
	int r;
941
	if ( Has_fp )
942
	{
943
	   b.base = FP; b.offset = 68;
944
	}
945
	else
946
	{
947
	   b.base = SP; b.offset = -(frame_sz>>3) + 68;
948
	}
949
    	r = getreg(nsp.fixed);
950
    	load_reg(son(cees),r,nsp);
951
	st_ins(i_sw,r,b);
952
	b.offset -= 4;
953
    	r = getreg(nsp.fixed);
954
    	load_reg(bro(son(cees)),r,nsp);
955
	st_ins(i_sw,r,b);  /*     NB The sum of the callee sizes has been
956
			   **  put on the stack.  **/
957
     }
958
     else
959
     if ( name(cees) == same_callees_tag )
960
     {
961
	restore_callees();
962
     }
963
     if ( !glob )
964
     { 
965
	 int r = getreg(nsp.fixed); 
966
	 load_reg( fn, r, nsp ) ;
967
	 st_ins( i_sw, r, mem_temp(0) ) ;
968
     }
969
 
970
     /**  Move the callers to the correct place if neccessary.  **/
971
     bdy = son(crt_proc);
972
     while( name(bdy) == dump_tag || name(bdy) == diagnose_tag )
973
	bdy = son(bdy);
974
     while( name(bdy) == ident_tag && isparam(bdy) 
975
		 	           && name(son(bdy)) != formal_callee_tag )
976
     {
977
      	exp sbdy = son(bdy);
978
	int pr =  props(sbdy) ;
979
#if 0
980
	if ( pt(bdy) == nilexp && !diagnose )
981
	{
982
	   /**  Parameter never used.  **/
983
	}
984
	else 
985
#endif
986
	if ( pr == 0 && (props(bdy)&inanyreg) != 0 )
987
	{
988
	   /*    Parameter is passed on stack, but is kept in reg given by
989
	   **  no(bdy).  **/
990
	   if (isvar(bdy))
991
	   {
992
	      baseoff b;
993
	      b.base = SP;
994
	      b.offset = -((no(sbdy)+params_offset)>>3);
995
	      if (is_floating(name(sh(sbdy))))
996
	      {	
997
		 /**  Cannot occur whilst floats are kept on the stack.  **/
998
	      }
999
	      else
1000
	      {
1001
		 st_ins(i_sw,no(bdy),b);
1002
	      }
1003
	   }
1004
	}
1005
	else
1006
	if ( pr && (props(bdy)&inanyreg) == 0 )
1007
	{
1008
	   /**  Parameter is passed in reg, but is kept on stack.  **/ 
1009
	   if (Has_no_vcallers)
1010
	   {
1011
	      baseoff stkpos;
1012
	      int off,sz = shape_size(sh(sbdy));
1013
	      off = -((no(sbdy)+params_offset)>>3);
1014
	      stkpos.base = Has_vcallees ? FP : EP;
1015
	      stkpos.offset = off;
1016
	      if (is_floating(name(sh(sbdy))))
1017
	      {	
1018
		 ldf_ins( sz == 64 ? i_fldd : i_fldw, stkpos, pr ) ;
1019
	      }
1020
	      else 
1021
	      {
1022
		 ld_ins( i_lw, 1, stkpos, pr ) ;
1023
		 if ( sz > 32 )
1024
		 {
1025
		    /*    Parameter must be a compound passed by value with
1026
		    **  sz<=64, load the second half into register.  **/
1027
		    stkpos.offset+=4;
1028
		    ld_ins( i_lw, 1, stkpos, pr-1 ) ;
1029
		 }
1030
	      }
1031
	   }
1032
	}
1033
	else 
1034
	if ( pr != 0 && props(sbdy) != no(bdy) )
1035
	{
1036
	   /*    Parameter is passed in a different register to that which
1037
	   **  it is kept in.  **/
1038
	   if ( is_floating( name(sh(sbdy))) )
1039
	   {
1040
	      /**  Cannot occur whilst floats are kept on the stack.  **/
1041
	   }
1042
	   else 
1043
	   {
1044
	      if (Has_no_vcallers)
1045
		 rr_ins( i_copy, no(bdy), pr ) ;
1046
	      else
1047
	      {
1048
		 baseoff b;
1049
		 b.base = Has_vcallees ? FP : EP;
1050
		 b.offset = -((((pr-GR26)<<3)+params_offset)>>3);
1051
		 st_ins(i_sw,no(bdy),b);
1052
	      }
1053
	   }	
1054
	}
1055
	bdy = bro(sbdy);
1056
     }        
1057
     if ( !Has_no_vcallers )
1058
     {
1059
	int r;
1060
	baseoff b;
1061
	b.base = Has_vcallees ? FP : EP;
1062
	b.offset = -36;
1063
	for (r=GR26;r<=GR23;r++)
1064
	{
1065
	   ld_ins( i_lw, 1, b, r ) ;
1066
	   b.offset-=4;
1067
	}
1068
     }
1069
 
1070
     if ( !glob )
1071
     {
1072
	ld_ins( i_ldw, 1, mem_temp(0), GR22 ) ;
1073
     }
1074
     if ( name(cees) == make_callee_list_tag )
1075
     {
1076
       	/** Copy callees from top of stack. **/
1077
	int i ;
1078
	baseoff b ;
1079
	b.offset = -(frame_sz>>3) ;
1080
	if ( !Has_fp )
1081
	{
1082
	   b.base = (Has_vsp ? EP : SP) ;
1083
	   ld_ins(i_lo,0,b,T4);
1084
	}
1085
	if ( call_has_vcallees(cees) ) 
1086
	{
1087
	   /**  Store the callee size.  **/
1088
	   ir_ins( i_ldi, fs_, empty_ltrl, no(cees) >> 3, GR1 ) ;
1089
	   st_ir_ins( i_stw, cmplt_, GR1, fs_, empty_ltrl, 64,                                       Has_fp ? FP : T4 ) ; 
1090
	}
1091
       	for( i = 0 ; i < (no(cees) >> 3) ; i += 4 )
1092
	{
1093
	   b.base = SP ;
1094
       	   b.offset = i + (18 << 2) ;
1095
	   ld_ins( i_lw, 0, b, T3 ) ;
1096
	   b.base = Has_fp ? FP : T4;
1097
       	   st_ins( i_sw, T3, b ) ;
1098
       	}
1099
    	/* 
1100
    	**	sp + 72 + 0  ->  sp -(frame size) + 72 + 0
1101
    	**	sp + 72 + 4  ->  sp -(frame size) + 72 + 4
1102
    	**	sp + 72 + 8  ->  sp -(frame size) + 72 + 8
1103
    	**                     ....     
1104
    	**                     ....     
1105
    	*/
1106
	if ( Has_fp )
1107
	{
1108
	   rr_ins( i_copy, FP, SP ) ;
1109
	}
1110
	else
1111
	{
1112
	   rr_ins( i_copy, T4, SP ) ;
1113
	}
1114
     }
1115
     else
1116
     if ( name(cees) == make_dynamic_callee_tag )
1117
     {
1118
	int lb,le;
1119
	baseoff b;
1120
 
1121
	if ( Has_fp )
1122
	   rr_ins( i_copy, FP, SP ) ;
1123
	else
1124
	{
1125
	   b.offset = - (frame_sz>>3);
1126
	   b.base = ( Has_vsp ? EP : SP ) ;
1127
	   ld_ins( i_lo, 0, b, SP ) ;
1128
	}
1129
	b.base = SP;  b.offset = 68;
1130
 
1131
	ld_ins(i_lw,0,b,T2);
1132
	/**  T2 = pointer to the bytes constituting the dynamic callees. **/
1133
	b.offset-=4;
1134
	ld_ins(i_lw,0,b,T3);
1135
	/**  T3 = number of bytes constituting the dynamic callees.  **/
1136
 
1137
	lb = new_label();
1138
	le = new_label();
1139
	cj_ins( c_eq, 0, T3, le ) ;
1140
	rrr_ins( i_add, c_, T2, T3, T4 ) ;
1141
	ld_ir_ins( i_ldo, cmplt_, fs_, empty_ltrl, 18<<2, SP, T3) ;   
1142
	outlab("L$$",lb) ;
1143
	ld_ir_ins( i_ldbs, cmplt_MA, fs_, empty_ltrl, 1, T2, GR1 ) ;
1144
	comb_ins( c_l, T2, T4, lb ) ;
1145
	st_ir_ins( i_stbs, cmplt_MA, GR1, fs_, empty_ltrl, 1, T3 ) ;
1146
	outlab("L$$",le);
1147
     }
1148
     else
1149
     {
1150
	if ( Has_fp )
1151
	   rr_ins( i_copy, FP, SP ) ;
1152
	else
1153
	{
1154
	   baseoff b;
1155
	   b.offset = -(frame_sz>>3);
1156
	   b.base = ( Has_vsp ? EP : SP ) ;
1157
	   ld_ins( i_lo, 0, b, SP ) ;
1158
	}
1159
	if ( name(cees) == same_callees_tag && call_has_vcallees(cees)                     && !Has_vcallees )
1160
	{
1161
	      /*  We must store the sum of the callee sizes - it hasn't
1162
	      **  yet been done.  **/
1163
	      ir_ins( i_ldi, fs_, empty_ltrl, no(cees) >> 3, GR1 ) ;
1164
	      st_ir_ins( i_stw, cmplt_, GR1, fs_, empty_ltrl, 64, SP );
1165
	}
1166
 
1167
     }
1168
     restore_sregs();  /**  Restore s-regs.  **/
1169
     ld_ir_ins( i_ldw, cmplt_, fs_, empty_ltrl, -20, SP, RP ) ;
1170
     if ( glob )
1171
     {
1172
	call_ins(cmplt_, TARGET(fn), 0, "");
1173
     }
1174
     else
1175
     {
1176
	call_millicode(MILLI_DYNCALL, 0, "", 1);
1177
     }
1178
     return mka;
1179
  }
1180
 
1181
 
1182
  case apply_tag:		/* procedure call */
1183
  {
1184
     exp fn = son(e);
1185
     exp par = bro(fn);
1186
     int hda = name(sh(e));
1187
     int special;
1188
     space nsp;
1189
     int void_result = (name(sh(e))==tophd);
1190
     int reg_res = reg_result(sh(e));
1191
     makeans mka;
1192
     exp dad = father(e);
1193
     bool tlrecurse = RSCOPE_LEVEL==0 && (name(dad)==res_tag) && props(dad);
1194
     char stub[128];  /* relocation stub */
1195
     nsp = sp ;
1196
     stub[0]='\t';
1197
     stub[1]='\0';
1198
 
1199
     mka.lab = exitlab;
1200
     mka.regmove = NOREG;
1201
 
1202
     /* first see if it is a special to be handled inline */
1203
     if ( (special=specialfn(fn)) > 0 )   /* eg function is strlen */
1204
     {
1205
	mka.lab = specialmake(special,par,sp,dest,exitlab);
1206
	return mka;
1207
     }
1208
 
1209
     if (!last(fn))
1210
	nsp = do_callers(par,sp,stub);
1211
 
1212
     if (!reg_res && !void_result && shape_size(sh(e))>64)
1213
     {
1214
	/* structure or union result, address passed in %r28 (=RET0) */
1215
	instore is;
1216
	assert(discrim (dest.answhere) == notinreg);
1217
	/* struct must be in memory */
1218
	is = insalt(dest.answhere);
1219
	if (is.adval)
1220
	{
1221
	   /* generate address of dest */
1222
	   if (IS_FIXREG(is.b.base))
1223
	      ld_ins(i_lo,SIGNED,is.b,RET0);
1224
	   else
1225
 	      set_ins("",is.b,RET0);   
1226
	}
1227
	else
1228
	   ld_ins(i_lw,SIGNED,is.b,RET0);
1229
	nsp = guardreg(RET0,nsp);
1230
     }
1231
 
1232
     if (special != 0)
1233
     {
1234
	extj_special_ins(special_call_name(special),RP,stub,1);
1235
	if (PIC_code)
1236
	   rr_ins(i_copy,GR5,GR19);
1237
     }
1238
     else
1239
     if (is_fn_glob(fn))
1240
     {
1241
	if (!tlrecurse)
1242
	   call_ins(cmplt_,TARGET(fn),RP,stub);
1243
     }
1244
     else
1245
     {
1246
	reg_operand_here(fn,nsp,GR22);
1247
	call_millicode(MILLI_DYNCALL,RP,stub,1);
1248
     }
1249
 
1250
     if (!reg_res && !void_result && (shape_size(sh(e))<65))
1251
     {
1252
	/* 64 bit structure or union result returned in RET0 and RET1 */
1253
	instore is;
1254
	is = insalt(dest.answhere);
1255
	if (is.adval)
1256
	{
1257
	   st_ins(i_sw,RET0,is.b);
1258
	   is.b.offset+=4;
1259
	   st_ins(i_sw,RET1,is.b);
1260
	}
1261
	else
1262
	{
1263
	   baseoff b;
1264
	   ld_ins(i_lw,SIGNED,is.b,GR1);
1265
	   b.base=GR1;
1266
	   b.offset=0;
1267
	   st_ins(i_sw,RET0,b);
1268
	   b.offset+=4;
1269
	   st_ins(i_sw,RET1,b);
1270
	}
1271
     }
1272
 
1273
     clear_all();
1274
 
1275
     if (reg_res)
1276
     {
1277
	ans aa;
1278
	if (is_floating(hda))
1279
	{
1280
	   freg frg;
1281
	   frg.fr = R_FR4;
1282
	   frg.dble = (hda==shrealhd ? 0 : 1);
1283
	   setfregalt(aa,frg);
1284
	   move(aa,dest,sp.fixed,1);
1285
	   /* move floating point result of application to destination */
1286
	}
1287
	else
1288
	{
1289
	   setregalt(aa,RET0);
1290
	   if ( discrim(dest.answhere)==inreg )
1291
	   {
1292
	      int r = regalt(dest.answhere);
1293
	      if ( r!=RET0 && r!=GR0 )
1294
	      {
1295
		 /* Move from RET0 */
1296
		 move(aa,dest,sp.fixed,1);
1297
	      }
1298
	      mka.regmove = RET0;
1299
	   }
1300
	   else
1301
	   {
1302
	      /* dest not inreg */
1303
	      move(aa,dest,sp.fixed,1);
1304
	   }
1305
	}
1306
     }
1307
     return mka;
1308
  }
1309
 
1310
  case apply_general_tag:
1311
  {
1312
      exp fn = son(e);
1313
      exp cers = bro(fn);
1314
      exp cees = bro(cers);
1315
      exp pl = bro(cees);
1316
      space nsp;
1317
      char stub[128];  /* relocation stub */
1318
      stub[0]='\t';
1319
      stub[1]='\0';
1320
 
1321
      if (no(cers) !=0)
1322
	 nsp = do_callers(son(cers),sp,stub);
1323
      else
1324
	 nsp = sp;
1325
 
1326
      (void) make_code(cees,nsp,nowhere,0);
1327
 
1328
      if (!reg_result(sh(e)) && name(sh(e))!=tophd && shape_size(sh(e))>64)
1329
      {
1330
	 /* Must be a structure or union result, pass address in RET0 */
1331
	 instore is;
1332
	 assert(discrim (dest.answhere) == notinreg);
1333
	 /* struct must be in memory */
1334
	 is = insalt(dest.answhere);
1335
	 if (is.adval)
1336
	 {
1337
	    /* generate address of dest */
1338
	    if (IS_FIXREG(is.b.base))
1339
	       ld_ins(i_lo,SIGNED,is.b,RET0);
1340
	    else
1341
 	       set_ins("",is.b,RET0);   
1342
	 }
1343
	 else
1344
	    ld_ins(i_lw,SIGNED,is.b,RET0);
1345
	 nsp = guardreg(RET0,nsp);
1346
      }
1347
 
1348
      if (is_fn_glob(fn))
1349
      { 
1350
	 call_ins(cmplt_,TARGET(fn),RP,stub);  
1351
      } 
1352
      else
1353
      {
1354
	 reg_operand_here(fn,nsp,GR22);
1355
	 call_millicode(MILLI_DYNCALL,RP,stub,1);
1356
      }
1357
      clear_all();  /* forget all register memories */
1358
      if (reg_result(sh(e)))
1359
      {
1360
	 int hda = name(sh(e));
1361
	 ans aa;
1362
	 if (is_floating(hda))
1363
	 {
1364
	    freg frg;
1365
	    frg.fr = R_FR4;
1366
	    frg.dble = (hda != shrealhd);
1367
	    setfregalt (aa, frg);
1368
	    move (aa, dest, sp.fixed, 1);
1369
	    /* move floating point result of application to destination */
1370
	 }
1371
	 else
1372
	 {
1373
	    setregalt (aa, RET0);
1374
	    mka.regmove = RET0;
1375
	    move (aa, dest, sp.fixed, 1);
1376
	    /* move fixed point result of application to destination */
1377
	 }
1378
      }
1379
      else
1380
      if (name(sh(e))!=tophd && (shape_size(sh(e))<65))
1381
      {
1382
	 /* 64 bit structure or union result returned in RET0 and RET1 */
1383
	 instore is;
1384
	 is = insalt(dest.answhere);
1385
	 if (discrim(dest.answhere)==inreg && dest.answhere.val.regans==GR0)
1386
	 {
1387
	    /* dest is nowhere, do nothing */
1388
	 }
1389
	 else if (is.adval)
1390
	 {
1391
	    st_ins(i_sw,RET0,is.b);
1392
	    is.b.offset+=4;
1393
	    st_ins(i_sw,RET1,is.b);
1394
	 }
1395
	 else
1396
	 {
1397
	    baseoff b;
1398
	    ld_ins(i_lw,SIGNED,is.b,GR1);
1399
	    b.base=GR1;
1400
	    b.offset=0;
1401
	    st_ins(i_sw,RET0,b);
1402
	    b.offset+=4;
1403
	    st_ins(i_sw,RET1,b);
1404
	 }
1405
      }
1406
      if ( call_is_untidy(cees) )
1407
      {
1408
	 int ma = (max_args+511)&(~511);
1409
	 ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,(ma>>3),SP,SP);
1410
	 if (Has_tos)
1411
	    reset_tos();
1412
	 if (PIC_code)
1413
	    st_ir_ins(i_stw,cmplt_,GR5,fs_,empty_ltrl,-32,SP);
1414
      }
1415
      else
1416
      if (postlude_has_call(e))
1417
      {
1418
	 exp x = son(cers);
1419
	 postl_chain p;
1420
	 int ma = (max_args+511)&(~511);
1421
	 for(;x!=nilexp;)
1422
	 {
1423
	    if (name(x)==caller_tag) 
1424
	    {
1425
	       no(x) += ma;
1426
	    }      
1427
	    if ( last(x) )
1428
	       break;
1429
	    else
1430
	       x = bro(x);
1431
	 }
1432
	 mka.regmove = NOREG;
1433
	 update_plc(old_pls,ma);
1434
	 p.pl = pl;
1435
	 p.outer = old_pls;
1436
	 old_pls = &p;
1437
	 ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,ma>>3,SP,SP);
1438
	 (void) make_code(pl, sp, nowhere, 0);
1439
	 ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,-(ma>>3),SP,SP);
1440
	 old_pls = p.outer;
1441
	 update_plc(old_pls,-ma);
1442
      }
1443
      else
1444
	 (void) make_code(pl, sp, nowhere, 0);
1445
      return mka;
1446
  }
1447
 
1448
 
1449
  case caller_name_tag:
1450
  {
1451
     return mka;
1452
  }
1453
 
1454
  case caller_tag:
1455
  {
1456
     e = son(e); goto tailrecurse;
1457
  }
1458
 
1459
 
1460
  case make_callee_list_tag:
1461
  {
1462
     bool vc = call_has_vcallees(e);
1463
     do_callee_list( e, sp );    
1464
     if (vc)
1465
     {
1466
	 ir_ins(i_ldi,fs_,empty_ltrl,no(e)>>3,GR1);
1467
	 st_ir_ins(i_stw,cmplt_,GR1,fs_,empty_ltrl,64,SP);
1468
     }
1469
     return mka;
1470
  }
1471
 
1472
 
1473
  case same_callees_tag:
1474
  {
1475
     bool vc = call_has_vcallees(e);
1476
     restore_callees();
1477
     if (Has_vcallees)
1478
     {
1479
	int startl = new_label();
1480
	int endl = new_label();
1481
	/* Load callee_sz (in bytes), stored in 64(FP), into tmp T4. */
1482
	ld_ir_ins(i_ldw,cmplt_,fs_,empty_ltrl,64,FP,T4);
1483
	comb_ins(c_eq,0,T4,endl);
1484
	if (vc)
1485
	{
1486
	   st_ir_ins(i_stw,cmplt_,T4,fs_,empty_ltrl,64,SP);
1487
	}
1488
	else
1489
	{
1490
	   z_ins(i_nop);
1491
	}
1492
	/*
1493
	    Copy 72(FP),76(FP),...,68+callee_sz(FP) to 72(SP),76(FP),...,68+callee_sz(SP)
1494
	 */
1495
	ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,72,FP,T3);
1496
	rrr_ins(i_add,c_,T4,T3,T4);
1497
	ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,72,SP,T2);
1498
	outlab("L$$",startl);
1499
	ld_ir_ins(i_ldbs,cmplt_MA,fs_,empty_ltrl,1,T3,GR1);
1500
	comb_ins(c_l,T3,T4,startl);
1501
	st_ir_ins(i_stbs,cmplt_MA,GR1,fs_,empty_ltrl,1,T2);
1502
	outlab("L$$",endl);
1503
     }
1504
     else
1505
     {
1506
	int csz = (callee_sz>>3);
1507
	if (csz)
1508
	{
1509
	   int co = -(callees_offset>>3);
1510
	   imm_to_r(csz,T4);
1511
	   if (vc)
1512
	   {
1513
	      st_ir_ins(i_stw,cmplt_,T4,fs_,empty_ltrl,64,SP);
1514
	   }
1515
	   if (csz<17)
1516
	   {
1517
	       /*  16 or fewer bytes to move - may as well move them word
1518
		   by word then finish off byte by byte.  */
1519
	      int nw = csz&(~3);
1520
	      int o,base,off;
1521
	      if (SIMM14(co))
1522
	      {
1523
		 base = EP;
1524
		 off = co;
1525
	      }
1526
	      else
1527
	      {
1528
		 ir_ins(i_addil,fs_L,empty_ltrl,co,EP);
1529
		 ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,co,GR1,T3);
1530
		 base = T3;
1531
		 off = 0;
1532
	      }
1533
	      for(o=0;o<nw;o+=4)
1534
	      {
1535
		 ld_ir_ins(i_ldw,cmplt_,fs_,empty_ltrl,off+o,base,GR1);
1536
		 st_ir_ins(i_stw,cmplt_,GR1,fs_,empty_ltrl,72+o,SP);
1537
	      }
1538
	      for(;o<csz;o++)
1539
	      {
1540
		 ld_ir_ins(i_ldb,cmplt_,fs_,empty_ltrl,off+o,base,GR1);
1541
		 st_ir_ins(i_stb,cmplt_,GR1,fs_,empty_ltrl,72+o,SP);
1542
	      }
1543
	   }
1544
	   else
1545
	   {
1546
	      /*  use a loop to move bytes  */
1547
	     int startl = new_label();
1548
	     if (SIMM14(co))
1549
	     {
1550
		ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,co,EP,T3);
1551
	     }
1552
	     else
1553
	     {
1554
		ir_ins(i_addil,fs_L,empty_ltrl,co,EP);
1555
		ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,co,GR1,T3);
1556
	     }
1557
	     rrr_ins(i_add,c_,T4,T3,T4);
1558
	     ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,72,SP,T2);
1559
	     outlab("L$$",startl);
1560
	     ld_ir_ins(i_ldbs,cmplt_MA,fs_,empty_ltrl,1,T3,GR1);
1561
	     comb_ins(c_l,T3,T4,startl);
1562
	     st_ir_ins(i_stbs,cmplt_MA,GR1,fs_,empty_ltrl,1,T2);
1563
	   }
1564
	}
1565
	else
1566
	if (vc)
1567
	{
1568
	   st_ir_ins(i_stw,cmplt_,0,fs_,empty_ltrl,64,SP);
1569
	}
1570
     }
1571
     return mka;
1572
  }	
1573
 
1574
 
1575
    case make_dynamic_callee_tag:
1576
    {
1577
       /* vc = call_has_vcallees(e);  it should do!  */
1578
       int lower,upper,szr;
1579
       space nsp;
1580
       int lb,le;
1581
       nsp = sp;
1582
       lower = getreg(nsp.fixed);
1583
       load_reg(son(e),lower,nsp);
1584
       nsp = guardreg(lower,nsp);
1585
       szr = getreg(nsp.fixed);
1586
       load_reg(bro(son(e)),szr,nsp);
1587
       guardreg(szr,nsp);
1588
       szr = reg_operand(bro(son(e)),nsp);
1589
       /*  lower = pointer to the bytes constituting the dynamic callees
1590
	   szr = number of bytes constituting the dynamic callees
1591
	*/
1592
       upper = getreg(nsp.fixed);
1593
       lb = new_label();
1594
       le = new_label();
1595
       st_ir_ins(i_stw,cmplt_,szr,fs_,empty_ltrl,64,SP);
1596
       cj_ins(c_eq,0,szr,le);
1597
       rrr_ins(i_add,c_,lower,szr,upper);  /*  `upper' is where we stop  */
1598
       ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,18<<2,SP,szr);   
1599
       outlab("L$$",lb);
1600
       ld_ir_ins(i_ldbs,cmplt_MA,fs_,empty_ltrl,1,lower,GR1);
1601
       comb_ins(c_l,lower,upper,lb);
1602
       st_ir_ins(i_stbs,cmplt_MA,GR1,fs_,empty_ltrl,1,szr);
1603
       outlab("L$$",le);
1604
       return mka;
1605
    }
1606
 
1607
/*****************************************************************************/
1608
 
1609
  case ident_tag:
1610
  {
1611
     where placew;
1612
     int r = NOREG;
1613
     bool remember = 0;
1614
     exp se = son(e);
1615
 
1616
     if ( props(e) & defer_bit )
1617
     {
1618
 	return make_code(bro(se), sp, dest, exitlab);
1619
     }
1620
     if ( se == nilexp )
1621
     {
1622
	/*  Historical - unused tags are now removed cleanly  */
1623
	placew = nowhere;
1624
     }
1625
     else
1626
     if ( name(son(e)) == caller_name_tag )
1627
     {
1628
	/* the ident of a caller in a postlude */
1629
	exp ote = find_ote(e,no(son(e)));
1630
       	no(e) = no(ote);
1631
	placew = nowhere;
1632
     }
1633
     else
1634
     {
1635
	ash a ;
1636
	int n = no(e);
1637
	a = ashof(sh(se));
1638
	if ( props(e) & inreg_bits )
1639
	{
1640
	   /* tag is to be found in a fixed pt reg */
1641
	   if ( n == 0 )
1642
	   {
1643
 	      /*  We need to allocate a fixed t-reg  */
1644
	      int s = sp.fixed;
1645
	      if ( props(e) & notparreg )
1646
	      {
1647
		 s |= PARAM_TREGS;
1648
	      }
1649
	      if (props(e)&notresreg)
1650
	      {
1651
		 s |= RMASK(RET0);
1652
	      }
1653
	      n = getreg(s);
1654
	      no(e) = n;
1655
	   }
1656
	   else
1657
	   if ( n == RET0 )
1658
	   {
1659
	      /* use result reg optimisation */
1660
 	      assert(!(props(e) & notparreg));
1661
	      (void) needreg(RET0, sp);	/* just as an error check */
1662
	   }
1663
	   else
1664
	   {
1665
	      assert(IS_SREG(n));
1666
	   }
1667
	   setregalt(placew.answhere, n);
1668
	}
1669
	else
1670
	if ( props(e) & infreg_bits )
1671
	{
1672
	   /* tag in some float reg */
1673
	   freg frg;
1674
	   if ( n == 0 )
1675
	   {
1676
	      /*
1677
	       * if it hasn't been already allocated into a s-reg
1678
	       * allocate tag into float-reg ...
1679
	       */
1680
	      int s = sp.flt;
1681
	      if ( props(e) & notparreg )
1682
		 s |= PARAM_FLT_TREGS;	
1683
	      n = getfreg(s);
1684
	      no(e) = n;
1685
	   }
1686
	   else
1687
	   if ( n == R_DEFER_FR4 )
1688
	   {
1689
	      n = R_FR4;
1690
	      no(e) = R_FR4;
1691
	   }
1692
	   else
1693
	   {
1694
	      assert(IS_FLT_SREG(n));
1695
	   }
1696
	   frg.fr = n;
1697
	   frg.dble = (a.ashsize==64 ? 1 : 0);
1698
	   setfregalt(placew.answhere, frg);
1699
	}
1700
	else 
1701
	if ( isparam(e) )
1702
	{
1703
 	   instore is;
1704
	   long n = no(se);  /* bit disp of param */
1705
	   if ( name(son(e)) != formal_callee_tag )
1706
	   {
1707
	      /**  A caller parameter kept on the stack.  **/
1708
    	      is.adval = 1;
1709
	      is.b.base = GR17;
1710
	      is.b.offset = -((n+params_offset)>>3);
1711
	      setinsalt(placew.answhere, is);
1712
	      no(e) = n * 2 + GR17;
1713
	      remember = 1;
1714
	      if ( (last_param(e) && (!Has_no_vcallers ||
1715
				      (isvis(e) && props(se)!=0))) ||
1716
		   a.ashsize==0 )
1717
	      {
1718
 	         /*  possible varargs, dump remaining param regs on stack */
1719
		 int i = n >> 5; /* next offset */
1720
		 int off =- (params_offset>>3)-(i<<2);
1721
		 i--;
1722
		 while (i<4)
1723
		 {
1724
		    st_ir_ins(i_stw,cmplt_,ARG0+i,fs_,empty_ltrl,off, Has_vcallees ? FP : EP);
1725
		    strcat(export,i==0 ? ",ARGW0=GR" : i==1 ? ",ARGW1=GR" : i==2 ? ",ARGW2=GR" : ",ARGW3=GR");
1726
		    off-=4;
1727
		    i++;	
1728
		 }
1729
	      }
1730
	   }
1731
	   else
1732
	   {
1733
	      /* A callee parameter */
1734
	      instore is;
1735
	      is.b.base = EP;
1736
	      is.b.offset = no(se);
1737
	      no(e) = is.b.offset;
1738
	      is.adval = 1;
1739
	      setinsalt(placew.answhere,is);
1740
	   }
1741
	}
1742
	else
1743
	{
1744
 	   /* A local living on the stack */
1745
	   instore is;
1746
	   is.b = boff(e);
1747
	   is.adval = 1;
1748
#if USE_BITAD
1749
	   if ( a.ashalign != 1 )
1750
	   {
1751
	      setinsalt(placew.answhere, is);
1752
	      remember = 1;
1753
	   }
1754
	   else
1755
	   {
1756
	      is.b.offset = is.b.offset << 3;
1757
	      setbitadalt(placew.answhere, is);
1758
	   }
1759
#else
1760
	   setinsalt(placew.answhere, is);
1761
	   remember = 1;
1762
#endif
1763
	}  
1764
	placew.ashwhere = a;
1765
     }
1766
     if ( isparam(e) )
1767
     {
1768
	if ( name(se) != formal_callee_tag )
1769
	{
1770
	   int off,sz = shape_size(sh(se));
1771
	   baseoff stkpos;
1772
	   int n = no(se);
1773
	   int pr = props(se); /* (pr == 0) ? (on stack) : (input reg) */
1774
	   stkpos.base = Has_vcallees ? FP : EP;
1775
	   off = -((n+params_offset)>>3);
1776
	   stkpos.offset = off;
1777
#if 0
1778
	   if ( pt(e)==nilexp && !diagnose )
1779
	   {
1780
	      /* parameter never used */
1781
	   }
1782
	   else
1783
#endif
1784
	   if ( pr && ( props(e) & inanyreg ) == 0 )
1785
	   {
1786
	      /* param in reg pr, move to stack */
1787
	      if (is_floating(name(sh(se))))
1788
		 stf_ins(sz==64 ? i_fstd : i_fstw,pr,stkpos);
1789
	      else
1790
	      {
1791
		 if (sz==8)
1792
		    st_ins(i_sb,pr,stkpos);
1793
		 else
1794
		 if (sz==16)
1795
		    st_ins(i_sh,pr,stkpos);
1796
		 else
1797
		 if (sz==32)
1798
		    st_ins(i_sw,pr,stkpos);
1799
		 else  /*  sz==64  */
1800
		 {
1801
		    st_ins(i_sw,pr,stkpos);
1802
		    stkpos.offset+=4;
1803
		    st_ins(i_sw,pr-1,stkpos);
1804
		 }
1805
	      }
1806
	      if ( name(sh(se)) != cpdhd && name(sh(se)) != nofhd )
1807
		 remember = 0;
1808
	    }
1809
	    else
1810
	    if ( pr==0 && (props(e)&inanyreg)!=0 )
1811
	    {
1812
	       /* param on stack, move to reg */
1813
	       int d = no(e);
1814
	       if (sz==8)
1815
		  ld_ins(i_lb,1,stkpos,d);
1816
	       else
1817
	       if (sz==16)
1818
		  ld_ins(i_lh,1,stkpos,d);
1819
	       else
1820
	       if (sz==32)
1821
		  ld_ins(i_lw,1,stkpos,d);
1822
	       remember = 1;
1823
	       r = d;
1824
	    }
1825
	    else
1826
	    if ( pr && pr!=no(e) )
1827
	    {
1828
	       /* param passed in reg=pr, move to different reg=no(e) */
1829
	       int d = no(e);
1830
	       rr_ins(i_copy,pr,d);
1831
	       remember = 1;
1832
	       r = d;
1833
	    }
1834
	 }
1835
	 else
1836
	 {
1837
	    if ( props(e) & inanyreg )
1838
	    {
1839
	       /* A callee parameter passed on stack but kept in register */
1840
	       instore is;
1841
	       ans aa;
1842
	       is.b.base = Has_vcallees ? FP : EP;
1843
	       is.b.offset = (no(se)-callees_offset)>>3;
1844
	       is.adval = 0;
1845
	       setinsalt(aa,is);
1846
	       move(aa,placew,sp.fixed,is_signed(sh(se)));
1847
	    }
1848
	 }
1849
      }
1850
      else
1851
      {
1852
	 r = code_here(son(e), sp, placew);
1853
      }
1854
 
1855
      if (remember && r != NOREG && pt(e) != nilexp && eq_sze(sh(son(e)), sh(pt(e))))
1856
      {
1857
 	 /*  Temporarily in a register, track it to optimise future access  */
1858
 	 if (isvar(e))
1859
	 {
1860
	    keepcont(pt(e), r);
1861
	 }
1862
	 else
1863
	 {
1864
	    keepreg(pt(e), r);
1865
	 }
1866
      }
1867
 
1868
      /* and evaluate the body of the declaration */
1869
      mka = make_code(bro(son(e)), guard(placew, sp), dest, exitlab);
1870
      return mka;
1871
  } 
1872
  /* ENDS ident_tag */
1873
 
1874
/*****************************************************************************/
1875
 
1876
  case seq_tag:
1877
  {
1878
     exp t = son(son(e));
1879
     for (;;)
1880
     {
1881
	exp next = (last(t)) ? (bro(son(e))) : bro(t);
1882
	if ( name(next) == goto_tag )	/* gotos end sequences */
1883
	{
1884
 	   make_code(t, sp, nowhere, no(son(pt(next))));
1885
	}
1886
	else
1887
	{
1888
	   code_here(t, sp, nowhere);
1889
	}
1890
	if ( last(t) )
1891
	{
1892
	   return make_code(bro(son(e)), sp, dest, exitlab);
1893
	}
1894
	t = bro(t);
1895
     }
1896
  }
1897
  /*  ENDS seq_tag  */
1898
 
1899
/*****************************************************************************/
1900
 
1901
  case cond_tag:
1902
  {
1903
     exp first = son(e);
1904
     exp alt = bro(son(e));
1905
     exp test;
1906
     exp record;	 /* jump record for alt */
1907
     exp jr = nilexp;   /* jump record for end of construction */
1908
 
1909
     if ( discrim(dest.answhere) == insomereg )
1910
     {
1911
	/* must make choice of register to contain answer to cond */
1912
	int *sr = someregalt(dest.answhere);
1913
	if (*sr != -1)
1914
	   fail("somereg *2");
1915
	*sr = getreg(sp.fixed);
1916
	setregalt(dest.answhere, *sr);
1917
     }
1918
     if ( name(first)==goto_tag && pt(first)==alt )
1919
     {
1920
	/* first is goto alt */
1921
	no(son(alt)) = 0;
1922
	return make_code(alt, sp, dest, exitlab);
1923
     }
1924
#if 1 
1925
     /*  "take_out_of_line" stuff  */
1926
     if ( name(bro(son(alt))) == top_tag && !diagnose )
1927
     {
1928
	int extract = take_out_of_line(first, alt, repeat_level > 0, 1.0);
1929
	if ( extract )
1930
	{
1931
	   static ntest real_inverse_ntest[] = {
1932
		0, 4, 3, 2, 1, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0
1933
	   };
1934
	   exp t = son(son(first));
1935
	   exp p, s, z;
1936
	   int test_n;
1937
	   shape sha;
1938
	   outofline * rec;
1939
	   exp tst = (is_tester(t, 0)) ? t : bro(son(t));
1940
	   record = getexp(f_bottom, nilexp, 0, nilexp, nilexp,0, 0, 0);
1941
	   if (pt(son(alt)) != nilexp)
1942
	      ptno(record) = ptno(pt(son(alt)));
1943
	   else
1944
	      ptno(record) = new_label();
1945
	   jr = getexp(f_bottom, nilexp, 0, nilexp, nilexp, 0, 0, 0);
1946
	   ptno(jr) = new_label();
1947
	   sha = sh(son(tst));
1948
	   rec = (outofline*)xmalloc(sizeof(outofline));
1949
	   rec->next = odd_bits;
1950
	   odd_bits = rec;
1951
 	   rec->dest = dest;
1952
	   rec->labno = new_label();	/* label for outofline body */
1953
	   if ( last(t) )
1954
	      first = bro(son(first));
1955
	   else
1956
	      son(son(first)) = bro(son(son(first)));
1957
	   rec->body = first;
1958
	   rec->sp=sp;
1959
	       rec->jr=jr;
1960
	   pt(son(alt)) = record;
1961
	   test_n = (int)test_number(tst);
1962
	   if ( name(sha) < shrealhd || name(sha) > doublehd )
1963
	      test_n = (int)int_inverse_ntest[test_n];
1964
	   else
1965
	      test_n = (int)real_inverse_ntest[test_n];
1966
	   settest_number(tst, test_n);
1967
	   z = getexp (f_bottom, nilexp, 0, nilexp, nilexp, 0, 0, 0);
1968
	   ptno(z) = rec->labno;/* z->ptf.l */
1969
	   s = getexp(sha, nilexp, 0, nilexp, z, 0, 0, 0);
1970
	   no(s) = rec->labno;
1971
	   p = getexp(sha, nilexp, 0, s, nilexp, 0, 0, 0);
1972
	   pt(tst) = p;
1973
  	   mka = make_code(t,sp,dest,0);
1974
	   if ( name(sh(first)) != bothd )
1975
	   {
1976
	      outlab("L$$",ptno(jr));
1977
	      clear_all();
1978
	   };	  
1979
	   return mka;
1980
	};
1981
     };
1982
#endif
1983
 
1984
     if ( name(first) == goto_tag && pt(first) == alt )
1985
     {
1986
	/* first is goto alt */
1987
	no(son(alt)) = 0;
1988
	return make_code(alt, sp, dest, exitlab);
1989
     }
1990
     else
1991
     if ( name(alt) == labst_tag && name(bro(son(alt))) == top_tag )
1992
     {
1993
	/* alt is empty */
1994
	int endl = (exitlab == 0) ? new_label() : exitlab;
1995
	no(son(alt)) = endl;
1996
	make_code(first, sp, dest, endl);
1997
	mka.lab = endl;
1998
	return mka;
1999
     }
2000
     else
2001
     if ( name(alt) == labst_tag && name(bro(son(alt))) == goto_tag )
2002
     {
2003
	/* alt is goto */
2004
	exp g = bro(son(alt));
2005
	no(son(alt)) = no(son(pt(g)));
2006
	return make_code(first, sp, dest, exitlab);
2007
     }
2008
 
2009
     if ( ( test = testlast(first, alt) ) ) /* I mean it */
2010
     {
2011
	/* effectively an empty then part */
2012
	int l = (exitlab != 0) ? exitlab : new_label();
2013
	bool rev = IsRev(test);
2014
	ptno(test) = -l;  /* make test jump to exitlab - see test_tag: */
2015
	props(test) = notbranch[props(test)];
2016
	if (rev)
2017
	{
2018
	   SetRev(test);
2019
	}
2020
	/* ... with inverse test */
2021
	no(son(alt)) = new_label();
2022
	make_code(first, sp, dest, l);
2023
	make_code(alt, sp, dest, l);
2024
	mka.lab = l;
2025
	return mka;
2026
     }
2027
     else
2028
     {
2029
	int fl, l;
2030
	no(son(alt)) = new_label();
2031
	fl = make_code(first, sp, dest, exitlab).lab;
2032
 	l = (fl != 0) ? fl : ((exitlab != 0) ? exitlab : new_label());
2033
	ub_ins(cmplt_,l);
2034
	clear_all();
2035
	make_code(alt, sp, dest, l);
2036
	mka.lab = l;
2037
	return mka;
2038
     }
2039
  }
2040
  /*  ENDS cond_tag  */
2041
 
2042
/*****************************************************************************/
2043
 
2044
  case labst_tag:
2045
  {
2046
     if ( no(son(e)) != 0 )
2047
     {
2048
	clear_all();
2049
	outlab("L$$",no(son(e)));
2050
     }
2051
     if ( is_loaded_lv(e) && No_S )
2052
     {
2053
	/* Could be the target of a long_jump - we must reset SP and FP */
2054
	if (Has_tos)
2055
	   ld_ins(i_lw,1,SP_BOFF,SP);
2056
	else
2057
	   rr_ins(i_copy,EP,SP);
2058
	if (Has_fp)
2059
	   ld_ins(i_lw,1,FP_BOFF,FP);
2060
	if (PIC_code)
2061
	{
2062
	   ld_ir_ins(i_ldw,cmplt_,fs_R,empty_ltrl,-32,SP,GR19);
2063
	   if (!leaf)
2064
	   {
2065
	      rr_ins(i_copy,GR19,GR5);
2066
	   }
2067
	}
2068
     }		
2069
     return make_code(bro(son(e)), sp, dest, exitlab);
2070
  }				
2071
  /*  ENDS labst_tag  */
2072
 
2073
/*****************************************************************************/
2074
 
2075
  case rep_tag:
2076
  {
2077
     makeans mka;
2078
     exp first = son(e);
2079
     exp second = bro(first);
2080
     ++ repeat_level;
2081
     code_here(first,sp,nowhere);
2082
     no(son(second)) = new_label();
2083
     mka = make_code(second, sp, dest, exitlab);
2084
     -- repeat_level;
2085
     return mka;
2086
  }
2087
  /*  ENDS rep_tag  */
2088
 
2089
/*****************************************************************************/
2090
 
2091
  case goto_lv_tag:
2092
  {
2093
     int r = reg_operand(son(e),sp);
2094
     extj_reg_ins(i_bv,r);
2095
     z_ins(i_nop);
2096
     clear_all();
2097
     return mka;
2098
  }
2099
  /*  ENDS goto_lv_tag  */
2100
 
2101
/*****************************************************************************/
2102
 
2103
  case goto_tag:
2104
  {
2105
     int lab = no(son(pt(e)));
2106
     assert(lab >= 100);
2107
     clear_all();
2108
     /* if (lab != exitlab) */
2109
     {
2110
	ub_ins(cmplt_,lab);
2111
     }
2112
     return mka;
2113
  }				
2114
  /*  ENDS goto_tag  */
2115
 
2116
/*****************************************************************************/
2117
 
2118
  case absbool_tag:
2119
  {
2120
     fail("make_code: absbool_tag not used on HPPA");
2121
     /* NOTREACHED */
2122
  }
2123
  /*  ENDS absbool_tag  */
2124
 
2125
/*****************************************************************************/
2126
 
2127
  case test_tag:
2128
  {
2129
     exp l = son(e);
2130
     exp r = bro(l);
2131
     int lab = (ptno(e) < 0) ? -ptno(e) : no(son(pt(e)));
2132
     /* see frig in cond_tag */
2133
     shape shl = sh(l);
2134
     CONST char *branch;
2135
     int n = (int) test_number(e);	/* could have Rev bit in props */
2136
 
2137
#if use_long_double
2138
     if ( name(sh(l)) == doublehd )
2139
     {
2140
	quad_op( e, sp, dest );
2141
	cj_ins(c_eq,0,RET0,lab);
2142
	return(mka);
2143
     }
2144
#endif
2145
 
2146
     if ( is_floating(name(sh(l))) )
2147
     {
2148
	/* float test */
2149
	bool dble = ( (name(shl)==shrealhd) ? 0 : 1 );
2150
	int a1;
2151
	CONST char *branch = fbranches(n);
2152
	/* choose branch and compare instructions */
2153
	int a2;
2154
	space nsp;
2155
	if ( IsRev(e) )
2156
	{
2157
 	   a2 = freg_operand(r, sp, getfreg(sp.flt));
2158
	   nsp = guardfreg(a2, sp);
2159
	   a1 = freg_operand(l, nsp, getfreg(nsp.flt));
2160
	}
2161
	else
2162
	{
2163
	   a1 = freg_operand(l, sp, getfreg(sp.flt));
2164
	   nsp = guardfreg(a1, sp);
2165
	   a2 = freg_operand(r, nsp, getfreg(nsp.flt));
2166
	}
2167
	if (dble)
2168
	   cmp_rrf_ins(i_fcmp,f_dbl,branch,(3*a1+1),(3*a2+1));
2169
	else
2170
	   cmp_rrf_ins(i_fcmp,f_sgl,branch,(3*a1),(3*a2));
2171
	z_ins(i_ftest);
2172
	ub_ins(cmplt_,lab);
2173
	return mka;
2174
     }				/* end float test */
2175
     else
2176
     {
2177
			     /* int test */
2178
	int a1;
2179
	int a2;
2180
	bool unsgn;
2181
	if ( name(l) == val_tag )
2182
	{			
2183
	   /* put literal operand on right */
2184
	   exp temp = l;
2185
 	   l = r;
2186
	   r = temp;
2187
	   if ( n <= 2 )
2188
 	     n += 2;
2189
	   else 
2190
	   if ( n <= 4 )
2191
 	     n -= 2;
2192
	}
2193
 
2194
	/* choose branch instruction */
2195
	unsgn = (bool)(!is_signed(shl) && name(shl)!=ptrhd);
2196
	branch = unsgn ? usbranches(n) : sbranches(n);
2197
 
2198
	/* Generally, anding with an immediate requires 2 instructions. But,
2199
	   if the and is only being compared to 0, we may be able to get by
2200
	   with one instruction */
2201
	if ( name(l) == and_tag && name(r)==val_tag && no(r)==0 &&
2202
	    ( branch == c_eq || branch == c_neq ) && !( unsgn && (n==2 || n==3) ) )
2203
	{
2204
	   exp sonl = son(l);
2205
	   exp bsonl = bro(sonl);
2206
	   if ( name(bsonl) == val_tag )
2207
	   {
2208
	      int v = no(bsonl);
2209
	      if ( IS_POW2(v) ) 
2210
	      {
2211
		 /* We can branch on bit */
2212
 
2213
		 /* Which bit, b, to branch on ? */
2214
		 int b=0;
2215
		 while ( (v & (1<<b)) == 0 ) b++; 
2216
		 b=31-b;
2217
		 a1 = reg_operand(sonl,sp);
2218
		 if (OPTIM)
2219
		 {
2220
		    bb_in(branch==c_eq ? bit_is_0 : bit_is_1,a1,b,lab);
2221
		 }
2222
		 else
2223
		 {
2224
		    riir_ins(i_extru,branch==c_eq ? c_OD : c_EV,a1,b,1,0);
2225
		    ub_ins(cmplt_N,lab);
2226
		 }
2227
		 return mka;
2228
	      }
2229
	      else
2230
	      {
2231
		 /* v = 00..0011..1100..00 or v = 11..1100..0011..11 ? */
2232
		 int pos = 0, len, next, m;
2233
		 if ( v & 1 )
2234
		    m = ~v;
2235
		 else
2236
		    m = v;
2237
		 while ( pos < 32 && (m & (1<<pos))==0 ) pos++;
2238
		 len = pos;
2239
		 while ( len < 32 && (m & (1<<len)) ) len++;
2240
		 next = len;
2241
		 len -= pos;
2242
		 pos = 31-pos;
2243
		 while ( next < 32 && (m & (1<<next))==0 ) next++;
2244
		 if ( next == 32 )
2245
		 {
2246
		    int d;
2247
		    space nsp;
2248
		    a1 = reg_operand(sonl,sp);
2249
		    nsp = guardreg(a1,sp);
2250
		    d = getreg(nsp.fixed);
2251
		    if ( v&1 )
2252
		    {
2253
		       /* 2 instructions! Is this worth implementing ? */
2254
		       rr_ins(i_copy,a1,d);
2255
		       iiir_ins(i_depi,c_,0,pos,len,d);
2256
		    }
2257
		    else
2258
		       riir_ins(i_extru,c_,a1,pos,len,d);
2259
		    cij_ins(branch,0,d,lab);
2260
		    return mka;
2261
		 }
2262
	      }
2263
	   }
2264
	}
2265
 
2266
	a1 = reg_operand(l, sp);
2267
	if ( name(r) == val_tag )
2268
	{
2269
	   if ( unsgn && (no(r)==0) && (n==2 || n==3) )
2270
	   {
2271
	      if ( n==3 )
2272
		 ub_ins(cmplt_,lab);
2273
	   }
2274
	   else
2275
	      cij_ins(branch,no(r),a1,lab);
2276
	}
2277
	else
2278
	{
2279
 	   space nsp;
2280
 	   nsp = guardreg(a1, sp);
2281
 	   a2 = reg_operand(r, nsp);
2282
 	   if ( (n != 5) && (n !=6) )
2283
	   {
2284
	      if ( (name(l) == cont_tag) && (name(son(l)) == name_tag) &&
2285
		  isse_opt(son(son(l))) )
2286
		 riir_ins(i_extrs,c_, a1,31,shape_size(sh(l)),a1);
2287
	      if ( (name(r) == cont_tag) && (name(son(r)) == name_tag) &&
2288
		   isse_opt(son(son(r))) )
2289
		 riir_ins(i_extrs,c_, a2,31,shape_size(sh(r)),a2);
2290
	   }
2291
	   cj_ins(branch,a2,a1,lab);
2292
	}
2293
	return mka;
2294
     }				
2295
  }				
2296
  /*  ENDS test_tag  */
2297
 
2298
/*****************************************************************************/
2299
 
2300
  case ass_tag:
2301
  case assvol_tag:
2302
  {
2303
     exp lhs = son(e);
2304
     exp rhs = bro(lhs);
2305
     where assdest;
2306
     space nsp;
2307
     int contreg = NOREG;
2308
     int hdrhs = name(sh(rhs));
2309
     bool is_float = is_floating(hdrhs);
2310
 
2311
#if use_long_double
2312
     if ( hdrhs == doublehd )
2313
	is_float = 0 ;
2314
#endif
2315
 
2316
     /* +++ lose chvar_tag on rhs if no result, remember to invalidate reg */
2317
     /* +++ remove name(e)==ass_tag tests now assbits_tag has gone */
2318
 
2319
     if ( name(e) == assvol_tag )
2320
     {
2321
 
2322
	/* Assign to volatile location. Disable register-location tracing. */
2323
	/* Disable peep-hole optimisation  */
2324
	comment("make_code: Assign to volatile");
2325
	clear_all();
2326
	setvolatile();
2327
     }
2328
 
2329
     if ( name(e) == ass_tag &&
2330
	  (name(rhs) == apply_tag || is_muldivrem_call(rhs)) &&
2331
	  ((is_float) || valregable(sh(rhs))) )
2332
      {
2333
	 where apply_res;
2334
	 /* set up apply_res */
2335
	 if (is_float)
2336
	 {
2337
	    freg frg;
2338
	    frg.fr = R_FR4;
2339
	    frg.dble = (hdrhs!=shrealhd);
2340
	    setfregalt(apply_res.answhere, frg);
2341
	 }
2342
	 else
2343
	 {
2344
	    setregalt(apply_res.answhere, RET0);
2345
	 }
2346
	 apply_res.ashwhere = ashof(sh(rhs));
2347
 
2348
	 code_here(rhs, sp, apply_res);
2349
	 nsp = guard(apply_res, sp);
2350
 
2351
	 assdest = locate(lhs, nsp, sh(rhs), 0);
2352
	 move(apply_res.answhere, assdest, nsp.fixed, 1);
2353
	 move(apply_res.answhere, dest, nsp.fixed, 1);
2354
 
2355
	 clear_dep_reg(lhs);
2356
	 return mka;
2357
      }
2358
 
2359
      assdest = locate(lhs, sp, sh(rhs), 0);
2360
      nsp = guard(assdest, sp);
2361
#if USE_BITAD
2362
      if (assdest.ashwhere.ashalign == 1)
2363
      {
2364
 	 /* assignment of a bitfield, get address in proper form */
2365
	 instore is;
2366
	 switch ( discrim(assdest.answhere) )
2367
	 {
2368
	    case inreg:
2369
	    {
2370
	       is.b.base = regalt(assdest.answhere);
2371
	       is.b.offset = 0;
2372
	       is.adval = 1;
2373
	       break;
2374
	    }
2375
	    case notinreg:
2376
	    {
2377
	       is = insalt(assdest.answhere);
2378
	       if ( !is.adval )
2379
	       {
2380
		  int r = getreg(nsp.fixed);
2381
		  ld_ins(i_lw,1,is.b,r);
2382
		  nsp = guardreg(r, nsp);
2383
		  is.adval = 1;
2384
		  is.b.base = r;
2385
		  is.b.offset = 0;
2386
	       }
2387
	       else
2388
		  is.b.offset = is.b.offset << 3;
2389
 	       break;
2390
	   }
2391
	   case bitad:
2392
	   {
2393
	      is = bitadalt(assdest.answhere);
2394
	      break;
2395
	   }
2396
	   default:
2397
	     fail("wrong assbits");
2398
	}
2399
	setbitadalt(assdest.answhere, is);
2400
     }
2401
     else
2402
#endif
2403
     if ( name(e) == ass_tag &&
2404
	  discrim(assdest.answhere) == notinreg &&
2405
	  assdest.ashwhere.ashsize == assdest.ashwhere.ashalign )
2406
     {
2407
	instore is;
2408
	is = insalt(assdest.answhere);
2409
	if ( !is.adval )
2410
	{			/* this is an indirect assignment, so make it
2411
				 * direct by loading pointer into reg  (and
2412
				 * remember it) */
2413
	   int r = getreg(nsp.fixed);
2414
	   ld_ins(i_lw,1,is.b,r);
2415
	   nsp = guardreg(r, nsp);
2416
	   is.adval = 1;
2417
	   is.b.base = r;
2418
	   is.b.offset = 0;
2419
	   setinsalt(assdest.answhere, is);
2420
	   keepexp(lhs, assdest.answhere);
2421
	}
2422
     }
2423
#if 1
2424
     if ( name(e) == ass_tag && is_float && discrim(assdest.answhere) == notinreg )
2425
     {
2426
	/*
2427
	 * Ensure floating point values assigned using floating point regs so
2428
	 * floating point reg tracking works better. move() uses fixed regs
2429
	 * for mem to mem, so must pre-load to floating point reg.
2430
	 */
2431
	int f = freg_operand(rhs, nsp, getfreg(nsp.flt));
2432
	freg frg;
2433
	ans aa;
2434
	frg.fr = f;
2435
	frg.dble = (hdrhs!=shrealhd);
2436
	setfregalt(aa, frg);
2437
	nsp = guardfreg(f, nsp);
2438
	move(aa, assdest, nsp.fixed, 1);
2439
	move(aa, dest, nsp.fixed, 1);
2440
	clear_dep_reg(lhs);
2441
	/* +++ frg in mka */
2442
	return mka;
2443
     }
2444
#endif
2445
     /* evaluate source into assignment destination .... */
2446
     contreg = code_here(rhs, nsp, assdest);
2447
     /* ... and move it into dest - could use assignment as value */
2448
     switch ( discrim ( assdest.answhere ) )
2449
     {
2450
	case inreg:
2451
	{
2452
	   int a = regalt(assdest.answhere);
2453
	   keepreg(rhs, a);
2454
	   /* remember that source has been evaluated into a */
2455
	   clear_dep_reg(lhs);
2456
	   /* forget register dependencies on destination */
2457
	   move(assdest.answhere, dest, nsp.fixed, 1);
2458
	   break;
2459
	}
2460
	case infreg:
2461
	{
2462
	   freg frg;
2463
	   int r;
2464
 	   frg = fregalt(assdest.answhere);
2465
	   r = frg.fr + 32;
2466
	   if (frg.dble)
2467
	      r = -r;
2468
	   keepreg(rhs, r);
2469
	   /* remember that source has been evaluated into a */
2470
	   clear_dep_reg(lhs);
2471
	   /* forget register dependencies on destination */
2472
	   move(assdest.answhere, dest, nsp.fixed, 1);
2473
	   break;
2474
	}
2475
	case notinreg:
2476
#if USE_BITAD
2477
	case bitad:
2478
#endif
2479
	{
2480
	   if ( contreg != NOREG && name(e) == ass_tag )
2481
	   {
2482
	      ans aa;
2483
	      space nnsp;
2484
	      if ( contreg > 0 && contreg < 31 )
2485
	      {
2486
		 setregalt(aa, contreg);
2487
		 nnsp = guardreg(contreg, sp);
2488
	      }
2489
	      else
2490
	      {
2491
		 freg frg;
2492
		 frg.fr = ABS_OF(contreg) - 32;
2493
		 frg.dble = (contreg < 0);
2494
		 nnsp = nsp;
2495
		 setfregalt(aa, frg);
2496
	      }
2497
	      (void) move(aa, dest, nnsp.fixed, 1);
2498
	      /* forget register dependencies on destination */
2499
	      clear_dep_reg(lhs);
2500
	      /* remember that dest contains source, provided that it is not
2501
	      * dependent on it */
2502
	      if ( name(lhs)==name_tag )
2503
	      {
2504
		 exp dc = son(lhs);
2505
		 if ( son(dc)!=nilexp )
2506
		    dc = son(dc);
2507
		 if ( shape_size(sh(dc))==shape_size(sh(rhs)) )
2508
		    keepcont(lhs,contreg);
2509
	      }
2510
	      else
2511
	      if ( !dependson(lhs,0,lhs) )
2512
		 keepcont(lhs,contreg);
2513
	      return (mka);
2514
	   }
2515
	   clear_dep_reg(lhs);
2516
	   /* forget register dependencies on destination */
2517
	   move(assdest.answhere, dest, nsp.fixed, 1);
2518
	   break;
2519
	}
2520
	case insomereg:
2521
	{
2522
	   clear_dep_reg(lhs);
2523
	   /* forget register dependencies on destination */
2524
	   move(assdest.answhere, dest, guard(assdest, sp).fixed, 1);
2525
	}
2526
	default:;
2527
 
2528
     }				/* end sw on answhere */
2529
     if (name(e) == assvol_tag)
2530
	setnovolatile();
2531
     return mka;
2532
  }
2533
  /*  ENDS ass_tag and
2534
	   assvol_tag  */
2535
 
2536
/*****************************************************************************/
2537
 
2538
  case compound_tag:
2539
  {
2540
     exp t = son(e);
2541
     space nsp;
2542
     instore str;
2543
     int r;
2544
 
2545
      /*  Initialse bitfield by constructing an appropriate constant. */
2546
     /* Other compounds are initialised from register values below   */
2547
     if ( has_bitfield(e) )
2548
     {
2549
	instore isa;
2550
	ans aa;
2551
	labexp next;
2552
 
2553
	/* word-align bitfields for ease of access */
2554
	if (dest.ashwhere.ashalign < 32)
2555
	    dest.ashwhere.ashalign =32;
2556
 
2557
	/* generate constant value... */
2558
	fix_nonbitfield(e);	/* Ensure all offsets are BIT-offsets. */
2559
	next = (labexp) malloc( sizeof(struct labexp_t) );
2560
	next->e = e;
2561
	next->lab = next_data_lab();
2562
	next->next = (labexp) 0;
2563
	current->next = next;
2564
	current = next;
2565
	isa.adval = 0;
2566
	isa.b.offset = 0;
2567
	isa.b.base = next->lab;
2568
	/* ... and place it in dest */
2569
	setinsalt(aa, isa);
2570
	mka.regmove = move(aa, dest, sp.fixed, 1);
2571
	return mka;
2572
     }
2573
 
2574
     nsp = sp;
2575
     switch ( discrim(dest.answhere) )
2576
     {
2577
	case notinreg:
2578
	{
2579
	   str = insalt(dest.answhere);	/* it should be !! */
2580
	   if ( !str.adval )
2581
	   {
2582
	      int r = getreg(sp.fixed);
2583
	      nsp = guardreg(r, sp);
2584
	      ld_ins(i_lw,1,str.b,r);
2585
	      str.adval = 1;
2586
	      str.b.base = r;
2587
	      str.b.offset = 0;
2588
	   }
2589
	   for (;;)
2590
	   {
2591
	      where newdest;
2592
	      instore newis;
2593
	      newis = str;
2594
	      newis.b.offset += no(t);
2595
 	      assert(name(t) == val_tag && al2(sh(t)) >= 8); /* offset in bits */
2596
	      setinsalt(newdest.answhere, newis);
2597
	      newdest.ashwhere = ashof(sh(bro(t)));
2598
	      assert(ashof(bro(t)).ashalign != 1); /* stray bitfield */
2599
	      code_here(bro(t), nsp, newdest);
2600
	      if ( last(bro(t)) )
2601
		 return mka;
2602
	      t = bro(bro(t));
2603
	   }
2604
	}
2605
	case insomereg:
2606
	{
2607
	   int *sr = someregalt(dest.answhere);
2608
  	   if ( *sr != -1 )
2609
	      failer("Somereg *2");
2610
 	   *sr = getreg(sp.fixed);
2611
	   setregalt(dest.answhere, *sr);
2612
	   /* ,... */
2613
       }
2614
       case inreg:
2615
       {
2616
	  code_here(bro(t), sp, dest);
2617
	  r = regalt(dest.answhere);
2618
	  assert(name(t) == val_tag);
2619
	  if ( no(t) != 0 )
2620
	     rrir_ins(i_shd,c_,r,0,32-(((al2(sh(t)) >= 8) ? (no(t) << 3) : no(t))),r);
2621
	  nsp = guardreg(r, sp);
2622
	  while ( !last(bro(t)) )
2623
	  {
2624
	     int z;
2625
 	     t = bro(bro(t));
2626
	     assert(name(t) == val_tag);
2627
	     z = reg_operand(bro(t), nsp);
2628
	     if (no(t) != 0)
2629
		rrir_ins(i_shd,c_,z,0,32-(((al2(sh(t)) >= 8) ? (no(t) << 3) : no(t))),z);
2630
	     rrr_ins(i_or,c_,r,z,r);
2631
	  }
2632
	  return mka;
2633
       }
2634
       case insomefreg:
2635
       {
2636
	  somefreg sfr;
2637
	  freg fr;
2638
   	  sfr = somefregalt(dest.answhere);
2639
	  if ( *sfr.fr != -1 )
2640
	     failer ("Somefreg *2");
2641
	  *sfr.fr = getfreg(sp.flt);
2642
	  fr.fr = *sfr.fr;
2643
	  fr.dble = sfr.dble;
2644
	  setfregalt(dest.answhere, fr);
2645
       }             		
2646
       case infreg:
2647
       {
2648
	  code_here(bro(t), sp, dest);
2649
	  if (!last(bro(t)) || name(t)!=val_tag || no(t) !=0)
2650
	     failer("No Tuples in freg");
2651
	  return mka;
2652
       }
2653
       default:;
2654
    }
2655
 
2656
  }	
2657
  /*  ENDS compound_tag  */
2658
 
2659
/*****************************************************************************/
2660
 
2661
  case nof_tag:
2662
  case concatnof_tag:
2663
  {
2664
     exp t = son(e);
2665
     space nsp;
2666
     instore str;
2667
     int r, disp = 0;
2668
#if 1
2669
     if( t==nilexp )
2670
	return mka;
2671
#endif
2672
     nsp = sp;
2673
     switch ( discrim(dest.answhere) )
2674
     {
2675
	case notinreg:
2676
	{
2677
	   str = insalt(dest.answhere);	/* it should be !! */
2678
	   if ( !str.adval )
2679
	   {
2680
	      int r = getreg(sp.fixed);
2681
	      nsp = guardreg(r, sp);
2682
 	      ld_ins(i_lw,1,str.b,r);
2683
	      str.adval = 1;
2684
	      str.b.base = r;
2685
	      str.b.offset = 0;
2686
	   }
2687
	   for (;;)
2688
	   {
2689
	      where newdest;
2690
	      instore newis;
2691
 	      newis = str;
2692
	      newis.b.offset += disp;
2693
	      setinsalt(newdest.answhere, newis);
2694
	      newdest.ashwhere = ashof(sh(t));
2695
	      code_here(t, nsp, newdest);
2696
	      if ( last(t) )
2697
 	         return mka;
2698
	      disp += (rounder(shape_size(sh(t)), shape_align(sh(bro(t)))) >> 3);
2699
	      t = bro(t);
2700
	   }
2701
	}
2702
	case insomereg:
2703
	{
2704
	   int *sr = someregalt(dest.answhere);
2705
 	   if (*sr != -1)
2706
 	      failer("Somereg *2");
2707
	   *sr = getreg(sp.fixed);
2708
	   setregalt(dest.answhere, *sr);
2709
	   /* ,... */
2710
	}
2711
	case inreg:
2712
	{
2713
	   code_here(t, sp, dest);
2714
	   r = regalt(dest.answhere);
2715
	   nsp = guardreg(r, sp);
2716
	   while (!last(t))
2717
	   {
2718
	     int z;
2719
 	     disp += rounder(shape_size(sh(t)), shape_align(sh(bro(t))));
2720
	     t = bro(t);
2721
	     z = reg_operand(t, nsp);
2722
	     rrir_ins(i_shd,c_,z,0,32-disp,z);
2723
	     rrr_ins(i_or,c_,r,z,r);
2724
	  }
2725
	  return mka;
2726
       }
2727
       default:
2728
	 failer("No Tuples in freg");
2729
    }
2730
  }
2731
  /*  ENDS nof_tag and
2732
	   concatnof_tag  */
2733
 
2734
/*****************************************************************************/
2735
 
2736
  case ncopies_tag:
2737
  {
2738
     exp t = son(e);
2739
     space nsp;
2740
     instore str;
2741
     int i, r, disp = 0;
2742
 
2743
     nsp = sp;
2744
     switch ( discrim(dest.answhere) )
2745
     {
2746
	case notinreg:
2747
	{
2748
	   str = insalt(dest.answhere);	/* it should be !! */
2749
	   if (!str.adval)
2750
	   {
2751
	      int r = getreg(sp.fixed);
2752
 	      nsp = guardreg(r, sp);
2753
	      ld_ins(i_lw,1,str.b,r);
2754
	      str.adval = 1;
2755
	      str.b.base = r;
2756
	      str.b.offset = 0;
2757
	   }
2758
	   for ( i = 1; i <= no(e); i++ )
2759
	   {
2760
	      where newdest;
2761
	      instore newis;
2762
	      newis = str;
2763
	      newis.b.offset += disp;
2764
	      setinsalt(newdest.answhere, newis);
2765
	      newdest.ashwhere = ashof(sh(t));
2766
	      code_here(t, nsp, newdest);
2767
	      disp += (rounder(shape_size(sh(t)), shape_align(sh(t))) >> 3);
2768
	   }
2769
	   return mka;
2770
	}
2771
	case insomereg:
2772
	{
2773
	   int *sr = someregalt(dest.answhere);
2774
 	   if ( *sr != -1 )
2775
 	      failer("Somereg *2");
2776
	   *sr = getreg(sp.fixed);
2777
	   setregalt(dest.answhere, *sr);
2778
	   /* ,... */
2779
	}
2780
	case inreg:
2781
	{
2782
	   code_here(t, sp, dest);
2783
	   r = regalt(dest.answhere);
2784
	   nsp = guardreg(r, sp);
2785
	   for ( i = 1; i <= no(e); i++ )
2786
	   {
2787
	      int z;
2788
 	      disp += rounder(shape_size(sh(t)), shape_align(sh(t)));
2789
	      z = reg_operand(t, nsp);
2790
	      rrir_ins(i_shd,c_,z,0,32-disp,z);
2791
	      rrr_ins(i_or,c_,r,z,r);
2792
	   }
2793
	   return mka;
2794
	}
2795
	default:
2796
	  failer("No Tuples in freg");
2797
     }
2798
   }
2799
   /*  ENDS ncopies_tag  */
2800
 
2801
/*****************************************************************************/
2802
 
2803
    case diagnose_tag :
2804
    {
2805
       /* Diagnostics */
2806
       diag_info *d = dno(e);
2807
       stab_begin(d,0,e);
2808
       mka = make_code(son(e),sp,dest,exitlab);
2809
       stab_end(d,e);
2810
       return (mka);
2811
    }
2812
    /*  ENDS diagnose_tag  */
2813
 
2814
/*****************************************************************************/
2815
 
2816
  case solve_tag:
2817
  {
2818
     exp m = bro(son(e));
2819
     int l = exitlab;
2820
 
2821
     if ( discrim(dest.answhere) == insomereg )
2822
     {
2823
	int *sr = someregalt(dest.answhere);
2824
	if (*sr != -1)
2825
 	   fail("somereg *2");
2826
	*sr = getreg(sp.fixed);
2827
	setregalt(dest.answhere, *sr);
2828
     }
2829
 
2830
     /* set up all the labels in the component labst_tags */
2831
     for (;;)
2832
     {
2833
	no(son(m)) = new_label();
2834
	if (last(m))
2835
	  break;
2836
	m = bro(m);
2837
     }
2838
     m = son(e);
2839
 
2840
     /* evaluate all the component statements */
2841
     for (;;)
2842
     {
2843
	int fl = make_code(m, sp, dest, l).lab;
2844
 
2845
	clear_all();
2846
	if ( fl != 0 )
2847
	   l = fl;
2848
 
2849
	if ( !last(m) )
2850
	{
2851
 	   /* jump to end of solve */
2852
	   if ( l == 0 )
2853
	      l = new_label();
2854
	   if (name(sh(m)) != bothd)
2855
	   {
2856
	      ub_ins(cmplt_,l);
2857
	   }
2858
	}
2859
	if ( last(m) )
2860
	{
2861
	   mka.lab = l;
2862
	   return mka;
2863
	};
2864
	m = bro(m);
2865
     }
2866
  }
2867
  /*  ENDS solve_tag  */
2868
 
2869
/*****************************************************************************/
2870
 
2871
  case case_tag:
2872
  {
2873
     int r = reg_operand(son(e),sp);
2874
     /* evaluate controlling integer into register r */
2875
     exp z = bro(son(e));
2876
     exp zt = z;
2877
     long n;
2878
     long l;
2879
     long u = 0x80000000;
2880
 
2881
     unsigned long approx_range;  /* max(u-l, 0x7fffffff) avoiding overflow */
2882
     bool use_jump_vector;
2883
     l = no(zt);
2884
     for(n = 1;;n++)
2885
     {
2886
	/* calculate crude criterion for using jump vector or branches */
2887
	if ( u + 1 != no(zt) && son(zt) != nilexp)
2888
	   n++;
2889
	if (last(zt))
2890
	{
2891
	   u = (son(zt) != nilexp) ? no(son(zt)) : no(zt);
2892
	   break;
2893
	}
2894
	if ( son(zt) != nilexp )
2895
	{
2896
	   u = no(son(zt));
2897
	}
2898
	else
2899
	{
2900
	   if ( u + 1 == no(zt) )
2901
	      u += 1;
2902
	}
2903
	zt = bro(zt);
2904
     }
2905
     /* 
2906
     *    Now l is lowest controlling value, u is highest, and n is number of
2907
      *   cases
2908
       */
2909
     if ( u - l < 0 )
2910
	approx_range = 0x7fffffff;  /* u-l overflowed into -ve, use huge */
2911
     else
2912
	approx_range = u - l;
2913
     if ( approx_range < 16 )
2914
     {
2915
	/* small jump vector needed, decide on instuctions executed only */
2916
 
2917
	unsigned jump_vector_cnt = ((l >= 0 && l <= 4) ? 8 : 9);
2918
	unsigned cmp_jmp_step_cnt = 2 + (!SIMM13(l)) + (!SIMM13(u));
2919
 
2920
	/* cmp & jmp, delay slot filled plus possibly load of large consts */
2921
	/* +++ assume default used as often as case, is this good? */
2922
	unsigned default_weight = 1;	/* likelyhood of default against
2923
					 * single case */
2924
	unsigned total_case_test_chain_cnt =
2925
	((((n + 1) * cmp_jmp_step_cnt) * n) / 2) + 1	/* unused delay slot on
2926
	    last case */ ;
2927
	unsigned default_test_chain_cnt =
2928
	(n * cmp_jmp_step_cnt) + 1 /* unused delay slot */ ;
2929
	unsigned average_test_chain_cnt =
2930
	(total_case_test_chain_cnt + (default_test_chain_cnt * default_weight)) / (n + default_weight);
2931
 
2932
 
2933
	use_jump_vector = jump_vector_cnt <= average_test_chain_cnt;
2934
	FULLCOMMENT2("case_tag small jump vector: jump_vector_cnt=%d average_test_chain_cnt=%d",
2935
		     jump_vector_cnt, average_test_chain_cnt);
2936
     }
2937
     else
2938
     {
2939
	/*
2940
	 * space-time product criterion for jump vector instead of tests and
2941
	 * branches
2942
	 */
2943
	unsigned long range_factor = approx_range + 9;
2944
	unsigned long n_factor = ((unsigned long) n * n) / 2;
2945
 
2946
	use_jump_vector = range_factor <= n_factor;
2947
 
2948
     }
2949
 
2950
     assert(l <= u);
2951
     assert(n >= 0);
2952
 
2953
     if ( use_jump_vector )
2954
     {
2955
	/* use jump vector, 8/9 insts overhead */
2956
	int endlab = new_label();
2957
	int veclab = 0;
2958
	char zeroveclab[16];
2959
	int mr = getreg(sp.fixed);
2960
	zeroveclab[0] = 0;
2961
	if (!PIC_code)
2962
	{
2963
	   veclab = next_data_lab();
2964
	   sprintf(zeroveclab, "LD$%ld", (long)veclab);
2965
	}
2966
	if ( l >= 0 && l <= 4 )
2967
	{
2968
	   /* between 0 and 4 dummy table entries used to avoid subtract */
2969
	   cij_ins(c_lu,u,r,endlab);
2970
 	   n = 0;
2971
	   if (PIC_code)
2972
	   {
2973
	      bl_in(cmplt_,".+8",GR1);
2974
	      iiir_ins(i_depi,c_,0,31,2,GR1);
2975
	      ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,16,GR1,GR1);
2976
	   }
2977
	   else
2978
	   {
2979
	      ir_ins(i_ldil,fs_L,zeroveclab,0,GR1);
2980
	      ld_ir_ins(i_ldo,cmplt_,fs_R,zeroveclab,0,GR1,GR1);
2981
	   }
2982
	   ld_rr_ins(i_ldwx,cmplt_S,r,GR1,GR1);
2983
	}
2984
	else
2985
	{
2986
	   /* subtract to index jump vector */
2987
	   if SIMM11( -l )
2988
	      irr_ins(i_addi,c_,fs_,-l,r,mr);
2989
	   else
2990
	   {
2991
	      ir_ins(i_addil,fs_L,empty_ltrl,-l,r);
2992
	      ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,-l,GR1,mr);
2993
	   }
2994
	   cij_ins(c_lu,u-l,mr,endlab);
2995
	   n = l;
2996
	   if (PIC_code)
2997
	   {
2998
	      bl_in(cmplt_,".+8",GR1);
2999
	      iiir_ins(i_depi,c_,0,31,2,GR1);
3000
	      ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,16,GR1,GR1);
3001
	   }
3002
	   else
3003
	   {
3004
	      ir_ins(i_ldil,fs_L,zeroveclab,0,GR1);
3005
	      ld_ir_ins(i_ldo,cmplt_,fs_R,zeroveclab,0,GR1,GR1);
3006
	   }
3007
	   ld_rr_ins(i_ldwx,cmplt_S,mr,GR1,GR1);
3008
	}
3009
 
3010
	extj_reg_ins(i_bv,GR1 /* not a call */ );
3011
	z_ins(i_nop);
3012
 
3013
	/* build the jump vector */
3014
 
3015
	if (!PIC_code)
3016
	   outlab("LD$",veclab);
3017
   	for (;;)
3018
	{
3019
	   char labl[48];
3020
	   for (; no(z) > n; n++ )
3021
	   {
3022
	      sprintf(labl,"L$$%d",endlab);
3023
	      out_directive(".WORD",labl);
3024
	   }
3025
	   u = (son(z) == nilexp) ? n : no(son(z));
3026
	   for (; n <= u; n++ )
3027
	   {
3028
	      sprintf(labl,"L$$%d",no(son(pt(z))));
3029
	      out_directive(".WORD",labl);
3030
	   }
3031
	   if (last(z))
3032
	      break;
3033
	   z = bro(z);
3034
	}
3035
	clear_all();
3036
	outlab("L$$",endlab);
3037
	return mka;
3038
     }
3039
     else
3040
     {
3041
	/*
3042
	*    Use branches - tests are already ordered
3043
	 */
3044
	int over = 0;
3045
	mm lims;
3046
	lims = maxmin(sh(son(e)));
3047
	if ( is_signed(sh(son(e))) )
3048
	{
3049
	   long u,l;
3050
	   for (;;)
3051
	   {
3052
	      int lab = no(son(pt(z)));
3053
	      l = no(z);
3054
	      if ( son(z) == nilexp )
3055
	      {
3056
 	         /* only single test required */
3057
		 cij_ins(c_eq,l,r,lab);
3058
		 if ( l == lims.maxi )
3059
		    lims.maxi -= 1;
3060
		 else
3061
		 if ( l == lims.mini )
3062
		    lims.mini += 1;
3063
	      }
3064
	      else
3065
	      if ( u = no(son(z)), l > lims.mini )
3066
	      {
3067
		 if ( u >= lims.maxi )
3068
		 {
3069
		    cij_ins(c_leq,l,r,lab);
3070
		    lims.maxi = l - 1;
3071
		 }
3072
		 else
3073
		 {
3074
		    if ( over == 0 )
3075
		       over = new_label();
3076
		    cij_ins(c_g,l,r,over);
3077
		    cij_ins(c_geq,u,r,lab);
3078
		    lims.mini = u + 1;
3079
		 }
3080
	      }
3081
	      else 
3082
	      if ( u < lims.maxi )
3083
	      {
3084
		 cij_ins(c_geq,u,r,lab);
3085
		 lims.mini = u + 1;
3086
	      }
3087
	      else
3088
	      {
3089
		 ub_ins(cmplt_,lab);
3090
	      }
3091
	      if ( last(z) )
3092
	      {
3093
		 if ( over != 0 )
3094
		 {
3095
		    clear_all();
3096
		    outlab("L$$",over);
3097
		 }
3098
		 return mka;
3099
	      }
3100
	      z = bro(z);
3101
	   }
3102
	}
3103
	else
3104
	{
3105
	   unsigned long maxi,mini,u,l;
3106
	   maxi = (unsigned)lims.maxi;
3107
	   mini = (unsigned)lims.mini;
3108
	   for (;;)
3109
	   {
3110
	      int lab = no(son(pt(z)));
3111
	      l = no(z);
3112
	      if ( son(z) == nilexp )
3113
	      {
3114
		 /* only single test required */
3115
		 cij_ins(c_eq,l,r,lab);
3116
		 if (l == maxi)
3117
		   maxi -= 1;
3118
		 else
3119
		 if (l == mini)
3120
		    mini += 1;
3121
	      }
3122
	      else
3123
	      if ( u = no(son(z)), l > mini )
3124
	      {
3125
		 if ( u >= maxi) 
3126
		 {
3127
		    cij_ins(c_lequ,l,r,lab);
3128
		    maxi = l - 1;
3129
		 }
3130
		 else
3131
		 {
3132
		    if ( over == 0 )
3133
		    {
3134
		       over = new_label();
3135
		    }
3136
		    cij_ins(c_gu,l,r,over);
3137
		    cij_ins(c_gequ,u,r,lab);
3138
		    mini = u + 1;
3139
		 }
3140
	      }
3141
	      else
3142
	      if ( u < maxi ) 
3143
	      {
3144
		 cij_ins(c_gequ,u,r,lab);
3145
		 mini = u + 1;
3146
	      }
3147
	      else
3148
	      {
3149
		 ub_ins(cmplt_,lab);
3150
 	      }
3151
	      if ( last(z) )
3152
	      {
3153
		 if ( over != 0 )
3154
		 {
3155
		    clear_all();
3156
		    outlab("L$$",over);
3157
		 }
3158
		 return mka;
3159
	      }
3160
 	      z = bro(z);
3161
	   }
3162
	}
3163
     }
3164
  }
3165
  /*  ENDS case_tag  */
3166
 
3167
/*****************************************************************************/
3168
 
3169
  case offset_add_tag:
3170
  case plus_tag:
3171
  {
3172
     if (optop(e))
3173
     {
3174
	mka.regmove = comm_op(e, sp, dest, i_add);
3175
     }
3176
     else
3177
     {
3178
	/* error_jump to "trap" on overflow */
3179
	int trap = trap_label(e);
3180
	int l,r,d;
3181
	space nsp;
3182
	l = reg_operand(son(e),sp);
3183
	nsp = guardreg(l,sp);
3184
	r = reg_operand(bro(son(e)),guardreg(l,sp));
3185
	nsp = guardreg(r,sp);
3186
	if ( discrim(dest.answhere)!=inreg || (d=regalt((dest).answhere))==0 )
3187
	   d = getreg(nsp.fixed);
3188
	if (shape_size(sh(e))==32)
3189
	{
3190
	   rrr_ins(i_add,is_signed(sh(e)) ? c_NSV : c_NUV,l,r,d);
3191
	   ub_ins(cmplt_N,trap);
3192
	}
3193
	else
3194
	{
3195
	   rrr_ins(i_add,c_,l,r,d);
3196
	   test_if_outside_of_var(name(sh(e)),d,trap);
3197
	}
3198
	if (discrim(dest.answhere)!=inreg)
3199
	{
3200
	   ans aa;
3201
	   setregalt(aa,d);
3202
	   move(aa,dest,sp.fixed,1);
3203
	}
3204
	mka.regmove=d;
3205
     }
3206
     return mka;
3207
  }
3208
  /*  ENDS offset_add_tag and plus_tag  */
3209
 
3210
/*****************************************************************************/
3211
 
3212
  case offset_pad_tag:
3213
  {
3214
     int r,o;
3215
     ans aa;
3216
     space nsp;
3217
     if ( (al2(sh(son(e))) < al2(sh(e))) || (al1_of(sh(e))->al.al_val.al_frame & 4)!=0 )
3218
     {
3219
	int al = (al2(sh(son(e)))==1) ? al2(sh(e)) : (al2(sh(e))/8);
3220
	r = GETREG(dest,sp);
3221
	o = reg_operand(son(e),sp); 
3222
	if ((al1_of(sh(e))->al.al_val.al_frame & 4)==0)
3223
	{
3224
	   irr_ins(i_addi,c_,fs_,al-1,o,r);
3225
	   logical_op(i_and,-al,r,r);
3226
	}
3227
	else
3228
	   logical_op(i_and,-al,o,r);
3229
	if ( al2(sh(son(e)))==1 )
3230
	{
3231
	   /*   Operand is bit-offset, byte-offset required.   */
3232
	   riir_ins(i_extrs,c_,r,28,29,r);
3233
	}
3234
     }
3235
     else
3236
     {
3237
	if ( al2(sh(e))!=1 || al2(sh(son(e)))==1 )
3238
	{
3239
	   /*   Already aligned correctly, whether as bit or byte-offset.   */
3240
	   e = son(e);
3241
	   goto tailrecurse;
3242
	}
3243
	r = GETREG(dest,sp);
3244
	o = reg_operand(son(e),sp);
3245
	rrr_ins(i_sh3add,c_,o,0,r);
3246
     }
3247
     setregalt(aa,r);
3248
     nsp = guardreg(r,sp);
3249
     mka.regmove = move(aa,dest,nsp.fixed,0);
3250
     return mka;
3251
  }
3252
  /*  ENDS offset_pad_tag  */
3253
 
3254
/*****************************************************************************/
3255
 
3256
  case locptr_tag:
3257
  {
3258
     int ansr = GETREG(dest,sp);
3259
     int pr = reg_operand(son(e),sp);
3260
     space nsp;
3261
     ans aa;
3262
     baseoff b;
3263
     b.base = pr; b.offset = FP_BOFF.offset;
3264
     ld_ins(i_lw,0,b,ansr);
3265
     setregalt(aa,ansr);
3266
     nsp = guardreg(ansr,sp);
3267
     mka.regmove = move(aa,dest,nsp.fixed,0);
3268
     return mka;
3269
  }
3270
  /*  ENDS locptr_tag  */
3271
 
3272
/*****************************************************************************/
3273
 
3274
  case chvar_tag:
3275
  {
3276
      /* 
3277
       *   Change integer variety.
3278
       */
3279
      exp arg = son(e); 		/* source of chvar, adjusted below */
3280
      int size_e = shape_size(sh(e));  /* shape of result */
3281
      int to = (int) name(sh(e));     /* to hd */
3282
      int from;			     /* from hd */
3283
      int sreg,dreg;
3284
      bool inmem_dest;
3285
      space nsp;
3286
       /*
3287
       *   For a series of chvar_tags, do large to small in one go.
3288
      */
3289
      while (name(arg) == chvar_tag && shape_size(sh(arg)) >= size_e )
3290
      {
3291
  	 arg = son(arg);
3292
      }
3293
      from = (int) name(sh(arg));
3294
#if 1
3295
      if (from == bitfhd)
3296
      {
3297
	 switch (shape_size(sh(arg)))
3298
	 {
3299
	     case 8:
3300
		sh(arg) = is_signed(sh(arg)) ? scharsh : ucharsh;
3301
		from = name(sh(arg));
3302
		break;
3303
	     case 16:
3304
		sh(arg) = is_signed(sh(arg)) ? swordsh : uwordsh;
3305
		from = name(sh(arg));
3306
		break;
3307
	     case 32:
3308
		sh(arg) = is_signed(sh(arg)) ? slongsh : ulongsh;
3309
		from = name(sh(arg));
3310
		break;
3311
	 }
3312
      }
3313
 
3314
      if (to == bitfhd)
3315
      {
3316
	 switch (shape_size(sh(e)))
3317
	 {
3318
	     case 8:
3319
		sh(e) = is_signed(sh(e)) ? scharsh : ucharsh;
3320
		to = name (sh(e));
3321
		break;
3322
	     case 16:
3323
		sh(e) = is_signed(sh(e)) ? swordsh : uwordsh;
3324
		to = name (sh(e));
3325
		break;
3326
	     case 32:
3327
		sh(e) = is_signed(sh(e)) ? slongsh : ulongsh;
3328
		to = name (sh(e));
3329
		break;
3330
	  }
3331
      }
3332
#endif
3333
      /*
3334
       *   Small to large conversions.
3335
       */
3336
      if ( from == to || ( to == uwordhd && from == ucharhd ) ||
3337
	   ( to == ulonghd && ( from == ucharhd || from == uwordhd ) ) ||
3338
	   ( to == swordhd && ( from == scharhd || from == ucharhd ) ) ||
3339
	   ( to == slonghd && from != ulonghd ) )
3340
      {
3341
	 ans aa;
3342
	 if ( discrim(dest.answhere)==inreg )
3343
	 {
3344
	    sreg = regalt(dest.answhere);
3345
	    reg_operand_here(arg, sp, sreg);
3346
	 }
3347
	 else
3348
	 {
3349
	    sreg = reg_operand(arg, sp);
3350
	 }
3351
	 setregalt(aa,sreg);
3352
	 mka.regmove = move(aa, dest, sp.fixed, is_signed(sh(e)));
3353
	 return mka;
3354
      }
3355
 
3356
      sreg = reg_operand(arg,sp);
3357
      nsp = guardreg(sreg,sp);
3358
 
3359
      if ( !optop(e) )
3360
      {
3361
	 bool signf = is_signed(sh(arg));
3362
	 bool signt = is_signed(sh(e));
3363
	 int trap = trap_label(e);
3364
	 if ( signf )
3365
	 {
3366
	    if ( signt )
3367
	    {
3368
	       if ( to == scharhd )
3369
		  riir_ins(i_extrs,c_,sreg,31,8,GR1);
3370
	       else
3371
	       if ( to == swordhd )
3372
		  riir_ins(i_extrs,c_,sreg,31,16,GR1);
3373
	       cj_ins(c_neq,sreg,GR1,trap);
3374
	    }
3375
	    else
3376
	    {
3377
	       if ( from == scharhd )
3378
	       {
3379
		  if (OPTIM)
3380
		     bb_in(bit_is_1,sreg,24,trap);
3381
		  else
3382
		  {
3383
		     riir_ins(i_extru,c_eq,sreg,24,1,0);
3384
		     ub_ins(cmplt_,trap);
3385
		  }
3386
	       }
3387
	       else
3388
	       if ( from == swordhd )
3389
	       {
3390
		  if ( to == ucharhd )
3391
		  {
3392
		     riir_ins(i_extru,c_eq,sreg,23,24,0);
3393
		     ub_ins(cmplt_,trap);
3394
		  }
3395
		  else
3396
		  {
3397
		     if (OPTIM)
3398
			bb_in(bit_is_1,sreg,16,trap);
3399
		     else
3400
		     {
3401
			riir_ins(i_extru,c_eq,sreg,16,1,0);
3402
			ub_ins(cmplt_,trap);
3403
		     }
3404
		  }
3405
	       }
3406
	       else
3407
	       {
3408
		  if ( to == ucharhd )
3409
		  {
3410
		     riir_ins(i_extru,c_eq,sreg,23,24,0);
3411
		     ub_ins(cmplt_,trap);
3412
		  }
3413
		  else
3414
		  if ( to == uwordhd )
3415
		  {
3416
		     riir_ins(i_extru,c_eq,sreg,15,16,0);
3417
		     ub_ins(cmplt_,trap);
3418
		  }
3419
		  else
3420
		  {
3421
		     if (OPTIM)
3422
			bb_in(bit_is_1,sreg,0,trap);
3423
		     else
3424
		     {
3425
			riir_ins(i_extru,c_eq,sreg,0,1,0);
3426
			ub_ins(cmplt_,trap);
3427
		     }
3428
		  }
3429
	       }
3430
	    }
3431
	 }
3432
	 else
3433
	 {
3434
	    if ( signt )
3435
	    {
3436
	       if ( to == scharhd )
3437
	       {
3438
		  riir_ins(i_extru,c_eq,sreg,24,25,0);
3439
		  ub_ins(cmplt_,trap);
3440
	       }
3441
	       else
3442
	       if ( to == swordhd )
3443
	       {
3444
		  riir_ins(i_extru,c_eq,sreg,16,17,0);
3445
		  ub_ins(cmplt_,trap);
3446
	       }
3447
	       else
3448
	       {
3449
		  if (OPTIM)
3450
		     bb_in(bit_is_1,sreg,0,trap);
3451
		  else
3452
		  {
3453
		     riir_ins(i_extru,c_eq,sreg,0,1,0);
3454
		     ub_ins(cmplt_,trap);
3455
		  }
3456
	       }
3457
	    }
3458
	    else
3459
	    {
3460
	       if ( to == ucharhd )
3461
		  riir_ins(i_extru,c_,sreg,31,8,GR1);
3462
	       else
3463
		  riir_ins(i_extru,c_,sreg,31,16,GR1);
3464
	       cj_ins(c_neq,sreg,GR1,trap);
3465
	    }
3466
	 }
3467
      }
3468
 
3469
      switch (discrim(dest.answhere))
3470
      {
3471
	 case inreg:
3472
	 {
3473
	    dreg = regalt(dest.answhere);
3474
	    if (dreg == 0)
3475
	       return mka;		/* dest void */
3476
	    inmem_dest = 0;
3477
	    break;
3478
	 }
3479
	 case insomereg:
3480
	 {
3481
 	    int *dr = someregalt(dest.answhere);
3482
	    dreg = getreg(sp.fixed);
3483
	    *dr = dreg;
3484
	    inmem_dest = 0;
3485
	    break;
3486
	 }
3487
	 default:
3488
	 {
3489
	    dreg = getreg(sp.fixed);
3490
	    inmem_dest = 1;
3491
	    break;
3492
	 }
3493
      }
3494
      if (inmem_dest && size_e <= shape_size(sh(arg)))
3495
      {
3496
 	 /* going to smaller sized memory, store will truncate */
3497
	 ans aa;
3498
	 setregalt(aa, sreg);
3499
	 (void) move(aa, dest, nsp.fixed, 1);
3500
      }
3501
      else
3502
      {
3503
	 /* from != to */
3504
 
3505
	 /* Shorten type if needed */
3506
	 if ( to==ucharhd )
3507
	 {
3508
	    if (dreg==sreg)
3509
	       riir_ins(i_dep,c_,0,23,24,dreg);
3510
	    else
3511
	       riir_ins(i_zdep,c_,sreg,31,8,dreg);
3512
	 }
3513
	 else
3514
	 if ( to==scharhd )
3515
	 {
3516
	    riir_ins(i_extrs,c_,sreg,31,8,dreg);
3517
	 }
3518
	 else
3519
	 if ( to==uwordhd )
3520
	 {
3521
	    if ( from!=ucharhd )
3522
	    {
3523
	       if ( dreg==sreg )
3524
		  riir_ins(i_dep,c_,0,15,16,dreg);
3525
	       else
3526
		  riir_ins(i_zdep,c_,sreg,31,16,dreg);
3527
	    }
3528
	    else
3529
	    if ( sreg!=dreg )
3530
	       rr_ins(i_copy,sreg,dreg);
3531
	 }
3532
	 else
3533
	 if ( to == swordhd )
3534
	 {
3535
	    if ( from!=scharhd && from!=ucharhd )
3536
	    {
3537
	       riir_ins(i_extrs,c_,sreg,31,16,dreg);
3538
	    }
3539
	    else
3540
	    if ( sreg!=dreg )
3541
	       rr_ins(i_copy,sreg,dreg);
3542
	 }
3543
	 else
3544
	 {
3545
	    if ( sreg!=dreg )
3546
	       rr_ins(i_copy,sreg,dreg);
3547
	 }
3548
	 if (inmem_dest)
3549
	 {
3550
	    ans aa;
3551
	    setregalt(aa, dreg);
3552
	    move(aa, dest, nsp.fixed, 1);
3553
	 }
3554
	 else
3555
	 {
3556
	    mka.regmove = dreg;
3557
	 }
3558
      }
3559
      return mka;
3560
   }			
3561
   /*  ENDS chvar_tag  */
3562
 
3563
/*****************************************************************************/
3564
 
3565
  case minus_tag:
3566
  case offset_subtract_tag:
3567
  {
3568
     if (optop(e))
3569
     {
3570
	mka.regmove = non_comm_op(e, sp, dest, i_sub);
3571
     }
3572
     else
3573
     {
3574
	/* error_jump to "trap" on overflow */
3575
	int trap = trap_label(e);
3576
	int l,r,d;
3577
	space nsp;
3578
	int us = !is_signed(sh(e));
3579
	l = reg_operand(son(e),sp);
3580
	nsp = guardreg(l,sp);
3581
	r = reg_operand(bro(son(e)),guardreg(l,sp));
3582
	nsp = guardreg(r,sp);
3583
	if ( discrim(dest.answhere)!=inreg || (d=regalt((dest).answhere))==0 )
3584
	   d = getreg(nsp.fixed);
3585
	if ( us || shape_size(sh(e))==32 )
3586
	{
3587
	   rrr_ins(i_sub,us ? c_gequ : c_NSV,l,r,d);
3588
	   ub_ins(cmplt_N,trap);
3589
	}
3590
	else
3591
	{
3592
	   rrr_ins(i_sub,c_,l,r,d);
3593
	   test_if_outside_of_var(name(sh(e)),d,trap);
3594
	}
3595
	if (discrim(dest.answhere)!=inreg)
3596
	{
3597
	   ans aa;
3598
	   setregalt(aa,d);
3599
	   move(aa,dest,sp.fixed,1);
3600
	}
3601
	mka.regmove=d;
3602
     }
3603
     return mka;
3604
  }
3605
  /*  ENDS minus_tag and  
3606
	   offset_subtract_tag  */
3607
 
3608
/*****************************************************************************/
3609
 
3610
  case mult_tag:
3611
  case offset_mult_tag:
3612
  {
3613
     bool sgned = is_signed(sh(e));
3614
     if (optop(e))
3615
     {
3616
	FULLCOMMENT2("mult_tag: name(sh(e))=%d sgned=%d", name(sh(e)), sgned);
3617
	mka.regmove = do_mul_comm_op(e, sp, dest, sgned);
3618
	return mka;
3619
     }
3620
     else
3621
     {
3622
	int trap = trap_label(e);
3623
	int end = new_label();
3624
	space nsp;
3625
	ans aa;
3626
	baseoff b;
3627
	b = mem_temp(0);
3628
	reg_operand_here(son(e),sp,ARG0);
3629
	nsp = guardreg(ARG0,sp);
3630
	reg_operand_here(bro(son(e)),nsp,ARG1);
3631
	if (sgned)
3632
	{
3633
	   irr_ins(i_comiclr,c_neq,fs_,1,ARG0,RET0);
3634
	   rr_ins(i_copy,ARG1,RET0);
3635
	   cij_ins(c_gu,2,ARG0,end);
3636
	   irr_ins(i_comiclr,c_neq,fs_,1,ARG1,RET0);
3637
	   rr_ins(i_copy,ARG0,RET0);
3638
	   cij_ins(c_gu,2,ARG1,end);
3639
	   iiir_ins(i_zdepi,c_,-1,0,1,GR1);
3640
	   cj_ins(c_eq,ARG0,GR1,trap);
3641
	   cj_ins(c_eq,ARG1,GR1,trap);
3642
	   ld_ins(i_lo,1,b,GR1);
3643
	   b.base = GR1;
3644
	   b.offset = 4;
3645
	   rrr_ins(i_xor,c_,ARG0,ARG1,ARG2);
3646
	   rrr_ins(i_comclr,c_geq,ARG0,0,0);
3647
	   rrr_ins(i_sub,c_,0,ARG0,ARG0);
3648
	   rrr_ins(i_comclr,c_geq,ARG1,0,0);
3649
	   rrr_ins(i_sub,c_,0,ARG1,ARG1);
3650
	   st_ins(i_sw,ARG1,b);     
3651
	   b.offset = 0;
3652
	   st_ins(i_sw,ARG0,b);     
3653
	   ldf_ins(i_fldd,b,13);
3654
	   rrrf_ins(i_xmpyu,f_,12,14,13);
3655
	   cmp_rrf_ins(i_fcmp,f_sgl,c_eq,12,0);       
3656
	   z_ins(i_ftest);
3657
	   ub_ins(cmplt_N,trap);
3658
	   stf_ins(i_fstw,14,b);
3659
	   ld_ins(i_lw,1,b,RET0);
3660
	   rrr_ins(i_comclr,c_geq,ARG2,0,0);
3661
	   rrr_ins(i_sub,c_,0,RET0,RET0);
3662
	   rrr_ins(i_xor,c_geq,RET0,ARG2,0);
3663
	   ub_ins(cmplt_N,trap);
3664
	   outlab("L$$",end);
3665
	}
3666
	else
3667
	{
3668
	   ld_ins(i_lo,1,b,GR1);
3669
	   b.base = GR1;
3670
	   b.offset = 4;
3671
	   st_ins(i_sw,ARG1,b);     
3672
	   b.offset = 0;
3673
	   st_ins(i_sw,ARG0,b);     
3674
	   ldf_ins(i_fldd,b,13);
3675
	   rrrf_ins(i_xmpyu,f_,12,14,13);
3676
	   cmp_rrf_ins(i_fcmp,f_sgl,c_eq,12,0);       
3677
	   z_ins(i_ftest);
3678
	   ub_ins(cmplt_N,trap);
3679
	   stf_ins(i_fstw,14,b);
3680
	   ld_ins(i_lw,1,b,RET0);
3681
	}
3682
	test_if_outside_of_var(name(sh(e)),RET0,trap);
3683
	setregalt(aa,RET0);
3684
	mka.regmove = move(aa, dest, nsp.fixed, 0);
3685
	clear_t_regs();
3686
	return mka;          	
3687
     }
3688
  }				
3689
  /*  ENDS mult_tag and
3690
	   offset_mult_tag  */
3691
 
3692
/*****************************************************************************/
3693
 
3694
  case div0_tag:
3695
  case div1_tag:
3696
  case div2_tag:
3697
  case offset_div_by_int_tag:
3698
  case offset_div_tag:
3699
  {
3700
     bool sgned = is_signed(sh(e));
3701
     mka.regmove = do_div_op(e,sp,dest,sgned);
3702
     return mka;
3703
  }
3704
  /*  ENDS div0_tag,
3705
	   div1_tag,
3706
	   div2_tag,
3707
	   offset_div_by_int_tag and
3708
	   offset_div_tag  */
3709
 
3710
/*****************************************************************************/
3711
 
3712
  case rem0_tag:
3713
  case mod_tag: /* i.e. rem1_tag */
3714
  case rem2_tag:
3715
  {
3716
     bool sgned = is_signed(sh(e));
3717
     mka.regmove = do_rem_op(e, sp, dest, sgned);
3718
     return mka;
3719
  }
3720
  /*  ENDS rem0_tag,
3721
	   mod_tag and
3722
	   rem2_tag  */
3723
 
3724
/*****************************************************************************/
3725
 
3726
  case abs_tag:
3727
  {
3728
     int d;
3729
     ans a;
3730
     space nsp;
3731
     int us = !is_signed(sh(e));
3732
     int sz = shape_size(sh(e));
3733
     if (us)
3734
     {
3735
	d = GETREG(dest,sp);
3736
	if (d==0 && !(optop(e)))
3737
	   d = getreg(sp.fixed);
3738
	reg_operand_here(son(e),sp,d);
3739
     }
3740
     else
3741
     if (optop(e))
3742
     {
3743
	int r = reg_operand(son(e),sp);
3744
	d = GETREG(dest,sp);
3745
	if (r==d)
3746
	{
3747
	   rrr_ins(i_sub,c_leq,0,d,GR1);
3748
	   rr_ins(i_copy,GR1,d);
3749
	}
3750
	else
3751
	{
3752
	   rrr_ins(i_sub,c_geq,0,r,d);
3753
	   rr_ins(i_copy,r,d);
3754
	}
3755
	tidyshort(d,sh(e));
3756
     }
3757
     else
3758
     {
3759
	int trap = trap_label(e);
3760
	int lab = new_label();
3761
	d = GETREG(dest,sp);
3762
	if (d==0 && !(optop(e)))
3763
	   d = getreg(sp.fixed);
3764
	reg_operand_here(son(e),sp,d);
3765
	if (sz==32)
3766
	{
3767
	   cj_ins(c_geq,d,0,lab);        
3768
	   rrr_ins(i_sub,c_NSV,0,d,d);
3769
	   ub_ins(cmplt_N,trap);
3770
	   outlab("L$$",lab);
3771
	}
3772
	else
3773
	{
3774
	   cj_ins(c_geq,d,0,lab);        
3775
	   if (sz==16)
3776
	      iiir_ins(i_zdepi,c_,-1,16,17,GR1);
3777
	   else
3778
	      iiir_ins(i_zdepi,c_,-1,24,25,GR1);
3779
	   cj_ins(c_eq,d,GR1,trap);
3780
	   rrr_ins(i_sub,c_,0,d,d);
3781
	   outlab("L$$",lab);
3782
	}
3783
	tidyshort(d,sh(e));
3784
     }
3785
     setregalt(a,d);
3786
     nsp = guardreg(d,sp);
3787
     mka.regmove = move(a, dest, nsp.fixed, 0);
3788
     return mka;
3789
  }
3790
  /*  ENDS abs_tag  */
3791
 
3792
/*****************************************************************************/
3793
 
3794
  case max_tag:
3795
  case min_tag: 
3796
  case offset_max_tag: 
3797
  {
3798
     int a,d;
3799
     ans aa;
3800
     space nsp;
3801
     ins_p cond;
3802
     exp l = son(e);
3803
     exp r = bro(son(e));
3804
     int nshl = name(sh(l));
3805
     if  ( discrim(dest.answhere)==inreg )
3806
	 d = regalt(dest.answhere);
3807
     else
3808
	 d = getreg(sp.fixed);
3809
     nsp = guardreg(d,sp);
3810
     a = reg_operand(l,nsp);
3811
     if ( nshl==scharhd || nshl==swordhd || nshl==slonghd || nshl==offsethd) 
3812
	cond = ( name(e)==min_tag ? c_geq : c_leq );
3813
     else
3814
	cond = ( name(e)==min_tag ? c_gequ : c_lequ );
3815
     if ( name(r)==val_tag && SIMM11(no(r)) )
3816
     {
3817
	int n=no(r);
3818
	rr_ins(i_copy,a,d);
3819
	irr_ins(i_comiclr,cond,fs_,n,a,0);
3820
	ir_ins(i_ldi,fs_,empty_ltrl,n,d);
3821
     }
3822
     else
3823
     {
3824
	int b;
3825
	nsp = guardreg(a,nsp);
3826
	b = reg_operand(r,nsp);
3827
	rr_ins(i_copy,a,d);
3828
	rrr_ins(i_comclr,cond,b,a,0);
3829
	rr_ins(i_copy,b,d);
3830
     }
3831
     setregalt(aa, d);
3832
     mka.regmove = move(aa, dest, sp.fixed, 1);
3833
     return mka;
3834
  } 
3835
  /*  ENDS max_tag,
3836
	   min_tag and
3837
	   offset_max_tag  */
3838
 
3839
/*****************************************************************************/
3840
 
3841
  case make_lv_tag:
3842
  {
3843
     int d;
3844
     ans a;
3845
     space nsp;
3846
     char label_name[32];
3847
     if (discrim(dest.answhere)==inreg)
3848
	d = regalt(dest.answhere);
3849
     else
3850
	d = getreg(sp.fixed);
3851
     sprintf(label_name,"L$$%d",no(son(pt(e))));
3852
     if (PIC_code)
3853
     {
3854
	int n = next_PIC_pcrel_lab(); 
3855
	char s[64];
3856
	sprintf(s,"%s-$PIC_pcrel$%d",label_name,n);
3857
	bl_in(cmplt_,".+8",GR1);
3858
	iiir_ins(i_depi,c_,0,31,2,GR1);
3859
	outlab("$PIC_pcrel$",n);
3860
	ir_ins(i_addil,fs_L,s,0,GR1);     
3861
	ld_ir_ins(i_ldo,cmplt_,fs_R,s,0,GR1,d);
3862
     }
3863
     else
3864
     {
3865
	ir_ins(i_ldil,fs_L,label_name,0,d);
3866
	ld_ir_ins(i_ldo,cmplt_,fs_R,label_name,0,d,d); 
3867
     }
3868
     setregalt(a, d);
3869
     nsp=guardreg(d,sp);
3870
     move(a, dest, nsp.fixed, 0);
3871
     mka.regmove = d; 
3872
     return mka;
3873
  }
3874
 
3875
 
3876
  case long_jump_tag:
3877
  {
3878
     int envr = reg_operand(son(e),sp);    
3879
     int lab = reg_operand(bro(son(e)), guardreg(envr,sp));
3880
     extj_reg_ins(i_bv,lab);
3881
     rr_ins(i_copy,envr,GR4); /* GR4==EP in the enviroment we're jumping to */
3882
     return mka;
3883
  }
3884
 
3885
 
3886
  case offset_negate_tag:
3887
  {
3888
     mka.regmove=monop(e,sp,dest,i_subi);
3889
     return mka;
3890
  }
3891
  /*  ENDS offset_negate_tag  */
3892
 
3893
 
3894
  case neg_tag:
3895
  {
3896
     if (optop(e))
3897
     {
3898
	mka.regmove = monop(e,sp,dest,i_sub);
3899
     }
3900
     else
3901
     {
3902
	/* error_jump to "trap" on overflow */
3903
	int trap = trap_label(e);
3904
	int d = GETREG(dest,sp);
3905
	int us = !is_signed(sh(e));
3906
	if ( d==0 )
3907
	   d = getreg(sp.fixed);
3908
	reg_operand_here(son(e),sp,d);
3909
	if ( us || shape_size(sh(e))==32 )
3910
	{
3911
	   rrr_ins(i_sub,us ? c_gequ : c_NSV,0,d,d);
3912
	   ub_ins(cmplt_N,trap);
3913
	}
3914
	else
3915
	{
3916
	   rrr_ins(i_sub,c_,0,d,d);
3917
	   test_if_outside_of_var(name(sh(e)),d,trap);
3918
	}
3919
	if (discrim(dest.answhere)!=inreg)
3920
	{
3921
	   ans aa;
3922
	   setregalt(aa,d);
3923
	   move(aa,dest,sp.fixed,1);
3924
	}
3925
	mka.regmove = d;
3926
     }
3927
     return mka;
3928
  }
3929
  /* end neg_tag */
3930
 
3931
 
3932
  case shl_tag:
3933
  case shr_tag:
3934
    {
3935
      exp s = son(e);
3936
      exp b = bro(s);
3937
      int a;
3938
      int d;
3939
      ans aa;
3940
      space nsp;
3941
      bool sgned = is_signed(sh(e));
3942
      int sz = shape_size(sh(e));
3943
      a = getreg(sp.fixed);
3944
 
3945
      if (name(b)==val_tag)
3946
      {
3947
	 int n = no(b)&(sz-1);
3948
	 reg_operand_here(s,sp,a);
3949
	 nsp = guardreg(a, sp);
3950
	 d = GETREG(dest,nsp);
3951
	 if (n==0)
3952
	 {
3953
	    if (a!=d)
3954
	       rr_ins(i_copy,a,d);
3955
	 }
3956
	 else
3957
	 {
3958
	    if (name(e)==shr_tag)
3959
	       riir_ins(sgned ? i_extrs : i_extru,c_,a,31-n,sz-n,d);
3960
	    else
3961
	       rrir_ins(i_shd,c_,a,0,32-n,d);
3962
	 }
3963
      }
3964
      else
3965
      {
3966
	 int ar;
3967
	 if ( name(s)==val_tag && SIMM5(no(s)) && name(e)==shl_tag )
3968
	 {
3969
	    int n = no(s);
3970
	    nsp = sp;
3971
	    d = GETREG(dest,nsp);
3972
	    ar = reg_operand(b, nsp);
3973
	    irr_ins(i_subi,c_lu,fs_,31,ar,GR1);
3974
	    r_ins(i_mtsar,GR1);
3975
	    irr_ins(i_comiclr,c_lu,fs_,31,GR1,d);
3976
	    iir_ins(i_zvdepi,c_,n,32,d);
3977
	 }
3978
	 else
3979
	 {
3980
	    reg_operand_here(s,sp,a);
3981
	    nsp = guardreg(a, sp);
3982
	    d = GETREG(dest,nsp);
3983
	    ar = reg_operand(b, nsp);
3984
	    if (name(e)==shr_tag)
3985
	    {
3986
	       if (sgned)
3987
	       {
3988
		  /* sole variable arithmetic shift right */
3989
		  irr_ins(i_subi,c_,fs_,31,ar,GR1);
3990
		  r_ins(i_mtsar,GR1);
3991
		  rir_ins(i_vextrs,c_,a,sz,d);
3992
	       }
3993
	       else
3994
	       {
3995
		  /* sole variable logical shift right */
3996
		  r_ins(i_mtsar,ar);
3997
		  rrr_ins(i_vshd,c_,0,a,d);
3998
	       }
3999
	    }
4000
	    else
4001
	    {
4002
	       /* sole variable logical shift left */
4003
	       if (a==d)
4004
	       {
4005
		   irr_ins(i_subi,c_gequ,fs_,31,ar,GR1);
4006
		   rr_ins(i_copy,0,d);
4007
		   r_ins(i_mtsar,GR1);
4008
		   rir_ins(i_zvdep,c_,d,32,d);
4009
	       } 
4010
	       else
4011
	       {
4012
		  irr_ins(i_subi,c_lu,fs_,31,ar,GR1);
4013
		  r_ins(i_mtsar,GR1);
4014
		  irr_ins(i_comiclr,c_lu,fs_,31,GR1,d);
4015
		  rir_ins(i_zvdep,c_,a,32,d);
4016
	       }
4017
	    }
4018
	 }
4019
       }
4020
       if ( !optop(e) && name(e)==shl_tag && sz<32 )
4021
       {
4022
	  int trap = trap_label(e);
4023
	  riir_ins(i_extru,c_eq,d,31-sz,32-sz,0);
4024
	  ub_ins(cmplt_,trap);
4025
       }
4026
       setregalt(aa, d);
4027
       move(aa, dest, nsp.fixed, 1);
4028
       mka.regmove = d;
4029
       return mka;
4030
 
4031
    }				/* end shl, shr */
4032
 
4033
  case minptr_tag:
4034
    {
4035
      mka.regmove = non_comm_op( e, sp, dest, i_sub );
4036
      return mka;
4037
    }
4038
 
4039
  case make_stack_limit_tag:
4040
    {
4041
      mka.regmove = comm_op( e, sp, dest, i_add );
4042
      return mka;
4043
    }
4044
 
4045
  case fplus_tag:
4046
    {
4047
      mka.regmove = fop( e, sp, dest, i_fadd );
4048
      return mka;
4049
    }
4050
 
4051
  case fminus_tag:
4052
    {
4053
      mka.regmove = fop( e, sp, dest, i_fsub );
4054
      return mka;
4055
    }
4056
 
4057
  case fmult_tag:
4058
    {
4059
      mka.regmove = fop( e, sp, dest, i_fmpy );
4060
      return mka;
4061
    }
4062
 
4063
  case fdiv_tag:
4064
    {
4065
      mka.regmove = fop( e, sp, dest, i_fdiv );
4066
      return mka;
4067
    }
4068
 
4069
  case fneg_tag:
4070
  {
4071
     int a1,r1;
4072
     int dble = (name(sh(e))==shrealhd ? 0 : 1);
4073
     freg frg;
4074
     baseoff b;
4075
 
4076
#if use_long_double
4077
     if ( name(sh(e)) == doublehd )
4078
     {
4079
	quad_op( e, sp, dest );
4080
	return(mka) ;
4081
     }
4082
#endif
4083
 
4084
     r1 = getfreg(sp.flt);
4085
     a1 = freg_operand(son(e), sp, r1);
4086
 
4087
     if (!optop(e))
4088
     {
4089
	b = zero_exception_register(sp);
4090
     }
4091
     if ( discrim(dest.answhere)==infreg ) 
4092
     {
4093
	frg = fregalt(dest.answhere);
4094
	clear_freg(frg.fr<<1);
4095
	if (dble)
4096
	{
4097
	   rrrf_ins(i_fsub,f_dbl,1,3*a1+1,3*(frg.fr)+1);
4098
	   clear_freg((frg.fr<<1)+1);
4099
	}
4100
	else
4101
	   rrrf_ins(i_fsub,f_sgl,0,3*a1,3*(frg.fr));
4102
	if (!optop(e))
4103
	{
4104
	   trap_handler(b,trap_label(e),(OVERFLOW|UNDERFLOW));
4105
	}
4106
     }
4107
     else
4108
     {
4109
	ans aa;
4110
	frg.fr = r1;
4111
	frg.dble = dble;
4112
	setfregalt(aa, frg);
4113
	clear_freg(r1<<1);
4114
	if (dble)
4115
	{
4116
	   rrrf_ins(i_fsub,f_dbl,1,3*a1+1,3*r1+1);
4117
	   clear_freg((r1<<1)+1);
4118
	}
4119
	else
4120
	   rrrf_ins(i_fsub,f_sgl,0,3*a1,3*r1);
4121
	if (!optop(e))
4122
	{
4123
	   trap_handler(b,trap_label(e),(OVERFLOW|UNDERFLOW));
4124
	}
4125
	move(aa,dest,sp.fixed,1);
4126
     }
4127
 
4128
     mka.regmove = (dble ? -(frg.fr + 32) : (frg.fr + 32));
4129
     if (!optop(e))
4130
       checknan(e, mka.regmove);
4131
     return mka;
4132
  }
4133
 
4134
  case fabs_tag:
4135
    {
4136
      freg frg;
4137
      int a1,r1;
4138
      bool dble;
4139
      baseoff b;
4140
 
4141
#if use_long_double
4142
      if ( name(sh(e)) == doublehd )
4143
      {
4144
	 quad_op ( e, sp, dest );
4145
	 return(mka) ;
4146
      }
4147
#endif
4148
 
4149
      r1 = getfreg(sp.flt);
4150
      a1 = freg_operand(son(e), sp, r1);
4151
      dble = isdbl(sh(e));
4152
 
4153
      if (!optop(e))
4154
      {
4155
	 b = zero_exception_register(sp);
4156
      }
4157
      switch ( discrim ( dest.answhere ) )
4158
      {
4159
      case infreg:
4160
	{
4161
	  frg = fregalt(dest.answhere);
4162
	  clear_freg(frg.fr<<1);
4163
	  if (dble)
4164
	  {
4165
	     rrf_ins(i_fabs,f_dbl,"",3*a1+1,3*(frg.fr)+1);
4166
	     clear_freg((frg.fr<<1)+1);
4167
	  }
4168
	  else
4169
	     rrf_ins(i_fabs,f_sgl,"",3*a1,3*(frg.fr));
4170
	  if (!optop(e))
4171
	  {
4172
	     trap_handler(b,trap_label(e),OVERFLOW|UNDERFLOW);
4173
	  }
4174
	  break;
4175
	}
4176
 
4177
      default:
4178
	{
4179
	  ans aa;
4180
 
4181
	  frg.fr = r1;
4182
	  frg.dble = dble;
4183
	  setfregalt(aa, frg);
4184
	  clear_freg(r1<<1);
4185
	  if (dble)
4186
	  {
4187
	     rrf_ins(i_fabs,f_dbl,"",3*a1+1,3*r1+1);
4188
	     clear_freg((r1<<1)+1);
4189
	  }
4190
	  else
4191
	     rrf_ins(i_fabs,f_sgl,"",3*a1,3*r1);
4192
	  if (!optop(e))
4193
	  {
4194
	     trap_handler(b,trap_label(e),OVERFLOW|UNDERFLOW);
4195
	  }
4196
	  move(aa, dest, sp.fixed, 1);
4197
	}
4198
      }
4199
 
4200
      mka.regmove = (dble ? -(frg.fr + 32) : (frg.fr + 32));
4201
      if (!optop(e))
4202
	checknan(e, mka.regmove);
4203
      return mka;
4204
    }
4205
 
4206
  case float_tag:
4207
    {
4208
      exp in = son(e);
4209
      where w;
4210
      int f = ( discrim ( dest.answhere )  == infreg)
4211
      ? regalt(dest.answhere)	/* cheat */
4212
      : getfreg(sp.flt);
4213
      freg frg;
4214
      ans aa;
4215
      ash ain ;
4216
      int from ;
4217
      bool from_sgned  ;
4218
 
4219
      ain = ashof(sh(in));
4220
      from = name(sh(in));
4221
      from_sgned = is_signed(sh(in));
4222
 
4223
      /*
4224
       *   error_jump would be superfluous.
4225
       */
4226
 
4227
#if use_long_double
4228
      if ( name(sh(e))==doublehd ) 
4229
      {
4230
	 quad_op( e, sp, dest );
4231
	 return(mka) ;
4232
      }
4233
#endif
4234
 
4235
 
4236
      frg.fr = f;
4237
      frg.dble = isdbl( sh(e) );
4238
 
4239
      if (ain.ashsize == 32 && !from_sgned)
4240
      {
4241
 
4242
	/*
4243
	 * Unsigned 32 bit to float. No single HPPA instruction to handle
4244
	 * this. We handle it thus:  stw r,mem_temp(0), fldws memtemp(0) fR,
4245
	 * fcpy,sgl 0,f, fcnvxf,dbl,(sgl or dbl) f,(fL or f).
4246
	 */
4247
 
4248
	int r = reg_operand(in, sp);
4249
 
4250
	st_ins(i_sw, r, mem_temp(0));
4251
	ldf_ins(i_fldw, mem_temp(0), (3*f)+2);
4252
	rrf_ins(i_fcpy,f_sgl,"",0,3*f+1);
4253
	if (name(sh(e))==shrealhd)
4254
	   rrf_ins(i_fcnvxf,f_dbl,f_sgl,3*f+1,3*f);
4255
	else
4256
	   rrf_ins(i_fcnvxf,f_dbl,f_dbl,3*f+1,3*f+1);
4257
 
4258
      }
4259
      else if (ain.ashsize == 32)
4260
      {
4261
	/* signed 32 bit to float */
4262
	/* pretend the int is a one word float to move to float reg */
4263
	freg fint;
4264
 
4265
	fint.fr = f;
4266
	fint.dble = 0;
4267
	setfregalt(w.answhere, fint);
4268
	w.ashwhere = ashof(sh(in));
4269
	code_here(in, sp, w);
4270
	if (name(sh(e))==shrealhd)
4271
	   rrf_ins(i_fcnvxf,f_sgl,f_sgl,3*f,3*f);
4272
	else
4273
	   rrf_ins(i_fcnvxf,f_sgl,f_dbl,3*f,3*f+1);
4274
      }
4275
      else
4276
      {
4277
	/* bytes and halfs must go through fixpt regs */
4278
	int r = reg_operand(in, sp);
4279
 
4280
	/* store and load to move to float reg */
4281
	st_ins(i_sw, r, mem_temp(0));
4282
	ldf_ins(i_fldw,mem_temp(0),3*f);
4283
	if (name(sh(e))==shrealhd)
4284
	   rrf_ins(i_fcnvxf,f_sgl,f_sgl,3*f,3*f);
4285
	else
4286
	   rrf_ins(i_fcnvxf,f_sgl,f_dbl,3*f,3*f+1);
4287
      }
4288
 
4289
      setfregalt(aa, frg);
4290
      move(aa, dest, sp.fixed, 1);
4291
      mka.regmove = ((frg.dble) ? -(f + 32) : (f + 32));
4292
      return mka;
4293
    }
4294
 
4295
  case chfl_tag:
4296
    {
4297
      int to = name(sh(e));
4298
      int from = name(sh(son(e)));
4299
      bool dto = isdbl( sh(e) );
4300
      bool dfrom = isdbl( sh(son(e)) );
4301
      freg frg;
4302
      ans aa;
4303
      where w;
4304
      baseoff b;
4305
#if use_long_double
4306
      if ( to==doublehd )
4307
      {
4308
	 if ( from==doublehd )
4309
	 {
4310
	    /* no change in representation */
4311
	    return ( make_code(son(e),sp,dest,exitlab) ) ;
4312
	 }
4313
	 quad_op( e, sp, dest ) ;
4314
	 return ( mka ) ;
4315
      }
4316
      else 
4317
      if ( from==doublehd )
4318
      {
4319
	 quad_op( e, sp, dest ) ;
4320
	 frg.fr = 4 ;
4321
	 frg.dble = dto;
4322
	 setfregalt(aa,frg) ;
4323
       	 (void) move(aa,dest,sp.fixed,1) ;
4324
	 return (mka) ;
4325
      }
4326
#endif
4327
      if (!dto && !dfrom)
4328
      {
4329
	 /* no change in representation */
4330
	 if (!optop(e))
4331
	 {
4332
	    b = zero_exception_register(sp);
4333
	 }
4334
	 return make_code(son(e), sp, dest, exitlab);
4335
      }
4336
      else
4337
      {
4338
	if ( discrim ( dest.answhere )  == infreg)
4339
	{
4340
	  frg = fregalt(dest.answhere);
4341
	}
4342
	else
4343
	{
4344
	  frg.fr = getfreg(sp.flt);
4345
	}
4346
	frg.dble = dfrom;
4347
	setfregalt(aa, frg);
4348
	w.answhere = aa;
4349
	w.ashwhere = ashof(sh(son(e)));
4350
	code_here(son(e), sp, w);
4351
	if (!optop(e))
4352
	{
4353
	   b = zero_exception_register(sp);
4354
	}
4355
	if (dfrom)
4356
	   rrf_ins(i_fcnvff,f_dbl,f_sgl,3*(frg.fr)+1,3*(frg.fr));
4357
	else
4358
	   rrf_ins(i_fcnvff,f_sgl,f_dbl,3*(frg.fr),3*(frg.fr)+1);
4359
	if (!optop(e))
4360
	{
4361
	   trap_handler(b,trap_label(e),(OVERFLOW|UNDERFLOW));
4362
	}
4363
	frg.dble = dto;
4364
	setfregalt(aa, frg);
4365
	move(aa, dest, sp.fixed, 1);
4366
	mka.regmove = ((frg.dble) ? -(frg.fr + 32) : (frg.fr + 32));
4367
	return mka;
4368
      }
4369
    }
4370
 
4371
  case and_tag:
4372
    {
4373
#if 0
4374
      exp r = son(e);
4375
      exp l = bro(son(e));
4376
      ans aa;
4377
 
4378
      /* +++ enable this optimisation for big-endian */
4379
      if (last(l) && name(l) == val_tag && (no(l) == 255 || no(l) == 0xffff)
4380
	  && ((name(r) == name_tag && regofval(r) == R_NO_REG)
4381
	      || (name(r) == cont_tag &&
4382
		  (name(son(r)) != name_tag
4383
		   || regofval(son(r)) > 0
4384
		   )
4385
		  )
4386
	      )
4387
	  && (aa = iskept(r), ( discrim ( aa )  == inreg && regalt(aa) == 0))
4388
	)
4389
      {				/* can use load short instructions */
4390
	where w;
4391
	int dsize = dest.ashwhere.ashsize;
4392
	int asize = (no(l) == 255) ? 8 : 16;
4393
 
4394
	w = locate(r, sp, sh(r), 0);
4395
	if ( discrim ( w.answhere )  == notinreg
4396
	    &&  discrim ( dest.answhere )  == notinreg && no(l) == 0xffff)
4397
	{
4398
	  instore isw;
4399
	  instore isd;
4400
 
4401
	  isw = insalt(w.answhere);
4402
	  isd = insalt(dest.answhere);
4403
	  if (!isw.adval && isd.adval && isw.b.base == isd.b.base &&
4404
	      isd.b.offset == isw.b.offset)
4405
	  {
4406
	    if (dsize > 16)
4407
	    {
4408
	      isd.b.offset += 2;/* just clear out top bits */
4409
	      ls_ins(i_sh, 0, isd.b);
4410
	    }
4411
	    return mka;
4412
	  }			/* else drop through to load short case */
4413
	}
4414
 
4415
	dest.ashwhere.ashsize = dest.ashwhere.ashalign =
4416
	  min(dsize, asize);
4417
	mka.regmove
4418
	  = move(w.answhere, dest, guard(w, sp).fixed, 0 /* unsigned */ );
4419
      }
4420
      else
4421
#endif
4422
      {
4423
	mka.regmove = comm_op(e, sp, dest, i_and);
4424
      }
4425
      return mka;
4426
    }
4427
  case or_tag:
4428
    {
4429
      mka.regmove = comm_op(e, sp, dest, i_or);
4430
      return mka;
4431
    }
4432
 
4433
  case xor_tag:
4434
    {
4435
      mka.regmove = comm_op(e, sp, dest, i_xor);
4436
      return mka;
4437
    }
4438
 
4439
  case not_tag:
4440
    {
4441
      mka.regmove = monop(e,sp,dest,i_uaddcm);
4442
      return mka;
4443
    }
4444
 
4445
    /* +++ mips uses same code as name_tag for cont/contvol_tag should we combine? */
4446
  case cont_tag:
4447
  case contvol_tag:
4448
    {
4449
 
4450
      if (name(e) == contvol_tag)
4451
      {
4452
	/*
4453
	 * Load contents of volatile location. Diasble register-location
4454
	 * tracing. Disable peep-hole optimisation.
4455
	 */
4456
	comment("make_code: Load volatile");
4457
	clear_all();
4458
	setvolatile();
4459
      }
4460
 
4461
#if DO_INDEXED_LOADS
4462
      /* see if an indexed shift load is appropriate */
4463
 
4464
      if (name(e)==cont_tag)
4465
      {
4466
	 exp sone,p,o;
4467
	 bool sgned=is_signed(sh(e));
4468
	 int dr,ashsize;
4469
	 ans aa;
4470
	 ash ashe;
4471
	 int is_float = is_floating(name(sh(e)));
4472
	 ashe=ashof(sh(e));
4473
	 ashsize=ashe.ashsize;
4474
	 if ( name(son(e))==reff_tag && !no(son(e)) )
4475
	    sone = son(son(e));
4476
	 else
4477
	    sone = son(e);
4478
	 if (son(sone)!=(exp)0)
4479
	 {
4480
	    if (name(son(sone))==offset_mult_tag)
4481
	    {
4482
	       o=son(sone);   /* an offset ? */
4483
	       p=bro(o);     /* a pointer ? */
4484
	    }
4485
	    else
4486
	    {
4487
	       p=son(sone);   /* a pointer ? */
4488
	       o=bro(p);     /* an offset ? */
4489
	    }
4490
	    if ( name(sone) == addptr_tag && name(o)==offset_mult_tag
4491
				          && name(bro(son(o)))==val_tag )
4492
	    { 
4493
	       long shift;
4494
	       shift=no(bro(son(o)));
4495
	       if ( ashe.ashalign==ashsize &&
4496
		    ((ashsize==16 && (shift==2 || shift==0)) ||
4497
		     (ashsize==32 && (shift==4 || shift==0)) ||
4498
		     (ashsize==64 && is_float && (shift==8 || shift==0))) )
4499
	       {
4500
		  space nsp;
4501
		  int lhs,rhs;
4502
		  CONST char *cmplt;
4503
		  if (son(sone)->commuted)
4504
		  {
4505
		     lhs = reg_operand(son(o),sp);
4506
		     nsp = guardreg(lhs,sp);
4507
		     rhs = reg_operand(p,nsp);
4508
		  }
4509
		  else
4510
		  {
4511
		     rhs = reg_operand(p,sp);
4512
		     nsp = guardreg(rhs,sp);
4513
		     lhs = reg_operand(son(o),nsp);
4514
		  }            
4515
		  /* register rhs contains the evaluation of pointer
4516
		     operand of addptr */
4517
		  cmplt = ( shift==0 ? cmplt_ : cmplt_S );
4518
		  if (is_float)
4519
  	          {
4520
		     freg dfreg;
4521
  	             if ( discrim ( dest.answhere )  == infreg)
4522
			dfreg = fregalt(dest.answhere);
4523
		     else
4524
			dfreg.fr = getfreg(sp.flt);
4525
 
4526
		     dfreg.dble = (ashsize==64);
4527
 
4528
		     if (dfreg.dble)
4529
			ldf_rr_ins(i_flddx,cmplt,lhs,rhs,(3*dfreg.fr)+1);
4530
		     else
4531
			ldf_rr_ins(i_fldwx,cmplt,lhs,rhs,3*dfreg.fr);
4532
	    	     setfregalt(aa, dfreg);
4533
		  }
4534
		  else
4535
		  {              
4536
		     dr = ( discrim ( dest.answhere )  == inreg) ? dest.answhere.val.regans : getreg(guardreg(lhs,nsp).fixed);
4537
		     if (ashsize==32)
4538
			ld_rr_ins(i_ldwx,cmplt,lhs,rhs,dr);
4539
		     else 
4540
		     {
4541
			ld_rr_ins(i_ldhx,cmplt,lhs,rhs,dr);
4542
			if (sgned)
4543
			   riir_ins(i_extrs,c_,dr,31,16,dr);
4544
		     }
4545
		     setregalt(aa, dr);
4546
		  }
4547
		  mka.regmove = move(aa, dest, nsp.fixed, sgned);
4548
		  return mka;
4549
	       }
4550
	    }
4551
	 }
4552
      }
4553
#endif
4554
 
4555
 
4556
 
4557
#if DO_INDEXED_LOADS
4558
#ifndef NO_REGREG_LOADS
4559
   {
4560
      exp addptr_sons = son(son(e));
4561
      /* see if we can use reg(reg) addressing for this load */
4562
      if ( name(son(e))==addptr_tag )
4563
      {
4564
	 ash ashe ;
4565
	 int ashsize ;
4566
	 bool is_float = is_floating(name(sh(e)));
4567
	 ashe = ashof(sh(e));
4568
	 ashsize = ashe.ashsize;
4569
	 if (last(bro(addptr_sons)) && ashe.ashalign==ashsize &&
4570
	     (ashsize==8 || ashsize==16 || ashsize==32 || is_float))
4571
	 {
4572
	    int lhsreg;
4573
	    int rhsreg;
4574
	    bool sgned = ((ashsize >= 32) || is_signed(sh(e)));
4575
	    ans aa;
4576
	    if (addptr_sons->commuted)
4577
	    {
4578
	       /* offset register */
4579
	       lhsreg = reg_operand(addptr_sons, sp);
4580
	       /* base register */
4581
	       rhsreg = reg_operand(bro(addptr_sons), guardreg(lhsreg, sp));
4582
	    }
4583
	    else
4584
	    {
4585
	       /* base register */
4586
	       rhsreg = reg_operand(addptr_sons, sp);
4587
	       /* offset register */
4588
	       lhsreg = reg_operand(bro(addptr_sons), guardreg(rhsreg, sp));
4589
	    }
4590
 	    if (is_float)
4591
	    {
4592
	       freg dfreg;
4593
	       if ( discrim ( dest.answhere )  == infreg)
4594
		  dfreg = fregalt(dest.answhere);
4595
	       else
4596
		  dfreg.fr = getfreg(sp.flt);
4597
 	       dfreg.dble = (ashsize==64);
4598
	       if (ashsize==32)
4599
		  ldf_rr_ins(i_fldwx,cmplt_,lhsreg,rhsreg,3*dfreg.fr);
4600
	       else
4601
		  ldf_rr_ins(i_flddx,cmplt_,lhsreg,rhsreg,(3*dfreg.fr)+1);
4602
	       setfregalt(aa, dfreg);
4603
	    }
4604
	    else
4605
	    {
4606
	       int dreg = ( discrim(dest.answhere)==inreg) ? dest.answhere.val.regans : getreg(sp.fixed);
4607
 
4608
	       if (ashsize==8)
4609
	       {
4610
		  ld_rr_ins(i_ldbx,cmplt_,lhsreg,rhsreg,dreg);
4611
		  if (sgned)
4612
		     riir_ins(i_extrs,c_,dreg,31,8,dreg);
4613
	       }
4614
	       else if (ashsize==16)
4615
	       {
4616
		  ld_rr_ins(i_ldhx,cmplt_,lhsreg,rhsreg,dreg);
4617
		  if (sgned)
4618
		     riir_ins(i_extrs,c_,dreg,31,16,dreg);
4619
	       }
4620
	       else
4621
		  ld_rr_ins(i_ldwx,cmplt_,lhsreg,rhsreg,dreg);
4622
	       setregalt(aa, dreg);
4623
	    }
4624
	    mka.regmove = move(aa, dest, sp.fixed, sgned);
4625
	    if (name(e) == contvol_tag)
4626
	    {
4627
	       mka.regmove = NOREG;
4628
	       setnovolatile();
4629
	    }
4630
	    return mka;
4631
	 } 
4632
      }
4633
   }
4634
#endif /* NO_REGREG_LOADS */
4635
#endif
4636
  }
4637
    /* FALLTHROUGH */
4638
 
4639
  case name_tag:
4640
  case field_tag:
4641
  case reff_tag:
4642
  case addptr_tag:
4643
  case subptr_tag:
4644
    {
4645
 
4646
      where w;
4647
      bool sgned;
4648
      int dr = (discrim(dest.answhere)==inreg) ? dest.answhere.val.regans : 0;
4649
      if (name(e) == contvol_tag)
4650
      {
4651
	clear_all();
4652
	setvolatile();
4653
      }
4654
      w = locate(e, sp, sh(e), dr);	/* address of arg */
4655
      sgned = ((w.ashwhere.ashsize >= 32) || ((is_signed(sh(e))) ? 1 : 0));
4656
      /* +++ load real into float reg, move uses fixed reg */
4657
      mka.regmove = move(w.answhere, dest, (guard(w, sp)).fixed, sgned);
4658
      if (name(e) == contvol_tag)
4659
      {
4660
	setnovolatile();
4661
	mka.regmove = NOREG;
4662
      }
4663
      return mka;
4664
    }				/* end cont */
4665
 
4666
 
4667
 
4668
  case string_tag:
4669
  case real_tag:
4670
  {
4671
     instore isa;
4672
     ans aa;
4673
     bool sgned = ((ashof(sh(e)).ashsize >= 32) || is_signed(sh(e)));
4674
     labexp next;
4675
      /* place constant in appropriate data segment */
4676
     next  = (labexp) malloc( sizeof(struct labexp_t) );
4677
     next->e = e;
4678
     next->lab = next_data_lab();
4679
     next->next = (labexp) 0;
4680
     current->next = next;
4681
     current = next;
4682
     isa.adval = 0;
4683
     isa.b.offset = 0;
4684
     isa.b.base = next->lab;
4685
     setinsalt(aa, isa);
4686
     mka.regmove = move(aa, dest, sp.fixed, sgned);
4687
     return mka;
4688
  }				/* end eval */
4689
 
4690
  case val_tag:
4691
    {
4692
      comment1("make_code val_tag: no(e) = %d", no(e));
4693
      if ( shape_size(sh(e))>32 ) 
4694
      {
4695
	 flt64 t;
4696
	 int ov;
4697
	 int r = getreg(sp.fixed);
4698
	 space nsp;
4699
	 int big;
4700
	 unsigned int small;
4701
	 ans aa;
4702
	 if ( discrim(dest.answhere)!=notinreg )
4703
	    return mka;
4704
	 if (isbigval(e))
4705
	 {
4706
	    t = flt_to_f64(no(e),0,&ov);
4707
	 }
4708
	 else
4709
	 {
4710
	    t.big = (is_signed(sh(e)) && no(e)<0)?-1:0;
4711
	    t.small = no(e);
4712
	 }
4713
	 nsp = guardreg(r,sp);
4714
	 big = t.big;
4715
	 imm_to_r(big,r);
4716
	 setregalt(aa,r);
4717
	 dest.ashwhere.ashsize = 32;
4718
	 dest.ashwhere.ashalign = 32;
4719
	 move(aa,dest,nsp.fixed,1);
4720
	 small = t.small;
4721
	 imm_to_r(small,r);
4722
	 dest.answhere.val.instoreans.b.offset+=4;
4723
	 move(aa,dest,nsp.fixed,1);
4724
	 return mka; 	
4725
      }
4726
      if (no(e) == 0)
4727
      {
4728
	goto null_tag_case;
4729
      }
4730
      else
4731
      {
4732
	ash a;
4733
 
4734
	a = ashof(sh(e));
4735
	if (a.ashsize == 32 || is_signed(sh(e))==0)
4736
 	   constval = no(e);
4737
	else if (a.ashsize == 8)
4738
	{
4739
	  constval = no(e) & 255;
4740
	  constval -= (constval & 128) << 1;
4741
	}
4742
	else
4743
	{
4744
	  constval = no(e) & 65535;
4745
	  constval -= (constval & 32768) << 1;
4746
	}
4747
	comment1("make_code val_tag: constval = %d", constval);
4748
	goto moveconst;
4749
      }
4750
    }
4751
 
4752
  case top_tag:
4753
  case prof_tag:
4754
  case clear_tag:
4755
  {
4756
     /* Do nothing */
4757
     if ( discrim(dest.answhere)==insomereg)
4758
     {
4759
	int *sr = someregalt(dest.answhere);
4760
	if (*sr!=-1)
4761
	   fail ( "Illegal register" );
4762
	*sr = GR0 ;
4763
     }
4764
     return mka;
4765
  }
4766
 
4767
  case null_tag:
4768
null_tag_case:
4769
    {
4770
      ans aa;
4771
 
4772
      setregalt(aa, GR0);
4773
      mka.regmove = move(aa, dest, sp.fixed, 1);
4774
      return mka;
4775
    }
4776
 
4777
 
4778
  case last_local_tag:
4779
  {
4780
     int r = GETREG(dest,sp);
4781
     ans aa;
4782
     baseoff b;
4783
     int maxargbytes = max_args>>3;
4784
     b.base = SP;
4785
     b.offset = -maxargbytes - 4;
4786
     ld_ins(i_lw,1,b,r);
4787
     setregalt(aa, r);
4788
     mka.regmove = move(aa,dest,sp.fixed,1);
4789
     return mka;
4790
  }
4791
  /*  ENDS last_local_tag  */
4792
 
4793
 
4794
  case local_free_tag:
4795
  {
4796
     exp s = son(e);
4797
     int r = reg_operand(s,sp);
4798
     int maxargbytes = max_args>>3;
4799
     if (SIMM14(maxargbytes))
4800
	ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,maxargbytes,r,SP);
4801
     else
4802
     {
4803
	ir_ins(i_addil,fs_L,empty_ltrl,maxargbytes,r);
4804
	ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,maxargbytes,GR1,SP);
4805
     }
4806
     if (Has_tos)
4807
	reset_tos();
4808
     return mka;
4809
  }
4810
  /*  ENDS local_free  */
4811
 
4812
 
4813
  case local_free_all_tag:
4814
  {
4815
     if (Has_vsp)
4816
     {
4817
	rr_ins(i_copy,EP,SP);
4818
	if (Has_tos)
4819
	   reset_tos();
4820
     }
4821
     return mka;
4822
  }      
4823
 
4824
  case current_env_tag:
4825
  {
4826
     int r = GETREG(dest,sp);
4827
     ans aa;
4828
     rr_ins(i_copy,EP,r);
4829
     setregalt(aa, r);
4830
     mka.regmove = move(aa, dest, sp.fixed, 1);
4831
     return mka;
4832
  } 
4833
 
4834
  case env_offset_tag: case general_env_offset_tag:
4835
  {
4836
     constval = frame_offset(son(e));
4837
     goto moveconst;
4838
  }  
4839
 
4840
 
4841
  case set_stack_limit_tag:
4842
  {
4843
     baseoff b ;
4844
     int r = reg_operand( son(e), sp );
4845
     exp stl = find_named_tg("__TDFstacklim",
4846
			     f_pointer(f_alignment(f_proc)));
4847
     setvar(stl);
4848
     b = boff(stl);
4849
     st_ins(i_sw,r,b);
4850
     return mka;
4851
  }
4852
 
4853
  case give_stack_limit_tag:
4854
  {
4855
     baseoff b;
4856
     ans aa;
4857
     int r = GETREG(dest,sp);
4858
     exp stl = find_named_tg("__TDFstacklim",
4859
			     f_pointer(f_alignment(f_proc)));
4860
     setvar(stl);
4861
     b = boff(stl);
4862
     ld_ins(i_lw,1,b,r);
4863
     setregalt(aa,r);
4864
     move(aa,dest,guardreg(r,sp).fixed,1);
4865
     return mka;
4866
  }
4867
 
4868
  case trap_tag:
4869
  {
4870
     if ( no(e) == f_overflow )
4871
     {
4872
	do_exception( SIGFPE );
4873
     }
4874
     else
4875
     if ( no(e) == f_nil_access )
4876
     {
4877
	do_exception( SIGSEGV );
4878
     }
4879
     else
4880
     {
4881
	do_exception(SIGUSR1);
4882
     }
4883
     return mka;
4884
  }	
4885
 
4886
  case round_tag:
4887
  {
4888
      /*
4889
      *   Floating point variety to integer variety conversion.
4890
       */
4891
     int r = GETREG(dest,sp);
4892
     freg f1,f2;
4893
     ash a;
4894
     ans aa;
4895
     int s;
4896
     baseoff b;
4897
     space nsp;
4898
     int us = !(is_signed(sh(e)));
4899
     int rm = (int) round_number(e); 
4900
     unsigned char nm = name(sh(e));
4901
     int inmem = (discrim(dest.answhere)==notinreg);
4902
     int trap=0;
4903
     int br;
4904
     nsp = sp;
4905
     if (!optop(e))
4906
	trap = trap_label(e);
4907
      /*
4908
      *   rm = 0 = nearest, rm = 1 = smaller, rm = 2 = larger, rm = 3 = to zero
4909
       */
4910
     if (r==0 && !optop(e))
4911
     {
4912
	r = getreg(sp.fixed);
4913
	nsp = guardreg( r, sp );
4914
     }
4915
     a = ashof(sh(son(e)));
4916
     s = shape_size(sh(son(e)));
4917
     if ( name(sh(son(e)))==doublehd && use_long_double )
4918
     {
4919
	if ( rm==3 && errhandle(e)<2 )  /* can't risk calling
4920
				        *  "_U_Qfcnvfxt_dbl_to_sgl" if
4921
				        *  error_treatment is continue
4922
				         */ 
4923
	{
4924
     	   quad_op( e, nsp, dest) ;
4925
	   if ( nm == ucharhd && !inmem )
4926
	      riir_ins(i_dep,c_,0,23,24,RET0);
4927
	   else
4928
	   if ( nm == scharhd )
4929
	      riir_ins(i_extrs,c_,RET0,31,8,RET0);
4930
	   else
4931
	   if ( nm == uwordhd && !inmem )
4932
	      riir_ins(i_dep,c_,0,15,16,RET0);
4933
	   else
4934
	   if ( nm == swordhd )
4935
	      riir_ins(i_extrs,c_,RET0,31,16,RET0);
4936
	   setregalt(aa, RET0);
4937
	   mka.regmove = move(aa, dest, nsp.fixed, 1);
4938
	   if (inmem)
4939
	      mka.regmove = NOREG;
4940
	   return mka;
4941
	}
4942
	else
4943
	{
4944
	   /*  Convert to double putting result in %fr4  */   
4945
      	   quad_op( e, nsp, dest) ;
4946
	   f1.fr = 4;
4947
	   /* and treat as a double..  */
4948
	}
4949
     }
4950
     else
4951
     {
4952
	f1.fr = freg_operand(son(e),nsp,getfreg(nsp.flt));
4953
     }
4954
     b = mem_temp(0);
4955
     br = getreg(nsp.fixed);
4956
     ld_ins(i_lo,0,b,br);
4957
     b.base = br; b.offset = 0;        
4958
     if (!optop(e) && us && (shape_size(sh(e))<=32))
4959
     {
4960
	f2.fr = getfreg(guardfreg(f1.fr,nsp).flt);
4961
	rrf_ins(i_fcpy,f_dbl,"",(R_FR0*3)+1,(3*f2.fr)+1);
4962
     }
4963
     else
4964
	f2.fr = f1.fr;
4965
     if ( rm < 3 )
4966
     {
4967
	if ( rm > 0 )
4968
	{
4969
	   /* Set rounding mode bits in floating point status register      */
4970
	   if ( rm == 1 )
4971
	      iiir_ins(i_zdepi,c_,-1,22,2,r);
4972
	   else
4973
	      iiir_ins(i_zdepi,c_,-1,21,1,r);
4974
	   st_ins(i_sw,r,b);
4975
	   ldf_ins(i_fldw,b,0);  /*  n.b. this zeros the exception register  */
4976
	}
4977
	/* Round and convert. */
4978
	if (us)
4979
	{
4980
	   if ( s > 32 )
4981
	   {
4982
	      rrf_ins(i_fcnvfx,f_dbl,f_dbl,(f1.fr*3)+1,(f2.fr*3)+1);
4983
	   }
4984
	   else
4985
	   {
4986
	      rrf_ins(i_fcnvfx,f_sgl,f_dbl,(f1.fr*3)+1,(f2.fr*3)+1);
4987
	   }
4988
	}
4989
	else if ( s > 32 )
4990
	{
4991
	   rrf_ins(i_fcnvfx,f_dbl,f_sgl,(f1.fr*3)+1,(f2.fr*3)+2);
4992
	}
4993
	else
4994
	   rrf_ins(i_fcnvfx,f_sgl,f_sgl,(f1.fr*3)+1,(f2.fr*3)+2);
4995
	if (!optop(e) && !us)
4996
	   stf_ins(i_fstd,1,b);
4997
	if ( rm > 0 )
4998
	{
4999
	   /*
5000
	   *   Reset rounding mode to rm = nearest (without corrupting
5001
	   *   the exception register data)
5002
	    */
5003
	   iiir_ins(i_zdepi,c_,0,22,2,r);
5004
	   b.offset = 4;
5005
	   st_ins(i_sw,r,b);
5006
	   ldf_ins(i_fldw,b,0);
5007
	   b.offset = 0;
5008
	}
5009
     }
5010
     else
5011
     {
5012
	if ( (!optop(e)) && (!us) )
5013
	{
5014
	   /*  Zero exception register  */          
5015
	   st_ins(i_sw,GR0,b);
5016
	   ldf_ins(i_fldw,b,0);         
5017
	}
5018
	if (us)
5019
	{
5020
	   if ( s > 32 )
5021
	   {
5022
	      rrf_ins(i_fcnvfxt,f_dbl,f_dbl,(f1.fr*3)+1,(f2.fr*3)+1);
5023
	   }
5024
	   else
5025
	   {
5026
	      rrf_ins(i_fcnvfxt,f_sgl,f_dbl,(f1.fr*3)+1,(f2.fr*3)+1);
5027
	   }
5028
	}
5029
	else if ( s > 32 )
5030
	{
5031
	   rrf_ins(i_fcnvfxt,f_dbl,f_sgl,(f1.fr*3)+1,(f2.fr*3)+2);
5032
	}
5033
	else
5034
	   rrf_ins(i_fcnvfxt,f_sgl,f_sgl,(f1.fr*3)+1,(f2.fr*3)+2);
5035
	if ( (!optop(e)) && (!us) )
5036
	   stf_ins(i_fstd,1,b);
5037
     }
5038
     if (!optop(e))
5039
     {
5040
	if (us)
5041
	{
5042
	   stf_ins(i_fstd,(f2.fr*3)+1,b);
5043
	   ld_ins(i_lw,1,b,r);
5044
	   cj_ins(c_neq,r,0,trap);
5045
	   b.offset=4;
5046
	}
5047
	else
5048
	{
5049
	   /* 
5050
	   *   If the unimplemented flag in the exception 
5051
	   *   register was set, then jump to trap.
5052
	    */
5053
	   ld_ins(i_lw,0,b,r);
5054
	   imm_to_r(64,GR1);
5055
	   rrr_ins(i_and,c_eq,r,GR1,0);
5056
	   ub_ins(cmplt_N,trap);
5057
	   stf_ins(i_fstw,(f2.fr*3)+2,b);
5058
	}
5059
	ld_ins(i_lw,1,b,r);
5060
	test_if_outside_of_var(nm,r,trap);
5061
	if ( nm!=slonghd && nm!=ulonghd )
5062
	   rr_ins(i_copy,GR1,r);
5063
     }
5064
     else
5065
     {
5066
	stf_ins(i_fstw,(f2.fr*3)+2,b);
5067
	/*   Load and shorten to type if needed.   */
5068
	if ( nm == ucharhd )
5069
	{
5070
	   b.offset += 3;
5071
	   ld_ins(i_lb,0,b,r);
5072
	}
5073
	else
5074
	if ( nm == scharhd )
5075
	{
5076
	   ld_ins(i_lw,1,b,r);
5077
	   riir_ins(i_extrs,c_,r,31,8,r);
5078
	}
5079
	else
5080
	if ( nm == uwordhd )
5081
	{
5082
	   b.offset += 2;
5083
	   ld_ins(i_lh,0,b,r);
5084
	}
5085
	else
5086
	if ( nm == swordhd )
5087
	{
5088
	   ld_ins(i_lw,1,b,r);
5089
	   riir_ins(i_extrs,c_,r,31,16,r);
5090
	}
5091
	else
5092
	   ld_ins(i_lw,1,b,r);
5093
     }
5094
     setregalt(aa,r);
5095
     mka.regmove = move(aa, dest, nsp.fixed, 1);
5096
     clear_freg(f2.fr<<1);
5097
     return mka;
5098
  }
5099
 
5100
  case int_to_bitf_tag:
5101
    {
5102
      int r;
5103
      int size_res = shape_size(sh(e));
5104
      int size_op = shape_size(sh(son(e)));
5105
      ans aa;
5106
      space nsp;
5107
 
5108
      r = reg_operand(son(e), sp);
5109
 
5110
      comment1("make_code int_to_bitf_tag: size=%d", size_res);
5111
 
5112
      /* maybe this not needed if going to memory +++ */
5113
      if (size_res != size_op && size_res != 32)
5114
      {
5115
	int destr;
5116
 
5117
	switch ( discrim ( dest.answhere ) )
5118
	{
5119
      case inreg:
5120
      {
5121
	destr = regalt(dest.answhere);
5122
	break;
5123
      }
5124
  default:
5125
  {
5126
    destr = getreg(sp.fixed);
5127
  }
5128
    }
5129
 
5130
	if (r==destr)
5131
	   riir_ins(i_dep,c_,0,31-size_res,32-size_res,destr);
5132
	else
5133
	   riir_ins(i_zdep,c_,r,31,size_res,destr);
5134
	r = destr;
5135
      }
5136
 
5137
      /* r is appropriately truncated operand */
5138
 
5139
      nsp = guardreg(r, sp);
5140
      setregalt(aa, r);
5141
      move(aa, dest, nsp.fixed, 0);
5142
      return mka;
5143
    }
5144
 
5145
  case bitf_to_int_tag:
5146
    {
5147
      ash a;
5148
      int r;
5149
      where w;
5150
      bool src_sgned = is_signed(sh(son(e)));
5151
      bool target_sgned = is_signed(sh(e));
5152
 
5153
      a = ashof(sh(son(e)));
5154
      switch ( discrim ( dest.answhere ) )
5155
      {
5156
      case inreg:
5157
	{
5158
	  r = regalt(dest.answhere);
5159
	  break;
5160
	}
5161
      default:
5162
	{
5163
	  r = getreg(sp.fixed);
5164
	}
5165
      }
5166
 
5167
#if 0
5168
      /* +++ enable */
5169
      if ((name(son(e)) == cont_tag || name(son(e)) == name_tag)
5170
	  && (a.ashsize == 8 || a.ashsize == 16 || a.ashsize == 32))
5171
      {				/* simple extractions of bytes, halfs and
5172
				 * words- see transform in check */
5173
	where intreg;
5174
	int olds = sh(son(e));
5175
 
5176
	setregalt(intreg.answhere, r);
5177
	intreg.ashwhere.ashsize = a.ashsize;
5178
	intreg.ashwhere.ashalign = a.ashsize;
5179
	sh(son(e)) = sh(e);	/* should be done in scan */
5180
	w = locate(son(e), sp, sh(e), r);
5181
	move(w.answhere, intreg, guard(w, sp).fixed, is_signed(sh(e)));
5182
	move(intreg.answhere, dest, sp.fixed, 1);
5183
	sh(son(e)) = olds;
5184
	keepreg(e, r);
5185
	return mka;
5186
      }
5187
#endif
5188
 
5189
      /* else do shifts/and */
5190
      setregalt(w.answhere, r);
5191
      w.ashwhere = a;
5192
      code_here(son(e), sp, w);
5193
 
5194
      comment1("make_code bitf_to_int_tag: size=%d", a.ashsize);
5195
 
5196
      if (a.ashsize != 32 && src_sgned != target_sgned)
5197
      {
5198
	/* propogate/correct sign bits */
5199
	/* +++ make move() handle this by pasting sign down */
5200
 
5201
	comment4("make_code bitf_to_int_tag: adjusting to sign/size %d/%d -> %d/%d",
5202
		 src_sgned, a.ashsize,
5203
		 target_sgned, a.ashsize);
5204
 
5205
	if (target_sgned)
5206
	   riir_ins(i_extrs,c_,r,31,a.ashsize,r);
5207
	else
5208
	   riir_ins(i_dep,c_,0,31-a.ashsize,32-a.ashsize,r);
5209
      }
5210
 
5211
      move(w.answhere, dest, guardreg(r, sp).fixed, 0);
5212
      keepreg(e, r);
5213
      return mka;
5214
    }
5215
 
5216
  case alloca_tag:
5217
  {
5218
     /* Grow stack frame by n bytes and then grab n bytes */
5219
     exp s=son(e);
5220
     int maxargbytes=max_args>>3;
5221
     ans aa;
5222
     int r = GETREG( dest, sp );
5223
     baseoff b;
5224
     int n,t;
5225
     if ( name(s)==val_tag )  /* n is a constant */
5226
     {
5227
	n = no(s);
5228
	if (Has_ll)
5229
	{
5230
	   n+=4;
5231
	}
5232
	/*
5233
	*   Adjust n to be multiple of 64 so stack stays 64 byte aligned
5234
	 */
5235
	n = (n+63) & ~(63);
5236
	if (n != 0)
5237
	{
5238
	   /* alloca(n) = %sp - maxargbytes */
5239
	   b.base = SP; b.offset = -maxargbytes;
5240
	   ld_ins(i_lo,0,b,r);
5241
	   /* grow stack frame, i.e. %sp -> %sp + n */             
5242
	   b.offset = n;
5243
	   ld_ins( i_lo, 0, b, SP );
5244
	}
5245
     }
5246
     else
5247
     {
5248
	space nsp;
5249
	nsp = guardreg( r, sp );
5250
	n = reg_operand(s, sp);
5251
	t = getreg( nsp.fixed );   
5252
	/* adjust n so that stack stays 64 byte aligned */
5253
	if (Has_ll)
5254
	   ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,67,n,t);
5255
	else
5256
	   ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,63,n,t);
5257
	riir_ins(i_dep,c_,0,31,6,t);
5258
 
5259
	/* alloca(n) = %sp - maxargbytes */
5260
	b.base = SP;
5261
	b.offset = -maxargbytes;
5262
	ld_ins(i_lo,0,b,r);
5263
	/* %sp -> %sp + n */
5264
	rrr_ins(i_add,c_,SP,t,SP);
5265
     }
5266
     if ( checkalloc(e) )
5267
     {
5268
	exp stl = find_named_tg("__TDFstacklim",
5269
	 	            f_pointer(f_alignment(f_proc)));
5270
	setvar( stl );
5271
	b = boff( stl );
5272
	ld_ins(i_lw,1,b,GR1);
5273
	if ( stackerr_lab==0 )
5274
	{
5275
	   stackerr_lab = new_label();
5276
	}
5277
	cj_ins(c_g,SP,GR1,stackerr_lab);
5278
     }
5279
     if (Has_tos)
5280
	reset_tos();
5281
     setregalt(aa, r);
5282
     mka.regmove = move(aa, dest, guardreg(r, sp).fixed, 0);
5283
     mka.lab = exitlab;
5284
     if (Has_ll)
5285
     {
5286
	baseoff b;
5287
	b.base = SP;
5288
	b.offset = -maxargbytes -4;
5289
	st_ins(i_sw,r,b);
5290
     }
5291
     return (mka);
5292
  }
5293
 
5294
  case movecont_tag:
5295
  {
5296
     exp szarg = bro(bro(son(e)));
5297
     int dr, sr, sz, szr, mr,alt=0,lab;	
5298
     int finish = new_label();
5299
     space nsp;
5300
     where w;
5301
     nsp = sp;
5302
     w.ashwhere = ashof(sh(bro(bro(son(e)))));
5303
     if (0 && name(szarg)==val_tag)
5304
     {
5305
	sz = evalexp(szarg);
5306
	if (sz==0)
5307
	   return mka;
5308
	else
5309
	if (!(isnooverlap(e) || SIMM14(sz)))
5310
	{
5311
	   imm_to_r(sz,szr);
5312
	}
5313
     }
5314
     else
5315
     {
5316
	szr = getreg(sp.fixed);
5317
	setregalt(w.answhere, szr);
5318
	make_code(szarg, sp, w, 0);
5319
	nsp = guardreg(szr, sp);
5320
	if (name(szarg)==val_tag)
5321
	{
5322
	   if (no(szarg)==0) 
5323
	      return mka; 
5324
	}
5325
	else
5326
	   cj_ins(c_eq,0,szr,finish);
5327
     }
5328
     sr = getreg(nsp.fixed);
5329
     setregalt(w.answhere, sr);
5330
     w.ashwhere = ashof(sh(son(e)));
5331
     make_code(son(e), sp, w , 0);
5332
     nsp = guardreg(sr, sp);
5333
     dr = getreg(nsp.fixed);
5334
     setregalt(w.answhere, dr);
5335
     make_code(bro(son(e)), nsp, w, 0);
5336
     nsp = guardreg(dr, nsp);
5337
     cj_ins(c_eq,sr,dr,finish);
5338
     mr = getreg(nsp.fixed);
5339
     if (!isnooverlap(e))
5340
     {
5341
	alt = new_label();
5342
	cj_ins(c_l,sr,dr,alt);
5343
     }   
5344
     /*  No overlap or dr<sr  */
5345
     lab = new_label();
5346
     if (0 && name(szarg)==val_tag)
5347
     {
5348
	if (SIMM14(sz))
5349
	   ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,sz,sr,mr);
5350
	else
5351
	{
5352
	   /* Moving more than 2^14 bytes. */
5353
	   if (isnooverlap(e))
5354
	   {
5355
	      ir_ins(i_addil,fs_L,empty_ltrl,sz,sr);
5356
	      ld_ir_ins(i_ldo,cmplt_,fs_R,empty_ltrl,sz,sr,mr);
5357
	   }
5358
	   else
5359
	      rrr_ins(i_add,c_,szr,sr,mr);               
5360
	}
5361
     }
5362
     else
5363
     {
5364
	rrr_ins(i_add,c_,szr,sr,mr);
5365
     }
5366
     outlab("L$$",lab);
5367
     ld_ir_ins(i_ldbs,cmplt_MA,fs_,empty_ltrl,1,sr,GR1);
5368
     comb_ins(c_l,sr,mr,lab);
5369
     st_ir_ins(i_stbs,cmplt_MA,GR1,fs_,empty_ltrl,1,dr);
5370
     if (!isnooverlap(e))
5371
     {
5372
	/* Overlap or dr>sr */
5373
	ub_ins(cmplt_N,finish);
5374
	outlab("L$$",alt);
5375
	lab = new_label();
5376
	rr_ins(i_copy,sr,mr);
5377
	if (0 && name(szarg)==val_tag && SIMM14(sz))
5378
	{
5379
	      ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,sz,sr,sr);
5380
	      ld_ir_ins(i_ldo,cmplt_,fs_,empty_ltrl,sz,dr,dr);
5381
	}
5382
	else
5383
	{
5384
	   rrr_ins(i_add,c_,sr,szr,sr);
5385
	   rrr_ins(i_add,c_,dr,szr,dr);
5386
	}
5387
	outlab("L$$",lab);
5388
	ld_ir_ins(i_ldbs,cmplt_MB,fs_,empty_ltrl,-1,sr,GR1);
5389
	comb_ins(c_g,sr,mr,lab);
5390
	st_ir_ins(i_stbs,cmplt_MB,GR1,fs_,empty_ltrl,-1,dr);
5391
     }
5392
     outlab("L$$",finish);
5393
     clear_dep_reg(bro(son(e)));
5394
     return mka;
5395
  }
5396
 
5397
  default:
5398
  {
5399
      char C[64];
5400
      sprintf(C,"TDF construct %d not done yet in make_code",name(e));
5401
      fail(C);
5402
    }
5403
  }
5404
 
5405
  assert(0);			/* should have return/goto from switch */
5406
 
5407
  moveconst:
5408
  {
5409
     int r;
5410
     if ( discrim(dest.answhere)==inreg )
5411
     {
5412
	r = regalt(dest.answhere);
5413
	imm_to_r(constval,r);
5414
     }
5415
     else
5416
     {
5417
  	ans aa;
5418
	if (constval == 0)
5419
 	    r = GR0;		/* HPPA zero reg */
5420
	else
5421
	{
5422
	   r = getreg(sp.fixed);
5423
	   imm_to_r(constval,r);
5424
	}
5425
	setregalt(aa, r);
5426
	move(aa, dest, guardreg(r, sp).fixed, 1);
5427
     }
5428
     mka.regmove = r;
5429
     return mka;
5430
   }
5431
}				/* end make_code */
5432
 
5433
 
5434
/* commented out return_to_label_tag and make_stack_limit_tag for puposes
5435
of debugging until proper 4.0 libraries are built. */
5436
 
5437
 
5438
 
5439
 
5440