Subversion Repositories tendra.SVN

Rev

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

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