Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/*
32
			    VERSION INFORMATION
33
			    ===================
34
 
35
--------------------------------------------------------------------------
36
$Header: /u/g/release/CVSROOT/Source/src/installers/sparc/common/makecode.c,v 1.3 1998/03/11 11:03:55 pwe Exp $
37
--------------------------------------------------------------------------
38
$Log: makecode.c,v $
39
 * Revision 1.3  1998/03/11  11:03:55  pwe
40
 * DWARF optimisation info
41
 *
42
 * Revision 1.2  1998/02/18  11:22:26  pwe
43
 * test corrections
44
 *
45
 * Revision 1.1.1.1  1998/01/17  15:55:54  release
46
 * First version to be checked into rolling release.
47
 *
48
 * Revision 1.70  1998/01/09  14:59:33  pwe
49
 * prep restructure
50
 *
51
 * Revision 1.69  1997/12/04  19:54:11  pwe
52
 * ANDF-DE V1.9
53
 *
54
 * Revision 1.68  1997/11/06  09:28:57  pwe
55
 * ANDF-DE V1.8
56
 *
57
 * Revision 1.67  1997/10/28  10:18:53  pwe
58
 * extra diags
59
 *
60
 * Revision 1.66  1997/10/23  09:32:56  pwe
61
 * prep extra_diags
62
 *
63
 * Revision 1.65  1997/10/10  18:32:34  pwe
64
 * prep ANDF-DE revision
65
 *
66
 * Revision 1.64  1997/08/23  13:54:00  pwe
67
 * initial ANDF-DE
68
 *
69
 * Revision 1.63  1997/04/17  11:59:47  pwe
70
 * dwarf2 support
71
 *
72
 * Revision 1.62  1997/03/26  13:04:25  pwe
73
 * general proc compatibility
74
 *
75
 * Revision 1.61  1997/03/24  17:09:25  pwe
76
 * reorganise solaris/sunos split
77
 *
78
 * Revision 1.60  1997/02/18  11:47:59  pwe
79
 * NEWDIAGS for debugging optimised code
80
 *
81
 * Revision 1.59  1996/11/14  17:19:38  pwe
82
 * correct previous correction to case unsigned
83
 *
84
 * Revision 1.58  1996/11/14  12:06:57  pwe
85
 * correct case unsigned
86
 *
87
 * Revision 1.57  1996/11/08  15:05:24  pwe
88
 * correct make_code(offset-pad) re double evaluation
89
 *
90
 * Revision 1.56  1996/10/03  08:51:01  pwe
91
 * PIC global/large offset, and PIC case guardregs
92
 *
93
 * Revision 1.55  1996/09/18  12:03:44  pwe
94
 * fixed PIC_code
95
 *
96
 * Revision 1.54  1996/09/02  15:52:48  pwe
97
 * reinstate previous test, and permit indirection in make_code 64-bit values
98
 *
99
 * Revision 1.53  1996/09/02  11:57:35  pwe
100
 * removed incomprehensible test re indirect assignment
101
 *
102
 * Revision 1.52  1996/08/28  14:24:01  pwe
103
 * trap exceptions in round and quad change_float_var
104
 *
105
 * Revision 1.51  1996/08/22  16:46:55  pwe
106
 * correct accessing for double params
107
 *
108
 * Revision 1.50  1996/04/17  08:25:48  john
109
 * Changed div2 trap treatment
110
 *
111
 * Revision 1.49  1996/03/20  16:12:47  john
112
 * Reformatting
113
 *
114
 * Revision 1.48  1996/02/27  11:19:37  john
115
 * Fix to return_to_label
116
 *
117
 * Revision 1.47  1996/02/22  11:46:36  john
118
 * Fix to return_to_label
119
 *
120
 * Revision 1.46  1996/02/12  17:32:22  john
121
 * Fix to double constants
122
 *
123
 * Revision 1.45  1996/01/12  16:54:12  john
124
 * Fix to fdiv_tag
125
 *
126
 * Revision 1.44  1995/12/15  10:25:21  john
127
 * Changed current_env
128
 *
129
 * Revision 1.43  1995/11/30  09:15:49  john
130
 * Fix to pointer comparison
131
 *
132
 * Revision 1.42  1995/11/24  16:22:14  john
133
 * Fixed error treatment for fchvar
134
 *
135
 * Revision 1.41  1995/11/24  14:50:33  john
136
 * Changes for limits tests
137
 *
138
 * Revision 1.40  1995/11/16  14:14:28  john
139
 * Minor change
140
 *
141
 * Revision 1.39  1995/11/13  11:49:13  john
142
 * Added prof_tag case
143
 *
144
 * Revision 1.38  1995/11/07  09:41:24  john
145
 * Changed parameter passing for general procs
146
 *
147
 * Revision 1.37  1995/11/02  18:04:19  john
148
 * Stopped using local reg to access data
149
 *
150
 * Revision 1.36  1995/10/27  15:32:26  john
151
 * change to error treatment
152
 *
153
 * Revision 1.35  1995/10/27  10:48:26  john
154
 * Fix to general procs
155
 *
156
 * Revision 1.34  1995/10/24  17:05:32  john
157
 * Fixes for AVS
158
 *
159
 * Revision 1.33  1995/10/18  09:18:57  john
160
 * Fix to round_tag
161
 *
162
 * Revision 1.32  1995/10/18  09:10:14  john
163
 * Fix to round_tag
164
 *
165
 * Revision 1.31  1995/10/17  08:09:39  john
166
 * Fix to trap handling in round_with_mode
167
 *
168
 * Revision 1.30  1995/10/13  15:23:07  john
169
 * change to env_offset
170
 *
171
 * Revision 1.29  1995/10/13  13:34:30  john
172
 * Fix for error check on floating plus
173
 *
174
 * Revision 1.28  1995/10/04  09:00:48  john
175
 * Added 64 bit constants
176
 *
177
 * Revision 1.27  1995/09/25  16:34:21  john
178
 * Fixed rounding modes
179
 *
180
 * Revision 1.26  1995/09/20  12:30:17  john
181
 * Change to floating point error handling
182
 *
183
 * Revision 1.25  1995/09/19  14:29:58  john
184
 * Changes to error treatments & fix to chvar_tag
185
 *
186
 * Revision 1.24  1995/09/15  16:15:23  john
187
 * New exception handling
188
 *
189
 * Revision 1.23  1995/09/13  08:18:48  john
190
 * Addition for exception handling
191
 *
192
 * Revision 1.22  1995/08/31  15:56:10  john
193
 * Fixed some bugs in error_jumps & added fmax_tag
194
 *
195
 * Revision 1.21  1995/08/24  16:39:45  john
196
 * Fix to find_ote, + various error_jump fixes
197
 *
198
 * Revision 1.20  1995/08/23  09:24:08  john
199
 * Added definition of trap_tag
200
 *
201
 * Revision 1.19  1995/08/21  13:35:52  john
202
 * Changed handling of caller_tag
203
 *
204
 * Revision 1.18  1995/08/04  15:45:44  john
205
 * Minor changes
206
 *
207
 * Revision 1.17  1995/07/27  16:32:21  john
208
 * Change to floating point error detection
209
 *
210
 * Revision 1.16  1995/07/18  15:30:00  john
211
 * Fix to return_to_label
212
 *
213
 * Revision 1.15  1995/07/18  09:39:07  john
214
 * Implemented return_to_label
215
 *
216
 * Revision 1.14  1995/07/18  08:24:08  john
217
 * Reformatting
218
 *
219
 * Revision 1.13  1995/07/17  16:43:11  john
220
 * Fix
221
 *
222
 * Revision 1.12  1995/07/17  16:39:10  john
223
 * return_to_label added
224
 *
225
 * Revision 1.11  1995/07/14  16:31:41  john
226
 * various changes for spec 4.0
227
 *
228
 * Revision 1.10  1995/07/03  15:18:10  john
229
 * Reformatting
230
 *
231
 * Revision 1.9  1995/06/27  08:47:25  john
232
 * Minor change
233
 *
234
 * Revision 1.8  1995/06/21  14:29:04  john
235
 * Reformatting & change to spec 4
236
 *
237
 * Revision 1.7  1995/06/14  15:34:32  john
238
 * Added code for stack limit & trap exceptions
239
 *
240
 * Revision 1.6  1995/05/26  12:59:24  john
241
 * Changes for new spec (3.1)
242
 *
243
 * Revision 1.5  1995/04/20  08:05:53  john
244
 * Fixed sign extension of char & short data
245
 *
246
 * Revision 1.4  1995/03/27  12:50:52  john
247
 * Fix for c-style varargs handling
248
 *
249
 * Revision 1.3  1995/03/23  16:55:48  john
250
 * Turned off assembler optimisation for long_jump
251
 *
252
 * Revision 1.2  1995/03/14  17:55:27  john
253
 * Turned off assembler optimisation for current_env
254
 *
255
 * Revision 1.1.1.2  1995/03/14  12:00:38  john
256
 * Entered into CVS
257
 *
258
 * Revision 1.20  1995/03/08  13:19:07  john
259
 * Corrected rounding modes for round_tag
260
 *
261
 * Revision 1.19  1995/03/08  11:53:54  john
262
 * Many changes for AVS test suite
263
 *
264
 * Revision 1.18  1995/02/08  14:34:04  john
265
 * First attempt at implementing error jumps, plus fix to test_tag
266
 *
267
 * Revision 1.17  1995/01/12  17:37:06  john
268
 * Fixed bug in movecont_tag
269
 *
270
 * Revision 1.16  1995/01/12  13:50:37  john
271
 * Removed unecessary jump to label
272
 *
273
 * Revision 1.15  1995/01/06  13:52:59  john
274
 * Removed attempt at struct = struct assignment, which is not supported
275
 * by SunOS cc.
276
 *
277
 * Revision 1.14  1994/12/21  12:10:26  djch
278
 * Added max_tag and min_tag and offset_max_tag
279
 *
280
 * Revision 1.13  1994/12/05  11:25:26  djch
281
 * Exported notbranch table to needscan
282
 *
283
 * Revision 1.12  1994/12/01  13:22:29  djch
284
 * Added make_lv_tag
285
 * Added movecont for move_some as call to bcopy (memmove on Solaris).
286
 * Fixed minor bugs in current_env and env_offset (which takes an ident, not a
287
 * name. )
288
 * Added long_jump_tag
289
 *
290
 * Revision 1.11  1994/11/28  13:55:34  djch
291
 * removed use_subvar
292
 *
293
 * Revision 1.10  1994/11/28  13:50:06  djch
294
 * Added first attempts at current_env, abs and env_offset. ci to delete
295
 * use_subvar
296
 *
297
 * Revision 1.9  1994/11/18  13:50:20  djch
298
 * Altered test_tag to use (set)test_number
299
 *
300
 * Revision 1.8  1994/07/07  11:05:02  djch
301
 * Compounds which are redundant are coded into g0. They may exceed 32 bits.
302
 * Shifts of >= 32 bits crash the solaris asm. Now check for overflow, and don't
303
 * create compounds in g0.
304
 *
305
 * Revision 1.7  1994/07/04  08:26:39  djch
306
 * added code to change chvar to/from 8/16/32 bitfields into corresponding
307
 * int types.
308
 *
309
 * Revision 1.6  1994/06/17  14:51:05  djch
310
 * fixed unsigned <=0 to be !=0, to work round sparc asm problem with add -1
311
 * setting overflow
312
 *
313
 * added a guardreg since calls to .udiv etc corrupt %o0, and this can actually
314
 * hit (1/24) since move may choose the same place
315
 *
316
 * added div0 and rem0
317
 *
318
 * disabled some bitfield stuff which should never be used.
319
 *
320
 * Revision 1.5  1994/05/25  14:14:31  djch
321
 * Added CREATE_instore_bits and {} to shut up tcc.
322
 *
323
 * Revision 1.4  1994/05/19  08:18:43  djch
324
 * removed an assert for !struct_par, no longer true
325
 *
326
 * Revision 1.3  1994/05/13  12:37:07  djch
327
 * Incorporates improvements from expt version
328
 * jmf now puts constants on rhs
329
 * addded defaults to switchs
330
 * use new macros from addrtypes.h
331
 * de-long-ed some format strings
332
 *
333
 * Revision 1.2  1994/05/03  15:07:53  djch
334
 * ifdefed out rscope_tag
335
 *
336
 * Revision 1.11  94/02/21  16:11:50  16:11:50  ra (Robert Andrews)
337
 * Correct a number of places where the sign of a shape was being
338
 * found by anding its name with 1.
339
 * 
340
 * Revision 1.10  93/09/27  14:48:10  14:48:10  ra (Robert Andrews)
341
 * The label prefix is now given by lab_prefix rather than being
342
 * hardwired in.  A number of changes to allow for long doubles.
343
 * 
344
 * Revision 1.9  93/08/27  11:31:29  11:31:29  ra (Robert Andrews)
345
 * A number of lint-like changes.
346
 * 
347
 * Revision 1.8  93/08/18  11:12:54  11:12:54  ra (Robert Andrews)
348
 * Reformatted remaining cases in make_code.
349
 * 
350
 * Revision 1.7  93/08/13  14:38:48  14:38:48  ra (Robert Andrews)
351
 * Did rounding modes and unsigned <-> float conversions properly.  Removed
352
 * a couple of comments.
353
 * 
354
 * Revision 1.6  93/07/15  12:30:36  12:30:36  ra (Robert Andrews)
355
 * Reformatted and restructured slightly.  Added extra test instructions
356
 * for ntests not arising from C.
357
 * 
358
 * Revision 1.5  93/07/14  11:19:55  11:19:55  ra (Robert Andrews)
359
 * Use %g0 rather than 0 in comparison operations.  Spot use of unimplemented
360
 * rounding modes in round_tag case.
361
 * 
362
 * Revision 1.4  93/07/12  15:14:53  15:14:53  ra (Robert Andrews)
363
 * The floating->unsigned conversion was previously wrong.
364
 * 
365
 * Revision 1.3  93/07/05  18:21:13  18:21:13  ra (Robert Andrews)
366
 * Made distinction between the System V assembler and the System V ABI.
367
 * Added support for PIC (switch statements).
368
 * 
369
 * Revision 1.2  93/06/29  14:28:01  14:28:01  ra (Robert Andrews)
370
 * Changed failer to fail.  A couple of minor renaming of diagnostic
371
 * routines.  Now use ins_p to represent instructions.
372
 * 
373
 * Revision 1.1  93/06/24  14:58:41  14:58:41  ra (Robert Andrews)
374
 * Initial revision
375
 * 
376
--------------------------------------------------------------------------
377
*/
378
 
379
 
380
#define SPARCTRANS_CODE
381
#include "config.h"
382
#include "common_types.h"
383
#include "myassert.h"
384
#include "addrtypes.h"
385
#include "tags.h"
386
#include "extra_tags.h"
387
#include "expmacs.h"
388
#include "installtypes.h"
389
#include "exp.h"
390
#include "exptypes.h"
391
#include "maxminmacs.h"
392
#include "shapemacs.h"
393
#include "basicread.h"
394
#include "proctypes.h"
395
#include "eval.h"
396
#include "move.h"
397
#include "oprators.h"
398
#include "comment.h"
399
#include "getregs.h"
400
#include "guard.h"
401
#include "locate.h"
402
#include "codehere.h"
403
#include "inst_fmt.h"
404
#include "sparcins.h"
405
#include "bitsmacs.h"
406
#include "labels.h"
407
#include "regexps.h"
408
#include "regmacs.h"
409
#include "regable.h"
410
#include "muldvrem.h"
411
#include "proc.h"
412
#include "flags.h"
413
#include "special.h"
414
#include "sparcdiags.h"
415
#include "translat.h"
416
#include "out.h"
417
#include "makecode.h"
418
#include "install_fns.h"
419
#include "externs.h"
420
#include "flpt.h"
421
#include "szs_als.h"
422
#include "new_tags.h"
423
#include "f64.h"
424
 
425
#ifdef NEWDIAGS
426
#include "dg_aux.h"
427
#include "dg_globs.h"
428
#endif
429
 
430
#ifdef NEWDWARF
431
#include "dw2_config.h"
432
#include "dw2_info.h"
433
#include "dw2_basic.h"
434
#endif
435
 
436
 
437
/* 
438
  Check for parameter access via add_to_ptr ( env, off ) 
439
*/
440
#define param_aligned(off) (al1_of(sh(off))->al.al_val.al_frame & 6)
441
 
442
 
443
/*
444
  THE NIL WHERE
445
*/
446
where nowhere ;
447
 
448
 
449
/*
450
  CHECK FOR NOT-A-NUMBER
451
*/
452
void checknan 
453
    PROTO_N ( ( e, fr ) )
454
    PROTO_T ( exp e X int fr )
455
{
456
#if 0
457
  long trap = no ( son ( pt ( e ) ) ) ;
458
  int t = ( ABS_OF ( fr ) - 32 ) << 1 ;
459
#endif
460
  fail ( "checknan not implemented" ) ;
461
  return ;
462
}
463
 
464
 
465
/*
466
  START OF VOLATILE USE
467
  Not available until SunOS 5.0.
468
*/
469
 
470
void setvolatile 
471
    PROTO_Z ()
472
{
473
  outs ( "!\t.volatile\n" ) ;
474
  return ;
475
}
476
 
477
 
478
/*
479
  END OF VOLATILE USE
480
  Not available until SunOS 5.0.
481
*/
482
 
483
void setnovolatile 
484
    PROTO_Z ()
485
{
486
  outs ( "!\t.nonvolatile\n" ) ;
487
  return ;
488
}
489
 
490
 
491
 
492
 
493
/*
494
  Jump to the exception handler
495
*/
496
void do_exception 
497
    PROTO_N ( ( ex ) )
498
    PROTO_T ( int ex )
499
{
500
  baseoff b;
501
  ir_ins(i_mov,ex,R_O0);
502
  b = find_tag(TDF_HANDLER);
503
  ld_ins(i_ld,b,R_TMP);
504
  extj_reg_ins(i_call,R_TMP,1);
505
  /*extj_ins(i_call,b,1);*/
506
}
507
 
508
 
509
/*
510
  Check whether or not an exception condition has occured and,
511
  if so, jump to the label given in no(son(pt(e))).  
512
*/
513
static void check_integer_exception 
514
    PROTO_N ( ( e ) )
515
    PROTO_T ( exp e )
516
{
517
 
518
  if(!error_treatment_is_trap(e)){
519
    int trap = no(son(pt(e)));
520
    uncond_ins(i_bvs,trap);
521
  }
522
  else{
523
#if 1
524
    int lab = new_label();
525
    uncond_ins(i_bvc,lab);
526
    do_exception(f_overflow);
527
    set_label(lab);
528
#endif
529
  }
530
  return;
531
}
532
 
533
 
534
/*
535
  Settings of exception bits in FSR.
536
*/
537
 
538
#define FSR_INVALID_FOP 0x200
539
#define FSR_OVERFLOW 0x100
540
#define FSR_UNDERFLOW 0x080
541
#define FSR_DIV_BY_0 0x040
542
#define FSR_INEXACT 0x020
543
#define FSR_ANY FSR_INVALID_FOP | FSR_OVERFLOW | FSR_DIV_BY_0 | FSR_UNDERFLOW 
544
 
545
/*
546
  Examine the accumulated exception bits (5:9) of the floating point status
547
  register to see if an exception has been raised.  If so, output a jump
548
  to the error label for the exp, otherwise return.
549
*/
550
static void check_floating_exception 
551
    PROTO_N ( ( e, sp, except ) )
552
    PROTO_T ( exp e X space sp X int except )
553
{
554
  freg fr;
555
  ans aa;
556
  where assdest;
557
  int rt = getreg(sp.fixed);
558
  int rt2;
559
  space nsp;
560
  nsp = guardreg(rt,sp);
561
  rt2 = getreg(nsp.fixed);
562
  fr.fr = FSR>>1;
563
  fr.dble = 0;
564
  discrim(assdest.answhere) = inreg;
565
  assdest.answhere.val.regans = rt;
566
  assdest.ashwhere.ashsize = assdest.ashwhere.ashalign = 32;
567
  setfregalt(aa,fr);
568
  move(aa,assdest,guardreg(rt2,nsp).fixed,1);
569
  rir_ins(i_and,rt,except,rt2);
570
  rir_ins(i_and,rt,~except,rt);
571
  discrim(assdest.answhere) = infreg;
572
  assdest.answhere.val.fregans = fr;
573
  assdest.ashwhere.ashalign = assdest.ashwhere.ashsize = 32;
574
  setregalt(aa,rt);
575
  move(aa,assdest,guardreg(rt2,nsp).fixed,1);
576
  if(!error_treatment_is_trap(e)){
577
    condrr_ins(i_bne,rt2,R_G0,no(son(pt(e))));
578
  }
579
  else{
580
    int new_lab = new_label();
581
    condrr_ins(i_be,rt2,R_G0,new_lab);
582
    do_exception(f_overflow);
583
    set_label(new_lab);
584
  }
585
 
586
  /*
587
  rir_ins(i_sll,rt,17,rt);
588
  condrr_ins(i_blt,rt,0,trap);*/
589
  return;
590
}
591
 
592
 
593
/*
594
  Setup the FSR to turn off traps in the event of an 
595
  IEEE_754 exception.  Hopefully this still sets the 
596
  exception bit in the FSR.
597
*/
598
static void turn_off_trap_on_exceptions 
599
    PROTO_N ( ( sp ) )
600
    PROTO_T ( space sp )
601
{
602
  freg fr;
603
  ans aa;
604
  where assdest;
605
  int rt = getreg(sp.fixed);
606
  fr.fr = FSR>>1;
607
  fr.dble = 0;
608
  discrim(assdest.answhere) = inreg;
609
  assdest.answhere.val.regans = rt;
610
  assdest.ashwhere.ashsize = assdest.ashwhere.ashalign = 32;
611
  setfregalt(aa,fr);
612
  move(aa,assdest,guardreg(rt,sp).fixed,1);
613
  rir_ins(i_and,rt,0xf07fffffL,rt);	/* clear trap mask */
614
  assdest.answhere = aa;
615
  setregalt(aa,rt);
616
  move(aa,assdest,guardreg(rt,sp).fixed,1);
617
  return;
618
}
619
 
620
 
621
 
622
/*
623
  Integer multiply instructions do not set the overflow flag
624
  in the condition codes register.  Overflow is detected by 
625
  looking at the top 32 bits of the result, which are held in
626
  the Y register.
627
*/
628
static void check_integer_multiply_exception 
629
    PROTO_N ( ( e, sp, result ) )
630
    PROTO_T ( exp e X space sp X int result )
631
{
632
  space nsp;
633
  int yreg;
634
  nsp = guardreg(result,sp);
635
  yreg = getreg(nsp.fixed);
636
  if(optim_level != 0){
637
    optim_level = 0;
638
    fprintf(as_file,"\t.optim\t\"-O0\"\n");
639
  }
640
  rr_ins(i_rd,YREG,yreg);
641
  if(is_signed(sh(son(e)))){
642
    int result_shift = getreg(guardreg(yreg,nsp).fixed);
643
    rir_ins(i_sra,result,31,result_shift);
644
    if(!error_treatment_is_trap(e)){
645
      condrr_ins(i_bne,result_shift,yreg,no(son(pt(e))));
646
    }
647
    else{
648
      int new_lab = new_label();
649
      condrr_ins(i_be,result_shift,yreg,new_lab);
650
      do_exception(f_overflow);
651
      set_label(new_lab);
652
    }
653
  }
654
  else{
655
    if(!error_treatment_is_trap(e)){
656
      condrr_ins(i_bne,yreg,R_G0,no(son(pt(e))));
657
    }
658
    else{
659
      int new_lab = new_label();
660
      condrr_ins(i_be,yreg,R_G0,new_lab);
661
      do_exception(f_overflow);
662
      set_label(new_lab);
663
    }
664
  }
665
  return;
666
}
667
 
668
/*
669
  If the value in register reg does not lie between the limits, then
670
  go to label trap.
671
*/
672
void test_unsigned 
673
    PROTO_N ( ( reg, upper, trap ) )
674
    PROTO_T ( int reg X int upper X int trap )
675
{
676
  condri_ins(i_bgu,reg,upper,trap);
677
  return;
678
}
679
 
680
void test_signed 
681
    PROTO_N ( ( reg, lower, upper, trap ) )
682
    PROTO_T ( int reg X int lower X int upper X int trap )
683
{
684
  condri_ins(i_blt,reg,lower,trap);
685
  condri_ins(i_bgt,reg,upper,trap);
686
  return;
687
}
688
 
689
void test_signed_and_trap 
690
    PROTO_N ( ( reg, lower, upper, except ) )
691
    PROTO_T ( int reg X int lower X int upper X int except )
692
{
693
  int ok_lab = new_label();
694
  int jump_label = new_label();
695
 
696
  condri_ins(i_blt,reg,lower,jump_label);
697
  condri_ins(i_bgt,reg,upper,jump_label);
698
  uncond_ins(i_b,ok_lab);
699
  set_label(jump_label);
700
  do_exception(except);
701
  set_label(ok_lab);
702
  return;
703
}
704
 
705
void test_unsigned_and_trap 
706
    PROTO_N ( ( reg, upper, except ) )
707
    PROTO_T ( int reg X long upper X int except )
708
{
709
  int ok_lab = new_label();
710
  condri_ins(i_bleu,reg,upper,ok_lab);
711
  do_exception(except);
712
  set_label(ok_lab);
713
  return;
714
}
715
 
716
int regfrmdest 
717
    PROTO_N ( ( dest, sp ) )
718
    PROTO_T ( where * dest X space sp )
719
{
720
  if(dest->answhere.d == inreg){
721
    return regalt(dest->answhere);
722
  }
723
  else{
724
    return getreg(sp.fixed);
725
  }
726
}
727
 
728
 
729
void load_reg 
730
    PROTO_N ( ( e, reg, sp ) )
731
    PROTO_T ( exp e X int reg X space sp )
732
{
733
  where w;
734
  w.ashwhere = ashof(sh(e));
735
  setregalt(w.answhere,reg);
736
  code_here(e,sp,w);
737
  return;
738
}
739
 
740
 
741
/*
742
  TABLE OF UNSIGNED JUMPS
743
 
744
  The key to the test numbers is as follows :
745
 
746
  1 = "<="		8 = "!>="
747
  2 = "<"			9 = "!<"
748
  3 = ">="		A = "!<="
749
  4 = ">"			B = "<>"
750
  5 = "!="		C = "!<>"
751
  6 = "=="		D = "comp"
752
  7 = "!>"		E = "!comp"
753
*/
754
 
755
static CONST ins_p usbranch_tab [] = {
756
    /* 0 */ I_NIL,
757
    /* 1 */ i_bleu,
758
    /* 2 */ i_blu,
759
    /* 3 */ i_bgeu,
760
    /* 4 */ i_bgu,
761
    /* 5 */ i_bne,
762
    /* 6 */ i_be,
763
    /* 7 */ i_bleu,
764
    /* 8 */ i_blu,
765
    /* 9 */ i_bgeu,
766
    /* A */ i_bgu,
767
    /* B */ i_bne,
768
    /* C */ i_be,
769
    /* D */ i_ba,
770
    /* E */ i_bn
771
} ;
772
 
773
#define usbranches( i )	( usbranch_tab [i] )
774
 
775
 
776
/*	
777
    TABLE OF SIGNED JUMPS
778
*/
779
 
780
static CONST ins_p sbranch_tab [] = {
781
    /* 0 */ I_NIL,
782
    /* 1 */ i_ble,
783
    /* 2 */ i_bl,
784
    /* 3 */ i_bge,
785
    /* 4 */ i_bg,
786
    /* 5 */ i_bne,
787
    /* 6 */ i_be,
788
    /* 7 */ i_ble,
789
    /* 8 */ i_bl,
790
    /* 9 */ i_bge,
791
    /* A */ i_bg,
792
    /* B */ i_bne,
793
    /* C */ i_be,
794
    /* D */ i_ba,
795
    /* E */ i_bn
796
} ;
797
 
798
#define sbranches( i )	( sbranch_tab [i] )
799
 
800
 
801
/*
802
  TABLE OF FLOATING JUMPS
803
*/
804
 
805
static CONST ins_p fbranch_tab [] = {
806
    /* 0 */ I_NIL,
807
    /* 1 */ i_fble,
808
    /* 2 */ i_fbl,
809
    /* 3 */ i_fbge,
810
    /* 4 */ i_fbg,
811
    /* 5 */ i_fbne,
812
    /* 6 */ i_fbe,
813
    /* 7 */ i_fbule,
814
    /* 8 */ i_fbul,
815
    /* 9 */ i_fbuge,
816
    /* A */ i_fbug,
817
    /* B */ i_fblg,
818
    /* C */ i_fbue,
819
    /* D */ i_fbo,
820
    /* E */ i_fbu
821
} ;
822
 
823
#define fbranches( i )	( fbranch_tab [i] )
824
 
825
 
826
/*
827
  TABLE OF INVERTED JUMPS
828
 
829
  Are these right?
830
*/
831
 
832
prop notbranch [] = {
833
    /* 0 */ 0x0,
834
    /* 1 */ 0x4,
835
    /* 2 */ 0x3,
836
    /* 3 */ 0x2,
837
    /* 4 */ 0x1,
838
    /* 5 */ 0x6,
839
    /* 6 */ 0x5,
840
    /* 7 */ 0xa,
841
    /* 8 */ 0x9,
842
    /* 9 */ 0x8,
843
    /* A */ 0x7,
844
    /* B */ 0xc,
845
    /* C */ 0xb,
846
    /* D */ 0xe,
847
    /* E */ 0xd
848
} ;
849
 
850
#define obranch( i )	( notbranch [i] )
851
 
852
 
853
#define is_char_variety(v) ((name(v) == scharhd) || (name(v) == ucharhd))
854
#define is_short_variety(v) ((name(v) == swordhd) || (name(v) == uwordhd))
855
 
856
/*
857
  MOVE A FLOATING POINT CONSTANT INTO A REGISTER
858
*/
859
static void fconst 
860
    PROTO_N ( ( f, hi, lo ) )
861
    PROTO_T ( int f X long hi X long lo )
862
{
863
  baseoff b ;
864
  int dlab = next_data_lab () ;
865
  insection ( rodata_section ) ;
866
  outs ( "\t.align\t8\n" ) ;
867
  outlab ( dlab ) ;
868
  outs ( ":\n\t.word\t" ) ;
869
#if little_end
870
  outn ( lo ) ;
871
  outc ( ',' ) ;
872
  outn ( hi ) ;
873
#else
874
  outn ( hi ) ;
875
  outc ( ',' ) ;
876
  outn ( lo ) ;
877
#endif
878
  outs ( "\n\t.align\t8\n" ) ;
879
  insection ( text_section ) ;
880
  b.base = dlab ;
881
  b.offset = 0 ;
882
  ldf_ins ( i_ldd, b, f << 1 ) ;
883
  return ;
884
}
885
 
886
#if 0
887
/*
888
  MOVE A FLOATING POINT CONSTANT INTO A REGISTER
889
*/
890
static void ldconst 
891
    PROTO_N ( ( r, hi, word2, word3, lo ) )
892
    PROTO_T ( int r X long hi X long word2 X long word3 X long lo )
893
{
894
  baseoff b ;
895
  int dlab = next_data_lab () ;
896
  insection ( rodata_section ) ;
897
  outs ( "\t.align\t8\n" ) ;
898
  outlab ( dlab ) ;
899
  outs ( ":\n\t.word\t" ) ;
900
#if little_end
901
  outn ( lo ) ;
902
  outc ( ',' ) ;
903
  outn(word3);
904
  outc(',');
905
  outn(word2);
906
  outc(',');
907
  outn ( hi ) ;
908
#else
909
  outn ( hi ) ;
910
  outc ( ',' ) ;
911
  outn (word2);
912
  outc(',');
913
  outn(word3);
914
  outc(',');
915
  outn ( lo ) ;
916
#endif
917
  outs ( "\n\t.align\t8\n" ) ;
918
  insection ( text_section ) ;
919
  b.base = dlab ;
920
  b.offset = 0 ;
921
  ld_ins(i_set,b,r);
922
#ifdef NEWDWARF
923
  lost_count_ins();
924
#endif
925
  /*ldf_ins ( i_ldd, b, f << 1 ) ;*/
926
  return ;
927
}
928
#endif
929
 
930
/*
931
  FIND THE LAST TEST IN e WHICH IS A BRANCH TO second
932
*/
933
static exp testlast 
934
    PROTO_N ( ( e, second ) )
935
    PROTO_T ( exp e X exp second )
936
{
937
  if ( name ( e ) == test_tag && pt ( e ) == second ) return ( e ) ;
938
  if ( name ( e ) == seq_tag ) {
939
    exp b = bro ( son ( e ) ) ;
940
    if ( name ( b ) == test_tag && pt ( b ) == second ) {
941
      return ( b ) ;
942
    } else if ( name ( b ) == top_tag ) {
943
      exp list = son ( son ( e ) ) ;
944
      for ( ; ; ) {
945
	if ( last ( list ) ) {
946
	  if ( name ( list ) == test_tag &&
947
	       pt ( list ) == second ) {
948
	    return ( list ) ;
949
	  } else {
950
	    return ( nilexp ) ;
951
	  }
952
	} else {
953
	  list = bro ( list ) ;
954
	}
955
      }
956
    }
957
  }
958
  return ( nilexp ) ;
959
}
960
 
961
/*
962
  IS e THE LAST PROCEDURE ARGUMENT?
963
*/
964
bool last_param 
965
    PROTO_N ( ( e ) )
966
    PROTO_T ( exp e )
967
{
968
  if ( !isparam ( e ) ) return ( 0 ) ;
969
  e = bro ( son ( e ) ) ;
970
#ifndef NEWDIAGS
971
  aa :
972
#endif
973
  {
974
    if ( (name ( e ) == ident_tag && name(son(e)) != formal_callee_tag) && 
975
	 isparam ( e ) ) return ( 0 ) ;
976
#ifndef NEWDIAGS
977
    if ( name ( e ) == diagnose_tag ) {
978
      e = son ( e ) ;
979
      goto aa ;
980
    }
981
#endif
982
  }
983
  return ( 1 ) ;
984
}
985
 
986
 
987
/*
988
  DOES e OR ONE OF ITS COMPONENTS CONTAIN A BITFIELD?
989
  Should really detect this once and for all at an earlier stage and
990
  record in props ( e ).
991
*/
992
static int has_bitfield 
993
    PROTO_N ( ( e ) )
994
    PROTO_T ( exp e )
995
{
996
  if ( e == nilexp ) return ( 0 ) ;
997
  switch ( name ( e ) ) {
998
    case compound_tag : {
999
      e = bro ( son ( e ) ) ;
1000
      while ( 1 ) {
1001
	if ( has_bitfield ( e ) ) return ( 1 ) ;
1002
	if ( last ( e ) ) return ( 0 ) ;
1003
	e = bro ( bro ( e ) ) ; 
1004
      }
1005
      /* NOT REACHED */
1006
    }
1007
 
1008
    default : {
1009
      return ( shape_align ( sh ( e ) ) == 1 ) ;
1010
    }
1011
  }
1012
  /* NOT REACHED */
1013
}
1014
 
1015
 
1016
/*
1017
  CONVERT ALL NON-BITFIELDS FROM BYTE OFFSETS TO BIT OFFSETS
1018
  This must be done exactly once.  The problem arises because of the
1019
  val_tag case in needscan.c.
1020
*/
1021
 
1022
static void fix_nonbitfield 
1023
    PROTO_N ( ( e ) )
1024
    PROTO_T ( exp e )
1025
{
1026
  if ( name ( e ) == compound_tag ) {
1027
    e = son ( e ) ;
1028
    while ( 1 ) {
1029
      if ( name ( e ) == val_tag && name ( sh ( e ) ) == offsethd
1030
	   && al2 ( sh ( e ) ) >= 8 ) {
1031
	no ( e ) = no ( e ) << 3 ;
1032
      }
1033
      fix_nonbitfield ( bro ( e ) ) ;
1034
      if ( last ( bro ( e ) ) ) return ;
1035
      e = bro ( bro ( e ) ) ;
1036
    }
1037
    /* NOT REACHED */
1038
  }
1039
  return ;
1040
}
1041
 
1042
 
1043
/*
1044
  USEFUL MACROS
1045
*/
1046
 
1047
#define issgn( s )	is_signed ( s )
1048
 
1049
#define isdbl( s )	( ( bool ) ( name ( s ) != shrealhd ) )
1050
 
1051
#define is_long_double(s) ((bool) (name(s) == doublehd))
1052
 
1053
#define fregno( d, f )	( ( d ) ? -( ( f ) + 32 ) : ( ( f ) + 32 ) )
1054
 
1055
#define GETREG( d, s )	( discrim ( ( d ).answhere ) == inreg ?\
1056
			  regalt ( ( d ).answhere ) :\
1057
			  getreg ( ( s ).fixed ) )
1058
 
1059
#define GETFREG( d, s )	( discrim ( ( d ).answhere ) == infreg ?\
1060
			  regalt ( ( d ).answhere ) :\
1061
			  getfreg ( ( s ).flt ) )
1062
 
1063
 
1064
 
1065
/*
1066
  This function finds the caller_tag corresponding to a caller_name tag
1067
*/
1068
exp find_ote 
1069
    PROTO_N ( ( nom, n ) )
1070
    PROTO_T ( exp nom X int n ) 
1071
{
1072
  exp dad = father(nom);
1073
  while(name(dad) != apply_general_tag) {
1074
    dad = father(dad);
1075
  }
1076
  dad = son(bro(son(dad)));
1077
  while(n) {
1078
    dad = bro(dad);
1079
    n -- ;
1080
  }
1081
  assert(name(dad) == caller_tag);
1082
  return dad;
1083
}
1084
 
1085
/*
1086
  If the floating point value held in register r will, when converted,
1087
  fit into the integer variety rep_var then return, otherwise output
1088
  a jump to label lab and return.  The conversion functions always perform a 
1089
  round_towards zero, so the numbers used as the limits of the ranges are
1090
  adjusted to account for this.
1091
*/
1092
void check_range_and_do_error_jump 
1093
    PROTO_N ( ( rep_var, r, lab, sp, rmode ) )
1094
    PROTO_T ( shape rep_var X int r X int lab X space sp X int rmode ) 
1095
{
1096
  int ftmp = getfreg(sp.flt);
1097
  int to_small = (rmode == (int)f_toward_smaller);
1098
  switch(name(rep_var)) {
1099
    case ulonghd : {
1100
      /* check    0 <= value <= (unsigned)-1 */
1101
      /* fconst(ftmp,1106247679,-2097152); */
1102
 
1103
      if(to_small) {
1104
	fconst(ftmp,1106247680,0);
1105
      }
1106
      else {
1107
	fconst(ftmp,1106247679,-2097152);
1108
      }
1109
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1110
      fbr_ins(i_fbg,lab);
1111
      if(to_small) {
1112
	fconst(ftmp,0,0);
1113
      }
1114
      else {
1115
	fconst(ftmp,-1074790400,0);
1116
      }
1117
 
1118
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1119
      fbr_ins(i_fbl,lab);
1120
      break;
1121
    }
1122
    case slonghd : {
1123
      /* check -0x80000000 =< value <= 0x7fffffff */
1124
      if(to_small) {
1125
	fconst(ftmp,-1042284544,0);
1126
      }
1127
      else {
1128
	fconst(ftmp,-1042284544,2097152);
1129
      }
1130
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1131
      fbr_ins(i_fbl,lab);
1132
      /*fconst(ftmp,1105199104,0);*/
1133
      if(to_small) {
1134
	fconst(ftmp,1105199104,0);
1135
      }
1136
      else {
1137
	fconst(ftmp,1105199103,-4194304);
1138
      }
1139
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1140
      fbr_ins(i_fbg,lab);
1141
      break;
1142
    }
1143
    case uwordhd : {
1144
      /* check 0 <= value <= 0xffff */
1145
      if(to_small) {
1146
	fconst(ftmp,0,0);
1147
      }
1148
      else {
1149
	fconst(ftmp,-1074790400,0);
1150
      }
1151
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1152
      fbr_ins(i_fbl,lab);
1153
      if(to_small) {
1154
	fconst(ftmp,1089470464,0);
1155
      }
1156
      else {
1157
	fconst(ftmp,1089470432,0);
1158
      }
1159
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1160
      fbr_ins(i_fbg,lab);
1161
      break;
1162
    }
1163
    case swordhd : {
1164
      /* check -0x8000 <= value <= 0x7fff */
1165
      if(to_small) {
1166
	fconst(ftmp,-1059061760,0);
1167
      }
1168
      else {
1169
	fconst(ftmp,-1059061728,0);
1170
      }
1171
 
1172
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1173
      fbr_ins(i_fbl,lab);
1174
      if(to_small) {
1175
	fconst(ftmp,1088421888,0);
1176
      }
1177
      else {
1178
	fconst(ftmp,1088421824,0);
1179
      }
1180
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1181
      fbr_ins(i_fbg,lab);
1182
      break;
1183
    }
1184
    case scharhd : {
1185
      if(to_small) {
1186
	fconst(ftmp,-1067450368,0);
1187
      }
1188
      else {
1189
	fconst(ftmp,-1067442176,0);
1190
      }
1191
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1192
      fbr_ins(i_fbl,lab);
1193
      if(to_small) {
1194
	fconst(ftmp,1080033280,0);
1195
      }
1196
      else {
1197
	fconst(ftmp,1080016896,0);
1198
      }
1199
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1200
      fbr_ins(i_fbg,lab);
1201
      break;
1202
    }
1203
    case ucharhd : {
1204
      if(to_small) {
1205
	fconst(ftmp,0,0);
1206
      }
1207
      else {
1208
	fconst(ftmp,-1074790400,0);
1209
      }
1210
 
1211
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1212
      fbr_ins(i_fbl,lab);
1213
      if(to_small) {
1214
	fconst(ftmp,1081081856,0);
1215
      }
1216
      else {
1217
	fconst(ftmp,1081073664,0);
1218
      }
1219
 
1220
      rrf_ins(i_fcmpd,r<<1,ftmp<<1);
1221
      fbr_ins(i_fbg,lab);
1222
      break;
1223
    }
1224
    default : {
1225
      fail("shape not covered in range check");
1226
    }
1227
  }
1228
  return;
1229
}
1230
 
1231
 
1232
 
1233
/*
1234
  MAIN CODE PRODUCTION ROUTINE
1235
  Produce for for the expression e, putting its result into dest 
1236
  using the t-registers given by sp.  If exitlab is nonzero, it is 
1237
  the label where the code is to continue.
1238
*/
1239
 
1240
#ifdef NEWDIAGS
1241
makeans make_code_1 
1242
    PROTO_N ( ( e, sp, dest, exitlab ) )
1243
    PROTO_T ( exp e X space sp X where dest X int exitlab )
1244
{
1245
#else
1246
makeans make_code 
1247
    PROTO_N ( ( e, sp, dest, exitlab ) )
1248
    PROTO_T ( exp e X space sp X where dest X int exitlab )
1249
{
1250
#endif
1251
  makeans mka ;
1252
  static exceptions_initialised;
1253
  mka.lab = exitlab ;
1254
  mka.regmove = NOREG ;
1255
  insection ( text_section ) ;
1256
 
1257
  switch ( name ( e ) ) {
1258
    case general_proc_tag :
1259
    case proc_tag : {
1260
      /* Procedure body */
1261
      static int inside_proc = 0 ;
1262
      exceptions_initialised = 0;
1263
      if ( inside_proc ) {
1264
	fail ( "Nested procedures not implemented" ) ;
1265
      } else {
1266
	inside_proc = 1 ;
1267
	mka = make_proc_tag_code ( e, sp, dest, exitlab ) ;
1268
	inside_proc = 0 ;
1269
	exceptions_initialised = 0;
1270
      }
1271
      return ( mka ) ;
1272
    }
1273
    case untidy_return_tag : 
1274
    case res_tag : {
1275
      /* Procedure result */
1276
      return ( make_res_tag_code ( e, sp, dest, exitlab ) ) ;
1277
    }
1278
    case caller_tag : {
1279
      return make_code(son(e),sp,dest,exitlab);
1280
    }
1281
    case apply_general_tag : {
1282
      return make_apply_general_tag_code(e,sp,dest,exitlab);
1283
    }
1284
    case caller_name_tag : {
1285
      return mka;
1286
    }
1287
    case make_callee_list_tag :  {
1288
      return make_make_callee_list_tag(e,sp,dest,exitlab);
1289
    }
1290
    case same_callees_tag :  {
1291
      return make_same_callees_tag(e,sp,dest,exitlab);
1292
    }
1293
    case make_dynamic_callee_tag :  {
1294
      return make_make_dynamic_callee_tag(e,sp,dest,exitlab);
1295
    }
1296
    case tail_call_tag :  {
1297
      return make_tail_call_tag(e,sp,dest,exitlab);
1298
    }
1299
    case return_to_label_tag : {
1300
      int r = getreg(sp.fixed);
1301
      where w;
1302
      w.ashwhere.ashsize = 32;
1303
      w.ashwhere.ashalign = 32;
1304
 
1305
      setregalt(w.answhere,r);
1306
      code_here(son(e),sp,w);
1307
      clear_all();
1308
      rr_ins(i_mov,r,R_TMP);
1309
      /*rir_ins(i_sub,R_FP,proc_state.callee_size>>3,R_FP);*/
1310
#ifdef NEWDWARF
1311
      if (current_dg_info) {
1312
	current_dg_info->data.i_lj.brk = set_dw_text_label ();
1313
	current_dg_info->data.i_lj.j.k = WH_REG;
1314
	current_dg_info->data.i_lj.j.u.l = R_TMP;
1315
      }
1316
#endif
1317
      extj_reg_ins_no_delay(i_jmp,R_TMP,-1);
1318
      rir_ins(i_restore,R_FP,
1319
	      0/*-(proc_state.frame_size)>>3*/,R_SP);
1320
      clear_all();
1321
      return mka;
1322
    }
1323
 
1324
 
1325
    case apply_tag : {
1326
      /* Procedure application */
1327
      mka = make_apply_tag_code ( e, sp, dest, exitlab ) ;
1328
#if 0
1329
      if(Has_vcallees){
1330
	/* restore local_reg */
1331
	baseoff b;
1332
	b.base = R_FP;
1333
	b.offset = -3 * PTR_SZ>>3;
1334
	ld_ro_ins(i_ld,b,local_reg);
1335
      }
1336
#endif
1337
      return mka;
1338
    }
1339
    case top_tag :
1340
    case clear_tag : {
1341
      /* Do nothing */
1342
      if ( discrim ( dest.answhere ) == insomereg ) {
1343
	int *sr = someregalt ( dest.answhere ) ;
1344
	if ( *sr != -1 ) fail ( "Illegal register" ) ;
1345
	*sr = R_G0 ;
1346
      }
1347
      return ( mka ) ;
1348
    }
1349
 
1350
    case prof_tag : {
1351
      return mka;
1352
    }
1353
 
1354
    case seq_tag : {
1355
      /* Sequences */
1356
      exp t = son ( son ( e ) ) ;
1357
      exp f = bro ( son ( e ) ) ;
1358
      for ( ; ; ) {
1359
	exp nt = ( last ( t ) ? f : bro ( t ) ) ;
1360
	if ( name ( nt ) == goto_tag ) {
1361
	  /* Gotos end sequences */
1362
	  make_code ( t, sp, nowhere, no ( son ( pt ( nt ) ) ) ) ;
1363
	} else {
1364
	  ( void ) code_here ( t, sp, nowhere ) ;
1365
	}
1366
	if ( last ( t ) ) {
1367
	  return ( make_code ( f, sp, dest, exitlab ) ) ;
1368
	}
1369
	t = nt ;
1370
      }
1371
      /* NOT REACHED */
1372
    }
1373
 
1374
    case labst_tag : {
1375
      /* Labelled statements */
1376
      int lb = no ( son ( e ) ) ;
1377
      if ( lb != 0 ) {
1378
	clear_all () ;
1379
	set_label ( lb ) ;
1380
#ifdef NEWDWARF
1381
        START_BB ();
1382
#endif
1383
      }
1384
      return ( make_code ( bro ( son ( e ) ), sp, dest, exitlab ) ) ;
1385
    }
1386
 
1387
    case rep_tag : {
1388
      /* Repeats */
1389
      exp first = son ( e ) ;
1390
      exp second = bro ( first ) ;
1391
      code_here(first,sp,nowhere);
1392
      no ( son ( second ) ) = new_label () ;
1393
 
1394
      return ( make_code ( second, sp, dest, exitlab ) ) ;
1395
    }
1396
 
1397
    case make_lv_tag :  {
1398
      exp labst = pt(e);
1399
      assert(name(labst) == labst_tag);
1400
      {
1401
	int lab = no(son(labst)); /* this is the asm lab no without
1402
				     the prefix on it */
1403
	/* Now the code is much like val_tag, save that the value is a string...
1404
	 */
1405
	int r ;
1406
	switch ( discrim ( dest.answhere ) ){
1407
	  case inreg : {
1408
	    r = regalt ( dest.answhere ) ;
1409
	    lr_ins ( lab, r ) ;
1410
	    break ;
1411
	  }
1412
	  default : {
1413
	    ans aa ;
1414
	    r = getreg ( sp.fixed ) ;
1415
	    lr_ins ( lab, r ) ;
1416
	    setregalt ( aa, r ) ;
1417
	    (void)move ( aa, dest, guardreg ( r, sp ).fixed, 1 ) ;
1418
	  }
1419
	}
1420
	mka.regmove = r ;
1421
	return ( mka ) ;
1422
      }
1423
    }
1424
 
1425
    case goto_lv_tag : {
1426
      int ptr_reg;
1427
      assert (last(son(e)));	  
1428
      ptr_reg = reg_operand (son(e), sp ) ;
1429
#ifdef NEWDWARF
1430
      if (current_dg_info) {
1431
	current_dg_info->data.i_lj.brk = set_dw_text_label ();
1432
	current_dg_info->data.i_lj.j.k = WH_REG;
1433
	current_dg_info->data.i_lj.j.u.l = ptr_reg;
1434
      }
1435
#endif
1436
      extj_reg_ins( i_jmp, ptr_reg, -1); /* -1 means no params (not call)*/
1437
      return(mka);
1438
    }
1439
 
1440
    case goto_tag : {
1441
      /* Gotos */
1442
      int lab = no ( son ( pt ( e ) ) ) ;
1443
      assert ( lab >= 100 ) ;
1444
      clear_all () ;
1445
      /* needed if lab == exitlab ? */
1446
#ifdef NEWDWARF
1447
      if (current_dg_info) {
1448
	current_dg_info->data.i_tst.brk = set_dw_text_label ();
1449
	current_dg_info->data.i_tst.jlab.u.l = lab;
1450
	current_dg_info->data.i_tst.jlab.k = LAB_CODE;
1451
      }
1452
#endif
1453
      uncond_ins ( i_b, lab ) ;
1454
      return ( mka ) ;
1455
    }
1456
 
1457
    case test_tag : {
1458
      /* Tests */
1459
      int lab ;
1460
      ins_p branch ;
1461
      exp l = son ( e ) ;
1462
      exp r = bro ( l ) ;
1463
      shape shl = sh ( l ) ;
1464
 
1465
      /* Find test number (mask out Rev bit) */
1466
      int n = (int)test_number(e);
1467
 
1468
#ifdef NEWDIAGS
1469
      if (dgf(l))
1470
	diag_arg (l, sp, dest);
1471
      if (dgf(r))
1472
	diag_arg (r, sp, dest);
1473
#endif
1474
 
1475
      /* Find label - see cond_tag case */
1476
      if ( ptno ( e ) < 0 ) {
1477
	lab = -ptno ( e ) ;
1478
      } else {
1479
	lab = no ( son ( pt ( e ) ) ) ;
1480
      }
1481
 
1482
#if use_long_double
1483
      if ( name ( sh ( l ) ) == doublehd ) {
1484
	if ( IsRev ( e ) ) {
1485
	  quad_op ( r, l, sp, dest, -n ) ;
1486
        } 
1487
	else {
1488
	  quad_op ( l, r, sp, dest, -n ) ;
1489
	}
1490
#ifdef NEWDWARF
1491
	if (current_dg_info) {
1492
	  current_dg_info->data.i_tst.brk = set_dw_text_label ();
1493
	  current_dg_info->data.i_tst.jlab.u.l = lab;
1494
	  current_dg_info->data.i_tst.jlab.k = LAB_CODE;
1495
	}
1496
#endif
1497
	condrr_ins ( i_bne, R_O0, R_G0, lab ) ;
1498
#ifdef NEWDWARF
1499
	START_BB ();
1500
	if (current_dg_info)
1501
	  current_dg_info->data.i_tst.cont = set_dw_text_label ();
1502
#endif
1503
	return ( mka ) ;
1504
      }
1505
#endif
1506
 
1507
      if ( is_floating ( name ( sh ( l ) ) ) ) {
1508
	/* Floating tests */
1509
	space nsp ;
1510
	int a1, a2 ;
1511
	bool dble = isdbl ( shl ) ;
1512
	ins_p compare = ( dble ? i_fcmpd : i_fcmps ) ;
1513
 
1514
	branch = fbranches ( n ) ;
1515
	if ( IsRev ( e ) ) {
1516
	  a2 = freg_operand ( r, sp, getfreg ( sp.flt ) ) ;
1517
	  nsp = guardfreg ( a2, sp ) ;
1518
	  a1 = freg_operand ( l, nsp, getfreg ( nsp.flt ) ) ;
1519
	} else {
1520
	  a1 = freg_operand ( l, sp, getfreg ( sp.flt ) ) ;
1521
	  nsp = guardfreg ( a1, sp ) ;
1522
	  a2 = freg_operand ( r, nsp, getfreg ( nsp.flt ) ) ;
1523
	}
1524
	rrf_cmp_ins ( compare, a1 << 1, a2 << 1 ) ;
1525
#ifdef NEWDWARF
1526
	if (current_dg_info) {
1527
	  current_dg_info->data.i_tst.brk = set_dw_text_label ();
1528
	  current_dg_info->data.i_tst.jlab.u.l = lab;
1529
	  current_dg_info->data.i_tst.jlab.k = LAB_CODE;
1530
	}
1531
#endif
1532
	fbr_ins ( branch, lab ) ;
1533
#ifdef NEWDWARF
1534
	START_BB ();
1535
	if (current_dg_info)
1536
	  current_dg_info->data.i_tst.cont = set_dw_text_label ();
1537
#endif
1538
	return ( mka ) ;
1539
      } 
1540
      else {
1541
	/* Integer tests */
1542
	int a1, a2 ;
1543
	bool unsgn ;
1544
	assert(name(l) != val_tag); /* now in common section */
1545
	/* Choose branch instruction */
1546
	unsgn = (bool)(!is_signed(shl) || name(shl)==ptrhd);
1547
	branch = ( unsgn ? usbranches ( n ) : sbranches ( n ) ) ;
1548
	a1 = reg_operand ( l, sp ) ;
1549
	if ( name ( r ) == val_tag ) {
1550
	  long v = no(r);
1551
#ifdef NEWDWARF
1552
	  if (current_dg_info)
1553
	    current_dg_info->data.i_tst.brk = set_dw_text_label ();
1554
#endif
1555
	  if ( unsgn && v == 0 && ( n == 2 || n == 3 ) ) {
1556
	    /* Do unsigned < 0 and unsigned >= 0 */
1557
	    br_ins ( ( n == 2 ? i_bn : i_ba ), lab ) ;
1558
	  } 
1559
	  else
1560
	    {
1561
	      /* work round for using 0xffffffff as -1
1562
		 unsigned <=0 becomes == 0
1563
		 unsigned >0 becomes != 0 */
1564
	      if ( unsgn && v == 0 && ( n == 1 || n == 4 ) ) 
1565
		{
1566
		  n = ((n==1) ? 6 : 5);
1567
		  branch = usbranches ( n ) ;
1568
		}
1569
	      if ( v ) {
1570
		condri_ins ( branch, a1, v, lab ) ;
1571
	      } else {
1572
		condrr_ins ( branch, a1, R_G0, lab ) ;
1573
	      }
1574
	    }
1575
	} else {
1576
	  space nsp ;
1577
	  nsp = guardreg ( a1, sp ) ;
1578
	  a2 = reg_operand ( r, nsp ) ;
1579
#ifdef NEWDWARF
1580
	  if (current_dg_info)
1581
	    current_dg_info->data.i_tst.brk = set_dw_text_label ();
1582
#endif
1583
	  condrr_ins ( branch, a1, a2, lab ) ;
1584
	}
1585
#ifdef NEWDWARF
1586
	START_BB ();
1587
	if (current_dg_info) {
1588
	  current_dg_info->data.i_tst.jlab.u.l = lab;
1589
	  current_dg_info->data.i_tst.jlab.k = LAB_CODE;
1590
	  current_dg_info->data.i_tst.cont = set_dw_text_label ();
1591
	}
1592
#endif
1593
	return ( mka ) ;
1594
      }
1595
      /* NOT REACHED */
1596
    }
1597
 
1598
#ifndef NEWDIAGS
1599
    case diagnose_tag : {
1600
      /* Diagnostics */
1601
      diag_info *d = dno ( e ) ;
1602
#if DWARF
1603
      output_diag ( d, 0, e ) ;
1604
      mka = make_code ( son ( e ), sp, dest, exitlab ) ;
1605
      output_end_scope ( d, e ) ;
1606
#else
1607
      stab_begin ( d, 0, e ) ;
1608
      mka = make_code ( son ( e ), sp, dest, exitlab ) ;
1609
      stab_end ( d, e ) ;
1610
#endif
1611
      return ( mka ) ;
1612
    }
1613
#endif
1614
 
1615
    case solve_tag : {
1616
      /* Labelled statements */
1617
      exp m = bro ( son ( e ) ) ;
1618
      int l = exitlab ;
1619
 
1620
      if ( discrim ( dest.answhere ) == insomereg ) {
1621
	int *sr = someregalt ( dest.answhere ) ;
1622
	if ( *sr != -1 ) fail ( "Illegal register" ) ;
1623
	*sr = getreg ( sp.fixed ) ;
1624
	setregalt ( dest.answhere, *sr ) ;
1625
      }
1626
      /* Set up all the labels */
1627
      for ( ; ; ) {
1628
	no ( son ( m ) ) = new_label () ;
1629
	if ( last ( m ) ) break ;
1630
	m = bro ( m ) ;
1631
      }
1632
      m = son ( e ) ;
1633
      /* Evaluate all the component statements */
1634
      for ( ; ; ) {
1635
	int fl = make_code ( m, sp, dest, l ).lab ;
1636
	clear_all () ;
1637
	if ( fl != 0 ) l = fl ;
1638
	if ( !last ( m ) ) {
1639
	  /* jump to end of solve */
1640
	  if ( l == 0 ) l = new_label () ;
1641
	  if ( name ( sh ( m ) ) != bothd ) uncond_ins ( i_b, l ) ;
1642
	}
1643
	if ( last ( m ) ) {
1644
	  mka.lab = l ;
1645
	  return ( mka ) ;
1646
	}
1647
	m = bro ( m ) ;
1648
      }
1649
      /* NOT REACHED */
1650
    }
1651
    case chvar_tag : {
1652
      /* Change integer variety */
1653
      exp arg = son ( e ) ;
1654
      int size_e = shape_size ( sh ( e ) ) ;
1655
      int to = ( int ) name ( sh ( e ) ), from ;
1656
      int sreg, dreg ;
1657
      bool inmem_dest ;
1658
 
1659
      space nsp;
1660
 
1661
    /* For a series of chvar_tags, do large to small in one go */
1662
      while ( name ( arg ) == chvar_tag &&
1663
	      shape_size ( sh ( arg ) ) >= size_e ) {
1664
	arg = son ( arg ) ;
1665
      }
1666
      from = (int) name ( sh ( arg ) ) ;
1667
#if 1	    
1668
      if (from == bitfhd) {
1669
	switch (shape_size(sh(arg))) {
1670
	  case 8:
1671
	  sh(arg) = is_signed(sh(arg)) ? scharsh : ucharsh;
1672
	  from = name(sh(arg));
1673
	  break;
1674
	  case 16:
1675
	  sh(arg) = is_signed(sh(arg)) ? swordsh : uwordsh;
1676
	  from = name(sh(arg));
1677
	  break;
1678
	  case 32:
1679
	  sh(arg) = is_signed(sh(arg)) ? slongsh : ulongsh;
1680
	  from = name(sh(arg));
1681
	  break;
1682
	}
1683
      }
1684
 
1685
      if (to == bitfhd){
1686
	switch (shape_size(sh(e))){
1687
	  case 8:
1688
	  sh(e) = is_signed(sh(e)) ? scharsh : ucharsh;
1689
	  to = name (sh(e));
1690
	  break;
1691
	  case 16:
1692
	  sh(e) = is_signed(sh(e)) ? swordsh : uwordsh;
1693
	  to = name (sh(e));
1694
	  break;
1695
	  case 32:
1696
	  sh(e) = is_signed(sh(e)) ? slongsh : ulongsh;
1697
	  to = name (sh(e));
1698
	  break;
1699
	}
1700
      }
1701
 
1702
#endif
1703
      /* Small to large conversions */
1704
      if ( from == to || to == slonghd || to == ulonghd ||
1705
	   ( to == uwordhd && from == ucharhd ) ||
1706
	   ( to == swordhd && from == scharhd ) ||
1707
	   ( to == swordhd && from == ucharhd ) ) {
1708
	ans aa ;
1709
	switch ( discrim ( dest.answhere ) ) {
1710
	  case inreg : {
1711
	    sreg = regalt ( dest.answhere ) ;
1712
	    if(sreg == R_G0){
1713
	      if(0 /*optop(e)*/){
1714
		return mka;
1715
	      }
1716
	      else {
1717
		sreg = getreg(sp.fixed);
1718
	      }
1719
	    }
1720
	    sp = guardreg(sreg,sp);
1721
	    reg_operand_here ( arg, sp, sreg ) ;
1722
	    break ;
1723
	  }
1724
	  default : {
1725
	    sreg = reg_operand ( arg, sp ) ;
1726
	    break ;
1727
	  }
1728
	}
1729
	if(!optop(e)){
1730
	  switch ( to ) {
1731
	    case ucharhd : {
1732
	      if(is_signed(sh(son(e)))){
1733
		if(error_treatment_is_trap(e)){
1734
		  int oklab = new_label();
1735
		  condrr_ins(i_bge,sreg,R_G0,oklab);
1736
		  do_exception(f_overflow);
1737
		  set_label(oklab);
1738
		}
1739
		else{
1740
		  condrr_ins(i_blt,sreg,R_G0,no(son(pt(e))));
1741
		}
1742
	      }
1743
	      break ;
1744
	    }
1745
	    case scharhd : {
1746
	      if(!is_signed(sh(son(e)))){
1747
		if(error_treatment_is_trap(e)){
1748
		  int oklab = new_label();
1749
		  condri_ins(i_bleu,sreg,0x7f,oklab);
1750
		  do_exception(f_overflow);
1751
		  set_label(oklab);
1752
		}
1753
		else{
1754
		  condri_ins(i_bgtu,sreg,0x7f,no(son(pt(e))));
1755
		}
1756
	      }
1757
	      break ;
1758
	    }
1759
	    case uwordhd : {
1760
	      if(is_signed(sh(son(e)))){
1761
		if(error_treatment_is_trap(e)){
1762
		  int oklab = new_label();
1763
		  condrr_ins(i_bge,sreg,R_G0,oklab);
1764
		  do_exception(f_overflow);
1765
		  set_label(oklab);
1766
		}
1767
		else{
1768
		  condrr_ins(i_blt,sreg,R_G0,no(son(pt(e))));
1769
		}
1770
	      }
1771
	      break ;
1772
	    }
1773
	    case swordhd : {
1774
	      if(!is_signed(sh(son(e)))){
1775
		if(error_treatment_is_trap(e)){
1776
		  int oklab = new_label();
1777
		  condri_ins(i_bleu,sreg,0x7fff,oklab);
1778
		  do_exception(f_overflow);
1779
		  set_label(oklab);
1780
		}
1781
		else{
1782
		  condri_ins(i_bgtu,sreg,0x7fff,no(son(pt(e))));
1783
		}
1784
	      }
1785
	      break ;
1786
	    }
1787
	    case ulonghd :{
1788
	      if(is_signed(sh(son(e)))){
1789
		if(error_treatment_is_trap(e)){
1790
		  int oklab = new_label();
1791
		  condrr_ins(i_bge,sreg,R_G0,oklab);
1792
		  do_exception(f_overflow);
1793
		  set_label(oklab);
1794
		}
1795
		else{
1796
		  condrr_ins(i_blt,sreg,R_G0,no(son(pt(e))));
1797
		}
1798
	      }
1799
	      break;
1800
	    }
1801
	    case slonghd :{
1802
	      if(!is_signed(sh(son(e)))){
1803
		if(error_treatment_is_trap(e)){
1804
		  int oklab = new_label();
1805
		  condri_ins(i_bleu,sreg,0x7fffffff,oklab);
1806
		  do_exception(f_overflow);
1807
		  set_label(oklab);
1808
		}
1809
		else{
1810
		  condri_ins(i_bgtu,sreg,0x7fffffff,no(son(pt(e))));
1811
		}
1812
	      }
1813
	      break;
1814
	    }
1815
 
1816
	    default :
1817
	    break ;
1818
	  }
1819
	}
1820
	setregalt ( aa, sreg ) ;
1821
	mka.regmove = move ( aa, dest, sp.fixed, issgn ( sh ( e ) ) ) ;
1822
	return ( mka ) ;
1823
      }
1824
 
1825
    switch ( discrim ( dest.answhere ) ) {
1826
      case inreg : {
1827
	sreg = reg_operand ( arg, sp ) ;
1828
	nsp = guardreg(sreg, sp);
1829
	dreg = regalt ( dest.answhere ) ;
1830
	if(dreg == R_G0){
1831
	  if(optop(e)){
1832
	    return mka;
1833
	  }
1834
	  else { 
1835
	    dreg = getreg(nsp.fixed);
1836
	  }
1837
	}
1838
	inmem_dest = 0 ;
1839
	break ;
1840
      }
1841
      case insomereg : {
1842
	int *dr = someregalt ( dest.answhere ) ;
1843
	sreg = reg_operand ( arg, sp ) ;
1844
	nsp = guardreg(sreg, sp);
1845
	dreg = getreg ( sp.fixed ) ;
1846
	*dr = dreg ;
1847
	inmem_dest = 0 ;
1848
	break ;
1849
      }
1850
      default : {
1851
	sreg = reg_operand ( arg, sp ) ;
1852
	nsp = guardreg(sreg, sp);
1853
	dreg = getreg ( sp.fixed ) ;
1854
	inmem_dest = 1 ;
1855
	break ;
1856
      }
1857
    }
1858
 
1859
    if ( inmem_dest && size_e <= shape_size ( sh ( arg ) ) ) {
1860
      /* Going to smaller sized memory, store will truncate */
1861
      ans aa ;
1862
      setregalt ( aa, sreg ) ;
1863
      ( void ) move ( aa, dest, nsp.fixed, 1 ) ;
1864
      return ( mka ) ;
1865
    }
1866
 
1867
    /* Shorten type if needed */
1868
    switch ( to ) {
1869
      case ucharhd : {
1870
	if(!optop(e)){
1871
	  if(error_treatment_is_trap(e)){
1872
	    test_unsigned_and_trap(sreg,255,f_overflow);
1873
	  }
1874
	  else {
1875
	    test_unsigned(sreg,255,no(son(pt(e))));
1876
	  }
1877
	}
1878
	rir_ins ( i_and, sreg, 0xff, dreg ) ;
1879
	break ;
1880
      }
1881
      case scharhd : {
1882
	if(!optop(e)){
1883
	  if(error_treatment_is_trap(e)){
1884
	    test_signed_and_trap(sreg,-128,127,f_overflow);
1885
	  }
1886
	  else{
1887
	    test_signed(sreg,-128,127,no(son(pt(e))));
1888
	  }
1889
	}
1890
	rir_ins ( i_sll, sreg, 24, dreg ) ;
1891
	rir_ins ( i_sra, dreg, 24, dreg ) ;
1892
	break ;
1893
      }
1894
      case uwordhd : {
1895
	if(!optop(e)){
1896
	  if(error_treatment_is_trap(e)){
1897
	    test_unsigned_and_trap(sreg,0xffff,f_overflow);
1898
	  }
1899
	  else{
1900
	    test_unsigned(sreg,0xffff,no(son(pt(e))));
1901
	  }
1902
	}
1903
	if ( from != ucharhd ) {
1904
	  rir_ins ( i_and, sreg, 0xffff, dreg ) ;
1905
	} else if ( sreg != dreg ) {
1906
	  rr_ins ( i_mov, sreg, dreg ) ;
1907
	}
1908
	break ;
1909
      }
1910
      case swordhd : {
1911
	if(!optop(e)){
1912
	  if(error_treatment_is_trap(e)){
1913
	    test_signed_and_trap(sreg,-0x8000,0x7fff,f_overflow);
1914
	  }
1915
	  else{
1916
	    test_signed(sreg,-0x8000,0x7fff,no(son(pt(e))));
1917
	  }
1918
	}
1919
	if ( from != scharhd && from != ucharhd ) {
1920
	  rir_ins ( i_sll, sreg, 16, dreg ) ;
1921
	  rir_ins ( i_sra, dreg, 16, dreg ) ;
1922
	  break ;
1923
	}
1924
	/* FALL THROUGH */
1925
      }
1926
      default : {
1927
	if ( sreg != dreg ) rr_ins ( i_mov, sreg, dreg ) ;
1928
	break ;
1929
      }
1930
    }
1931
 
1932
    if ( inmem_dest ) {
1933
      ans aa ;
1934
      setregalt ( aa, dreg ) ;
1935
      ( void ) move ( aa, dest, nsp.fixed, 1 ) ;
1936
    } else {
1937
      mka.regmove = dreg ;
1938
    }
1939
    return ( mka ) ;
1940
    }
1941
 
1942
    case env_size_tag : {
1943
      int constval = (proc_state.frame_size+proc_state.callee_size)>>3;
1944
      ans aa;
1945
      int rt = getreg(sp.fixed);
1946
      ir_ins(i_mov,constval,rt);
1947
      setregalt(aa,rt);
1948
      (void)move(aa,dest,guardreg(rt,sp).fixed,1);
1949
      mka.regmove = rt;
1950
      return mka;
1951
    }
1952
 
1953
 
1954
    case plus_tag :
1955
    case offset_add_tag : {
1956
      /* Addition */
1957
      if(optop(e)){
1958
	mka.regmove = comm_op ( e, sp, dest,(optop(e))?i_add:i_addcc) ;
1959
	return mka;
1960
      }
1961
#if 0
1962
      if(error_treatment_is_trap(e)){
1963
	int new_lab = new_label();
1964
	mka.regmove = comm_op ( e, sp, dest,(optop(e))?i_add:i_addcc) ;
1965
	uncond_ins(i_bvc,new_lab);
1966
	do_exception(f_overflow);
1967
	set_label(new_lab);
1968
	return mka;
1969
      }
1970
#endif      
1971
      if (!optop(e) /*&& !error_treatment_is_trap(e)*/){
1972
       where newdest;
1973
       ans aa;
1974
       int res_reg = getreg(sp.fixed);
1975
       space nsp;
1976
       newdest.ashwhere = dest.ashwhere;
1977
       newdest.answhere.d = inreg;
1978
 
1979
       newdest.answhere.val.regans = res_reg;
1980
       nsp = guardreg(res_reg,sp);
1981
       /*       if(name(sh(e)) != ulonghd && name(sh(e)) != slonghd)*/
1982
       mka.regmove = comm_op ( e, sp, newdest,(optop(e))?i_add:i_addcc) ;
1983
       switch(name(sh(e))){
1984
	 case ulonghd: {
1985
	   int l,r;
1986
	   /*int newlab = new_label();*/
1987
	   int rt;
1988
	   rt = getreg(nsp.fixed);
1989
	   l = reg_operand(son(e),nsp);
1990
	   r = reg_operand(bro(son(e)),nsp);		
1991
 
1992
	   if(error_treatment_is_trap(e)){
1993
	     int new_lab = new_label();
1994
	     condrr_ins(i_bgeu,res_reg,l,new_lab);
1995
	     do_exception(f_overflow);
1996
	     set_label(new_lab);
1997
	   }
1998
	   else{
1999
	     condrr_ins(i_bltu,res_reg,l,no(son(pt(e))));
2000
	   }
2001
	   break;
2002
	 }
2003
 
2004
	  case slonghd: {
2005
	    check_integer_exception(e);
2006
	    break;
2007
	  }
2008
	  case swordhd:{
2009
	    if(error_treatment_is_trap(e)){
2010
	      test_signed_and_trap(res_reg,-0x8000,0x7fff,f_overflow);
2011
	    }
2012
	    else{
2013
	      test_signed(res_reg,-0x8000,0x7fff,no(son(pt(e))));
2014
	    }
2015
	    break;
2016
	  }
2017
	  case uwordhd:{
2018
	    if(error_treatment_is_trap(e)){
2019
	      test_unsigned_and_trap(res_reg,0xffff,f_overflow);
2020
	    }
2021
	    else{
2022
	      test_unsigned(res_reg,0xffff,no(son(pt(e))));
2023
	    }
2024
	    break;
2025
	  }
2026
	 case scharhd:{
2027
	   if(error_treatment_is_trap(e)){
2028
	     test_signed_and_trap(res_reg,-128,127,f_overflow);
2029
	   }
2030
	   else{
2031
	     test_signed(res_reg,-128,127,no(son(pt(e))));
2032
	   }
2033
	   break;
2034
	 }
2035
	 case ucharhd:{
2036
	   if(error_treatment_is_trap(e)){
2037
	     test_unsigned_and_trap(res_reg,255,f_overflow);
2038
	   }
2039
	   else{
2040
	     test_unsigned(res_reg,255,no(son(pt(e))));
2041
	   }
2042
	   break;
2043
	 }
2044
	 default:
2045
	  failer("unimplemented shape");
2046
       }
2047
       setregalt(aa,res_reg);
2048
       mka.regmove = move(aa,dest,sp.fixed,0);
2049
       return mka;
2050
     }
2051
    }
2052
 
2053
 
2054
#ifdef make_stack_limit_tag
2055
    case make_stack_limit_tag :
2056
#endif
2057
    case minus_tag :
2058
    case minptr_tag :
2059
    case offset_subtract_tag : {
2060
    /* Subtraction */
2061
      if(optop(e)) {
2062
	mka.regmove = non_comm_op ( e, sp, dest, optop(e)?i_sub:i_subcc) ;
2063
	return mka;
2064
      }
2065
#if 0      
2066
      if(error_treatment_is_trap(e)) {
2067
      int new_lab = new_label();
2068
      mka.regmove = non_comm_op ( e, sp, dest, optop(e)?i_sub:i_subcc) ;
2069
      uncond_ins(i_bvc,new_lab);
2070
      do_exception(f_overflow);
2071
      set_label(new_lab);
2072
      return mka;
2073
      }
2074
#endif 
2075
      if(!optop(e) /*&& !error_treatment_is_trap(e)*/ ){
2076
	where newdest;
2077
	ans aa;
2078
	int res_reg = getreg(sp.fixed);
2079
	space nsp;
2080
	newdest.ashwhere = dest.ashwhere;
2081
	newdest.answhere.d = inreg;
2082
 
2083
	newdest.answhere.val.regans = res_reg;
2084
	nsp = guardreg(res_reg,sp);
2085
	mka.regmove = comm_op ( e, sp, newdest,(optop(e))?i_sub:i_subcc) ;
2086
 
2087
      switch(name(sh(e))){
2088
	case ulonghd:{
2089
	  int l,r;
2090
	  l = reg_operand(son(e),nsp);
2091
	  r = reg_operand(bro(son(e)),nsp);
2092
	  if(!error_treatment_is_trap(e)){
2093
	    condrr_ins(i_bgtu,r,l,no(son(pt(e))));
2094
	  }
2095
	  else{
2096
	    int newlab = new_label();
2097
	    condrr_ins(i_bleu,r,l,newlab);
2098
	    do_exception(f_overflow);
2099
	    set_label(newlab);
2100
	  }
2101
	  break;
2102
	}
2103
	case slonghd:{
2104
	  check_integer_exception(e);
2105
	  break;
2106
	}
2107
	case swordhd: {
2108
	  if(error_treatment_is_trap(e)){
2109
	    test_signed_and_trap(res_reg,-0x8000,0x7fff,f_overflow);
2110
	  }
2111
	  else{
2112
	    test_signed(res_reg,-0x8000,0x7fff,no(son(pt(e))));
2113
	  }
2114
	  break;
2115
	}
2116
	case uwordhd: {
2117
	  if(error_treatment_is_trap(e)){
2118
	    test_unsigned_and_trap(res_reg,0xffff,f_overflow);
2119
	  }
2120
	  else{
2121
	    test_unsigned(res_reg,0xffff,no(son(pt(e))));
2122
	  }
2123
	  break;
2124
	}
2125
	case scharhd: {
2126
	  if(error_treatment_is_trap(e)){
2127
	    test_signed_and_trap(res_reg,-128,127,f_overflow);
2128
	  }
2129
	  else{
2130
	    test_signed(res_reg,-128,127,no(son(pt(e))));
2131
	  }
2132
	  break;
2133
	}
2134
	case ucharhd: {
2135
	  if(error_treatment_is_trap(e)){
2136
	    test_unsigned_and_trap(res_reg,255,f_overflow);
2137
	  }
2138
	  else{
2139
	    test_unsigned(res_reg,255,no(son(pt(e))));
2140
	  }
2141
	  break;
2142
	}
2143
	default:
2144
	failer("unimplemented shape");
2145
      }	
2146
      setregalt(aa,res_reg);
2147
      mka.regmove = move(aa,dest,sp.fixed,0);
2148
      }
2149
      return ( mka ) ;
2150
    }
2151
 
2152
    case mult_tag :
2153
    case offset_mult_tag : {
2154
    /* Multiplication */
2155
    bool sgned = issgn ( sh ( e ) ) ;
2156
    if(optop(e)) {
2157
      mka.regmove = do_mul_comm_op ( e, sp, dest, sgned ) ;
2158
      return mka;
2159
    }
2160
#if 0
2161
    if(error_treatment_is_trap(e)) {
2162
      int new_lab = new_label();
2163
      mka.regmove = do_mul_comm_op ( e, sp, dest, sgned ) ;
2164
      uncond_ins(i_bvc,new_lab);
2165
      do_exception(f_overflow);
2166
      set_label(new_lab);
2167
      return mka;
2168
    }
2169
#endif          
2170
    if(!optop(e) /*&& !error_treatment_is_trap(e)*/ /* && is_signed(sh(e))*/ ){
2171
     where newdest;
2172
       ans aa;
2173
       int res_reg = getreg(sp.fixed);
2174
       space nsp;
2175
       newdest.ashwhere = dest.ashwhere;
2176
       newdest.answhere.d = inreg;
2177
       newdest.ashwhere.ashsize = 32;
2178
       newdest.ashwhere.ashalign = 32;
2179
       newdest.answhere.val.regans = res_reg;
2180
       nsp = guardreg(res_reg,sp);
2181
       mka.regmove = do_mul_comm_op ( e, sp, newdest, sgned );
2182
 
2183
      switch(name(sh(e))){
2184
	case ulonghd :
2185
	case slonghd :{
2186
	  check_integer_multiply_exception(e,sp,res_reg);
2187
	  break;
2188
	}
2189
	case swordhd : {
2190
	  if(error_treatment_is_trap(e)){
2191
	    test_signed_and_trap(res_reg,-0x8000,0x7fff,f_overflow);
2192
	  }
2193
	  else{
2194
	    test_signed(res_reg,-0x8000,0x7fff,no(son(pt(e))));
2195
	  }
2196
	  break;
2197
	}
2198
	case uwordhd : {
2199
	  if(error_treatment_is_trap(e)){
2200
	    test_unsigned_and_trap(res_reg,0xffff,f_overflow);
2201
	  }
2202
	  else{
2203
	    test_unsigned(res_reg,0xffff,no(son(pt(e))));
2204
	  }
2205
	  break;
2206
	}
2207
	case scharhd : {
2208
	  if(error_treatment_is_trap(e)){
2209
	    test_signed_and_trap(res_reg,-128,127,f_overflow);
2210
	  }
2211
	  else{
2212
	    test_signed(res_reg,-128,127,no(son(pt(e))));
2213
	  }
2214
	  break;
2215
	}
2216
	case ucharhd : {
2217
	  if(error_treatment_is_trap(e)){
2218
	    test_unsigned_and_trap(res_reg,255,f_overflow);
2219
	  }
2220
	  else{
2221
	    test_unsigned(res_reg,255,no(son(pt(e))));
2222
	  }
2223
	  break;
2224
	}
2225
	default :
2226
	failer("unimplemented shape");
2227
      }	
2228
      setregalt(aa,res_reg);
2229
      mka.regmove = move(aa,dest,sp.fixed,0);
2230
    }
2231
    return ( mka ) ;
2232
    }
2233
    case fmax_tag : {
2234
    /* modelled on test code */
2235
      ins_p branch ;
2236
      exp l = son ( e ) ;
2237
      exp r = bro ( l ) ;
2238
      shape shl = sh ( l ) ;
2239
      freg a1, a2, d;
2240
      space nsp;
2241
      ans aa;
2242
 
2243
      int n = (name(e) == min_tag) ? 2 : 3; /* min -> lt, max -> ge */
2244
 
2245
    bool unsgn ;
2246
 
2247
    /*assert(name(l) != val_tag);*/ /* now in common section */
2248
 
2249
 
2250
    /* Choose branch instruction */
2251
    unsgn = ( bool ) ( name ( shl ) >= ptrhd || !issgn ( shl ) ) ;
2252
    branch = fbranches (n);
2253
 
2254
    d.fr = GETFREG(dest, sp);
2255
    nsp = guardfreg(d.fr, sp);
2256
    a1.fr = freg_operand ( l, nsp,getfreg(sp.flt) ) ;
2257
    nsp = guardfreg ( a1.fr, nsp ) ;
2258
    a2.fr = freg_operand ( r, nsp,getfreg(sp.flt)) ;
2259
    fmaxminrr_ins ( branch, a1.fr<<1, a2.fr<<1, d.fr<<1,name(sh(e))) ;
2260
 
2261
    setfregalt (aa, d);
2262
    move (aa, dest, guardfreg (d.fr, sp).fixed, 0);
2263
    mka.regmove = d.fr<<1;
2264
    return mka;
2265
 
2266
  }
2267
 
2268
 
2269
  case max_tag :
2270
  case min_tag :
2271
  case offset_max_tag : {
2272
    /* modelled on test code */
2273
    ins_p branch ;
2274
    exp l = son ( e ) ;
2275
    exp r = bro ( l ) ;
2276
    shape shl = sh ( l ) ;
2277
    int a1, a2, d;
2278
    space nsp;
2279
    ans aa;
2280
 
2281
    int n = (name(e) == min_tag) ? 2 : 3; /* min -> lt, max -> ge */
2282
 
2283
    bool unsgn ;
2284
 
2285
    /*assert(name(l) != val_tag);*/ /* now in common section */
2286
 
2287
 
2288
    /* Choose branch instruction */
2289
    unsgn = ( bool ) ( name ( shl ) >= ptrhd || !issgn ( shl ) ) ;
2290
    branch = ( unsgn ? usbranches ( n ) : sbranches ( n ) ) ;
2291
 
2292
    d = GETREG(dest, sp);
2293
    nsp = guardreg(d, sp);
2294
    a1 = reg_operand ( l, nsp ) ;
2295
 
2296
    if ( name ( r ) == val_tag ) {
2297
      int v = no ( r ) ;
2298
      maxminri_ins ( branch, a1, v,d ) ;
2299
    }
2300
    else {
2301
      nsp = guardreg ( a1, nsp ) ;
2302
      a2 = reg_operand ( r, nsp ) ;
2303
      maxminrr_ins ( branch, a1, a2, d) ;
2304
    }
2305
 
2306
    setregalt (aa, d);
2307
    move (aa, dest, guardreg (d, sp).fixed, 0);
2308
    mka.regmove = d;
2309
    return mka;
2310
 
2311
  }
2312
  case div0_tag :
2313
  case div1_tag :
2314
  case div2_tag :
2315
  case offset_div_by_int_tag :
2316
  case offset_div_tag : {
2317
    /* Division */
2318
    where newdest;
2319
    int res_reg;
2320
    ans aa;
2321
    bool sgned = issgn ( sh ( e ) ) ;
2322
    if(!optop(e) && !error_treatment_is_trap(e)){
2323
      int reg_test = reg_operand(bro(son(e)),sp);
2324
      condrr_ins(i_be,reg_test,0,no(son(pt(e))));
2325
    }
2326
    if(!optop(e) /*&& !error_treatment_is_trap(e)*/) {
2327
      space nsp;
2328
      res_reg = getreg(sp.fixed);
2329
      newdest.ashwhere = dest.ashwhere;
2330
      newdest.answhere.d = inreg;
2331
      newdest.answhere.val.regans = res_reg;
2332
      newdest.ashwhere.ashsize = 32;
2333
      newdest.ashwhere.ashalign = 32;
2334
      nsp = guardreg(res_reg,sp);
2335
    }
2336
    else newdest = dest;
2337
 
2338
    mka.regmove = do_div_op ( e, sp, newdest, sgned ) ;
2339
    if(!optop(e)){
2340
      /* note : mka.regmove should always be a valid register if the 
2341
	 division has an error treatment */
2342
      switch(name(sh(e))) {
2343
	case slonghd :
2344
	case ulonghd :{
2345
	  break;
2346
	}
2347
 
2348
	case swordhd :{
2349
	  if(error_treatment_is_trap(e)){
2350
	    test_signed_and_trap(res_reg,-0x800,0x7fff,f_overflow);
2351
	  }
2352
	  else{
2353
	    test_signed(res_reg,-0x8000,0x7fff,no(son(pt(e))));
2354
	  }
2355
	  break;
2356
	}
2357
	case uwordhd :{
2358
	  if(error_treatment_is_trap(e)){
2359
	    test_unsigned_and_trap(res_reg,0xffff,f_overflow);
2360
	  }
2361
	  else{
2362
	    test_unsigned(res_reg,0xffff,no(son(pt(e))));
2363
	  }
2364
	  break;
2365
	}
2366
	case scharhd : {
2367
	  if(error_treatment_is_trap(e)){
2368
	    test_signed_and_trap(res_reg,-128,127,f_overflow);
2369
	  }
2370
	  else{
2371
	    test_signed(res_reg,-128,127,no(son(pt(e))));
2372
	  }
2373
	  break;
2374
	}
2375
	case ucharhd : {
2376
	  if(error_treatment_is_trap(e)){
2377
	    test_unsigned_and_trap(res_reg,255,f_overflow);
2378
	  }
2379
	  else{
2380
	    test_unsigned(res_reg,255,no(son(pt(e))));
2381
	  }
2382
	  break;
2383
	}
2384
	default: failer("unimplemented shape");
2385
      }
2386
      setregalt(aa,res_reg);
2387
      mka.regmove = move(aa,dest,sp.fixed,0);
2388
    }
2389
    return ( mka ) ;
2390
  }
2391
 
2392
  case rem0_tag :
2393
  case mod_tag :
2394
  case rem2_tag : {
2395
    /* Remainder */
2396
    bool sgned = issgn ( sh ( e ) ) ;
2397
    if(!optop(e) && !error_treatment_is_trap(e)){
2398
      int reg_test = reg_operand(bro(son(e)),sp);
2399
      condrr_ins(i_be,reg_test,0,no(son(pt(e))));
2400
    }
2401
    mka.regmove = do_rem_op ( e, sp, dest, sgned ) ;
2402
    return ( mka ) ;
2403
  }
2404
 
2405
  case neg_tag :
2406
  case offset_negate_tag : {
2407
    /* Negation */
2408
    ans aa;
2409
    int rd = regfrmdest(&dest,sp);
2410
    if(!optop(e)) {
2411
      int rsrc = reg_operand(son(e),sp);
2412
      if(rd == R_G0) rd = getreg(sp.fixed);
2413
      rrr_ins(i_subcc,R_G0,rsrc,rd);
2414
    }
2415
    else {
2416
      mka.regmove = monop ( e, sp, dest, i_neg ) ;
2417
      return mka;
2418
    }
2419
    if(!optop(e) /* && !error_treatment_is_trap(e)*/) {
2420
      switch(name(sh(e))) {
2421
	case ulonghd : {
2422
	  if(!error_treatment_is_trap(e)){
2423
	    condrr_ins(i_blt,rd,R_G0,no(son(pt(e))));
2424
	  }
2425
	  else{
2426
	    int lab = new_label();
2427
	    condrr_ins(i_bge,rd,R_G0,lab);
2428
	    do_exception(f_overflow);
2429
	    set_label(lab);
2430
	  }
2431
	  break;
2432
	}
2433
	case slonghd : {
2434
	  check_integer_exception(e);
2435
	  break;
2436
	}
2437
	case uwordhd : {
2438
	  if(!error_treatment_is_trap(e)){
2439
	    condrr_ins(i_blt,rd,R_G0,no(son(pt(e))));
2440
	  }
2441
	  else{
2442
	    int lab = new_label();
2443
	    condrr_ins(i_bge,rd,R_G0,lab);
2444
	    do_exception(f_overflow);
2445
	    set_label(lab);
2446
	  }
2447
	  break;
2448
	}
2449
	case swordhd : {
2450
	  if(error_treatment_is_trap(e)){
2451
	    test_signed_and_trap(rd,-0x8000,0x7fff,f_overflow);
2452
	  }
2453
	  else{
2454
	    test_signed(rd,-0x8000,0x7fff,no(son(pt(e))));
2455
	  }
2456
	  break;
2457
	}	
2458
	case ucharhd : {
2459
	  if(!error_treatment_is_trap(e)){
2460
	    condrr_ins(i_blt,rd,R_G0,no(son(pt(e))));
2461
	  }
2462
	  else{
2463
	    int lab = new_label();
2464
	    condrr_ins(i_bge,rd,R_G0,lab);
2465
	    do_exception(f_overflow);
2466
	    set_label(lab);
2467
	  }
2468
 
2469
	  break;
2470
	}
2471
	case scharhd : {
2472
	  if(!error_treatment_is_trap(e)){
2473
	    test_signed(rd,-128,127,no(son(pt(e))));
2474
	  }
2475
	  else{
2476
	    test_signed_and_trap(rd,-128,127,f_overflow);
2477
	  }
2478
	  break;
2479
	}
2480
	default: failer("unimplemented shape");
2481
      }
2482
    }
2483
    setregalt(aa,rd);
2484
    move(aa,dest,sp.fixed,0);
2485
    return ( mka ) ;
2486
  }
2487
 
2488
  case abs_tag : {
2489
    /* Negation */
2490
    mka.regmove = absop ( e, sp, dest) ;
2491
    if(!optop(e) && is_signed(sh(e))) {
2492
      switch(name(sh(e))) {
2493
	case slonghd : {
2494
	  if(error_treatment_is_trap(e)){
2495
	    test_unsigned_and_trap(mka.regmove,0x7fffffff,f_overflow);
2496
	  }
2497
	  else {
2498
	    test_unsigned(mka.regmove,0x7fffffff,no(son(pt(e))));
2499
	  }
2500
	  break;
2501
	}
2502
	case swordhd : {
2503
	  if(error_treatment_is_trap(e)){
2504
	    test_unsigned_and_trap(mka.regmove,0x7fff,f_overflow);
2505
	  }
2506
	  else {
2507
	    test_unsigned(mka.regmove,0x7fff,no(son(pt(e))));
2508
	  }
2509
	  break;
2510
	}
2511
	case scharhd : {
2512
	  if(error_treatment_is_trap(e)){
2513
	    test_unsigned_and_trap(mka.regmove,127,f_overflow);
2514
	  }
2515
	  else {
2516
	    test_unsigned(mka.regmove,127,no(son(pt(e))));
2517
	  }
2518
	  break;
2519
	}
2520
	default: failer("unimplemented shape");
2521
      }
2522
    }
2523
    return ( mka ) ;
2524
  }
2525
 
2526
  case shl_tag :
2527
  case shr_tag : {
2528
    /* Shifts */
2529
    ans aa ;
2530
    int d ;
2531
    space nsp ;
2532
    ins_p shnat ;
2533
    exp s = son ( e ) ;
2534
    exp b = bro ( s ) ;
2535
    bool sgned = issgn ( sh ( e ) ) ;
2536
    int a = reg_operand ( s, sp ) ;
2537
    int sz = shape_size(sh(s));
2538
    int norms = 0;
2539
    bool lded = ((name(s) == name_tag && regofval(s) >=100) 
2540
		 || (name(s) == cont_tag &&
2541
		     (name(son(s))!=name_tag || regofval(son(s))>0)
2542
		     ));
2543
    bool signok = (sz == 32) || (name(s) == chvar_tag) || lded;
2544
    if ( name ( e ) == shr_tag ) {
2545
      shnat = ( sgned ? i_sra : i_srl ) ;
2546
      if(!signok) rir_ins(i_sll,a,norms=32-sz,a);
2547
    } else {
2548
      shnat = i_sll ;
2549
    }
2550
    nsp = guardreg ( a, sp ) ;
2551
    d = GETREG ( dest, nsp ) ;
2552
 
2553
 
2554
    if ( name ( b ) == val_tag ) {
2555
      /* Special cases? */
2556
      if(((no(b) + norms) >= 32) && sysV_assembler){
2557
	long shiftval = (long)no(b) + norms;
2558
	rir_ins(shnat,a,31,d);
2559
	rir_ins(shnat,d,shiftval-31,d);
2560
      }
2561
      else{
2562
	rir_ins ( shnat, a, ( long ) no ( b )+norms, d ) ;
2563
      }
2564
    } 
2565
    else {
2566
      int ar = reg_operand ( b, nsp ) ;
2567
      if(norms!=0) rir_ins(shnat,a,norms,a);
2568
      rrr_ins ( shnat, a, ar, d ) ;
2569
    }
2570
    setregalt ( aa, d ) ;
2571
    ( void ) move ( aa, dest, nsp.fixed, 1 ) ;
2572
    mka.regmove = d ;
2573
    return ( mka ) ;
2574
  }
2575
 
2576
  case fplus_tag : {
2577
    /* Floating point addition */
2578
    ins_p i = ( isdbl ( sh ( e ) ) ? i_faddd : i_fadds ) ;
2579
    if(!optop(e) && !exceptions_initialised /*&& !error_treatment_is_trap(e)*/){
2580
      exceptions_initialised = 1;
2581
      turn_off_trap_on_exceptions(sp);
2582
    }
2583
 
2584
    mka.regmove = fop ( e, sp, dest, i ) ;
2585
    if(!optop(e) /*&& !error_treatment_is_trap(e)*/){
2586
      if(mka.regmove != NOREG){
2587
	int fval = (mka.regmove>=0)? mka.regmove:-mka.regmove;
2588
	stf_ins(i_st,(fval-32)<<1,mem_temp(0));
2589
      }
2590
      check_floating_exception(e,sp,FSR_ANY);
2591
    }
2592
    return ( mka ) ;
2593
  }
2594
 
2595
  case fminus_tag : {
2596
    /* Floating point subtraction */
2597
    ins_p i = ( isdbl ( sh ( e ) ) ? i_fsubd : i_fsubs ) ;
2598
    if(!optop(e) && !exceptions_initialised/*&& !error_treatment_is_trap(e)*/){
2599
      exceptions_initialised = 1;
2600
      turn_off_trap_on_exceptions(sp);
2601
    }
2602
    mka.regmove = fop ( e, sp, dest, i ) ;
2603
    if(!optop(e) /*&& !error_treatment_is_trap(e)*/){
2604
      check_floating_exception(e,sp,FSR_ANY);
2605
      if(mka.regmove != NOREG) {
2606
	mka.regmove = (mka.regmove<0)?-mka.regmove:mka.regmove;
2607
	if(error_treatment_is_trap(e)) {
2608
	  rrf_ins((isdbl(sh(e)))?i_fcmped:i_fcmpes,(mka.regmove-32)<<1,(mka.regmove-32)<<1);
2609
	}
2610
	else {
2611
	 rrf_ins((isdbl(sh(e)))?i_fcmpd:i_fcmps,(mka.regmove-32)<<1,(mka.regmove-32)<<1);
2612
	 fbr_ins(i_fbu,no(son(pt(e))));
2613
	}
2614
      }
2615
    }
2616
    return ( mka ) ;
2617
  }
2618
 
2619
 
2620
  case fmult_tag : {
2621
    /* Floating point multiplication */
2622
    ins_p i = ( isdbl ( sh ( e ) ) ? i_fmuld : i_fmuls ) ;
2623
    if(!optop(e) && !exceptions_initialised && !error_treatment_is_trap(e)){
2624
      exceptions_initialised = 1;
2625
      turn_off_trap_on_exceptions(sp);
2626
    }
2627
    mka.regmove = fop ( e, sp, dest, i ) ;
2628
    if(!optop(e) ){
2629
      check_floating_exception(e,sp,FSR_ANY);
2630
      if(mka.regmove != NOREG) {
2631
	mka.regmove = (mka.regmove<0)?-mka.regmove:mka.regmove;
2632
	if(error_treatment_is_trap(e)) {
2633
	  rrf_ins((isdbl(sh(e)))?i_fcmped:i_fcmpes,(mka.regmove-32)<<1,(mka.regmove-32)<<1);
2634
	}
2635
	else {
2636
	 rrf_ins((isdbl(sh(e)))?i_fcmpd:i_fcmps,(mka.regmove-32)<<1,(mka.regmove-32)<<1);
2637
	 fbr_ins(i_fbu,no(son(pt(e))));
2638
	}
2639
      }
2640
 
2641
    }
2642
    return ( mka ) ;
2643
  }
2644
 
2645
  case fdiv_tag : {
2646
    /* Floating point division */
2647
    ins_p i = ( isdbl ( sh ( e ) ) ? i_fdivd : i_fdivs ) ;
2648
    if(!optop(e) && !error_treatment_is_trap(e)){
2649
      if(is_long_double(sh(e))){
2650
	where newdest;
2651
	exp zero_exp = getexp(sh(e),nilexp,1,nilexp,nilexp,0,fzero_no,
2652
			  real_tag);
2653
	setregalt(newdest.answhere,getreg(sp.fixed));
2654
	newdest.ashwhere.ashsize = newdest.ashwhere.ashalign = 32;
2655
	quad_op(bro(son(e)),zero_exp,sp,newdest,-5);  /* _Q_fne */
2656
	condrr_ins(i_be,R_O0,R_G0,no(son(pt(e))));
2657
      }
2658
      else{
2659
	int divr = freg_operand(bro(son(e)),sp,getfreg(sp.flt));
2660
	int newfr = getfreg(guardfreg(divr,sp).flt);
2661
	fconst(newfr,0,0);
2662
	rrf_ins(isdbl(sh(e))? i_fcmpd : i_fcmps,divr<<1,newfr<<1);
2663
	fbr_ins(i_fbe,no(son(pt(e))));
2664
      }
2665
      if(!exceptions_initialised) {
2666
	exceptions_initialised = 1;
2667
	turn_off_trap_on_exceptions(sp);
2668
      }
2669
    }
2670
    mka.regmove = fop ( e, sp, dest, i ) ;
2671
    if(!optop(e) /*&& !error_treatment_is_trap(e)*/){
2672
      check_floating_exception(e,sp,FSR_ANY);
2673
      if(mka.regmove != NOREG) {
2674
	mka.regmove = (mka.regmove<0)?-mka.regmove:mka.regmove;
2675
	if(error_treatment_is_trap(e)) {
2676
	  rrf_ins((isdbl(sh(e)))?i_fcmped:i_fcmpes,(mka.regmove-32)<<1,(mka.regmove-32)<<1);
2677
	}
2678
	else {
2679
	 rrf_ins((isdbl(sh(e)))?i_fcmpd:i_fcmps,(mka.regmove-32)<<1,(mka.regmove-32)<<1);
2680
	 fbr_ins(i_fbu,no(son(pt(e))));
2681
	}
2682
      }
2683
 
2684
 
2685
    }
2686
    return ( mka ) ;
2687
  }
2688
 
2689
  case fneg_tag :
2690
  case fabs_tag : {
2691
    /* Floating point monadic operations */
2692
    freg frg ;
2693
    int r1, a1 ;
2694
    bool dble ;
2695
    ins_p i ;
2696
    if(!optop(e) && !exceptions_initialised /*&& !error_treatment_is_trap(e)*/){
2697
      exceptions_initialised = 1;
2698
      turn_off_trap_on_exceptions(sp);
2699
    }
2700
 
2701
#if use_long_double
2702
    if ( name ( sh ( e ) ) == doublehd ) {
2703
      if(name(e) != fabs_tag){
2704
	quad_op ( son ( e ), nilexp, sp, dest, ( int ) name ( e ) ) ;
2705
      }
2706
      else{	/* would it be so hard to implement _Q_abs? */
2707
	where newdest;
2708
	exp zero_exp;
2709
	int no_negate = new_label();
2710
	int negate = new_label();
2711
	int endlab = new_label();
2712
	setregalt(newdest.answhere,getreg(sp.fixed));
2713
	newdest.ashwhere.ashsize = newdest.ashwhere.ashalign=32;
2714
	zero_exp = getexp(sh(e),nilexp,1,nilexp,nilexp,0,fzero_no,
2715
			  real_tag);
2716
	quad_op(son(e),zero_exp,sp,newdest,-2);
2717
	condrr_ins(i_be,R_O0,R_G0,no_negate);
2718
	set_label(negate);
2719
	quad_op(son(e),nilexp,sp,dest,fneg_tag);
2720
	uncond_ins(i_b,endlab);
2721
	set_label(no_negate);
2722
	code_here(son(e),sp,dest);
2723
	set_label(endlab);
2724
      }
2725
      return mka;
2726
    }
2727
#endif
2728
    r1 = getfreg ( sp.flt ) ;
2729
    a1 = freg_operand ( son ( e ), sp, r1 ) ;
2730
    dble = isdbl ( sh ( e ) ) ;
2731
    i = ( name ( e ) == fneg_tag ? i_fnegs : i_fabss ) ;
2732
 
2733
    switch ( discrim ( dest.answhere ) ) {
2734
      case infreg : {
2735
	frg = fregalt ( dest.answhere ) ;
2736
	rrf_ins ( i, a1 << 1, frg.fr << 1 ) ;
2737
	if ( dble && frg.fr != a1 ) {
2738
	  rrf_ins ( i_fmovs, ( a1 << 1 ) + 1,
2739
		    ( frg.fr << 1 ) + 1 ) ;
2740
	}
2741
	break ;
2742
      }
2743
      default : {
2744
	ans a ;
2745
	frg.fr = r1 ;
2746
	frg.dble = dble ;
2747
	setfregalt ( a, frg ) ;
2748
	rrf_ins ( i, a1 << 1, r1 << 1 ) ;
2749
	if ( dble && r1 != a1 ) {
2750
	  rrf_ins ( i_fmovs, ( a1 << 1 ) + 1,
2751
		    ( r1 << 1 ) + 1 ) ;
2752
	}
2753
	( void ) move ( a, dest, sp.fixed, 1 ) ;
2754
	break ;
2755
      }
2756
    }
2757
    mka.regmove = fregno ( dble, frg.fr ) ;
2758
    if ( !optop ( e ) && !error_treatment_is_trap(e)) {
2759
    }
2760
 
2761
    return ( mka ) ;
2762
  }
2763
 
2764
  case float_tag : {
2765
    /* Integer to floating point conversion */
2766
    ans aa ;
2767
    where w ;
2768
    freg frg ;
2769
    int f = GETFREG ( dest, sp ) ;
2770
 
2771
    exp in = son ( e ) ;
2772
    int from_sz = shape_size ( sh ( in ) ) ;
2773
    bool from_sgned = issgn ( sh ( in ) ) ;
2774
 
2775
    ins_p fl_ins = ( isdbl ( sh ( e ) ) ? i_fitod : i_fitos ) ;
2776
    if(!optop(e) && !exceptions_initialised && !error_treatment_is_trap(e)){
2777
      exceptions_initialised = 1;
2778
      turn_off_trap_on_exceptions(sp);
2779
    }
2780
 
2781
#if use_long_double
2782
    if ( name ( sh ( e ) ) == doublehd ) {
2783
      quad_op ( son ( e ), nilexp, sp, dest, float_tag ) ;
2784
      return ( mka ) ;
2785
    }
2786
#endif
2787
 
2788
    frg.fr = f ;
2789
    frg.dble = isdbl ( sh ( e ) ) ;
2790
 
2791
    if ( from_sz == 32 && !from_sgned ) {
2792
      /* Unsigned word to floating is tricky */
2793
      int r = reg_operand ( in, sp ) ;
2794
      int f1 = getfreg ( guardfreg ( f, sp ).flt ) ;
2795
      ins_p fadd_ins = ( isdbl ( sh ( e ) ) ? i_faddd : i_fadds ) ;
2796
 
2797
		/* Load r / 2 into f */
2798
      rir_ins ( i_srl, r, 1, R_TMP ) ;
2799
      st_ro_ins ( i_st, R_TMP, mem_temp ( 0 ) ) ;
2800
      ldf_ro_ins ( i_ld, mem_temp ( 0 ), f << 1 ) ;
2801
      rrf_ins ( fl_ins, f << 1, f << 1 ) ;
2802
 
2803
		/* Double f */
2804
      rrrf_ins ( fadd_ins, f << 1, f << 1, f << 1 ) ;
2805
 
2806
      /* Load r % 2 into f1 */
2807
      rir_ins ( i_and, r, 1, R_TMP ) ;
2808
      st_ro_ins ( i_st, R_TMP, mem_temp ( 0 ) ) ;
2809
      ldf_ro_ins ( i_ld, mem_temp ( 0 ), f1 << 1 ) ;
2810
      rrf_ins ( fl_ins, f1 << 1, f1 << 1 ) ;
2811
 
2812
		/* Add f1 to f */
2813
      rrrf_ins ( fadd_ins, f << 1, f1 << 1, f << 1 ) ;
2814
    } else if ( from_sz == 32 ) {
2815
      /* Signed word to floating is easy */
2816
      freg fint ;
2817
      fint.fr = f ;
2818
      fint.dble = 0 ;
2819
      setfregalt ( w.answhere, fint ) ;
2820
      w.ashwhere = ashof ( sh ( in ) ) ;
2821
      ( void ) code_here ( in, sp, w ) ;
2822
      rrf_ins ( fl_ins, f << 1, f << 1 ) ;
2823
    } else {
2824
      /* All others */
2825
      int r = reg_operand ( in, sp ) ;
2826
      /* store and load to move to float reg */
2827
      st_ro_ins ( i_st, r, mem_temp ( 0 ) ) ;
2828
      ldf_ro_ins ( i_ld, mem_temp ( 0 ), f << 1 ) ;
2829
      rrf_ins ( fl_ins, f << 1, f << 1 ) ;
2830
    }
2831
    if(!optop(e) && !error_treatment_is_trap(e)){
2832
      check_floating_exception(e,sp,FSR_ANY);
2833
    }
2834
 
2835
    setfregalt ( aa, frg ) ;
2836
    ( void ) move ( aa, dest, sp.fixed, 1 ) ;
2837
    mka.regmove = fregno ( frg.dble, f ) ;
2838
    return ( mka ) ;
2839
  }
2840
 
2841
  case chfl_tag : {
2842
    /* Change floating variety */
2843
    ans aa ;
2844
    where w ;
2845
    freg frg ;
2846
    bool dto = isdbl ( sh ( e ) ) ;
2847
    bool dfrom = isdbl ( sh ( son ( e ) ) ) ;
2848
    if(!optop(e) && !exceptions_initialised /*&& !error_treatment_is_trap(e)*/){
2849
      exceptions_initialised = 1;
2850
      turn_off_trap_on_exceptions(sp);
2851
    }
2852
 
2853
#if use_long_double
2854
    if ( name ( sh ( e ) ) == doublehd ) {
2855
      if ( name ( sh ( son ( e ) ) ) == doublehd ) {
2856
	/* no change in representation */
2857
	return ( make_code ( son ( e ), sp, dest, exitlab ) ) ;
2858
      }
2859
      quad_op ( son ( e ), nilexp, sp, dest, chfl_tag ) ;
2860
      return ( mka ) ;
2861
    } else if ( name ( sh ( son ( e ) ) ) == doublehd ) {
2862
      int o = ( dto ? 100 : 101 ) ;
2863
      quad_op ( son ( e ), nilexp, sp, dest, o ) ;
2864
      frg.fr = 0 ;
2865
      frg.dble = dto ;
2866
      setfregalt ( aa, frg ) ;
2867
      ( void ) move ( aa, dest, sp.fixed, 1 ) ;
2868
      if(!optop(e)){
2869
	check_floating_exception(e,sp,FSR_ANY);
2870
      }
2871
      return ( mka ) ;
2872
    }
2873
#endif
2874
 
2875
    if ( !dto && !dfrom ) {
2876
      /* no change in representation */
2877
      return ( make_code ( son ( e ), sp, dest, exitlab ) ) ;
2878
    } else {
2879
      if ( discrim ( dest.answhere ) == infreg ) {
2880
	frg = fregalt ( dest.answhere ) ;
2881
      } else {
2882
	frg.fr = getfreg ( sp.flt ) ;
2883
      }
2884
      frg.dble = dfrom ;
2885
      setfregalt ( aa, frg ) ;
2886
      w.answhere = aa ;
2887
      w.ashwhere = ashof ( sh ( son ( e ) ) ) ;
2888
      ( void ) code_here ( son ( e ), sp, w ) ;
2889
      if (!dto || !dfrom){
2890
	if(!sysV_assembler && !optop(e)) {
2891
	  outs("\t.optim\t\"-O0\"\n");/*as -O2 removes fsto[ds] ??*/
2892
	}
2893
	rrf_ins ( ( dfrom ? i_fdtos : i_fstod ), frg.fr << 1,
2894
		  frg.fr << 1 ) ;
2895
      }
2896
      frg.dble = dto ;
2897
      setfregalt ( aa, frg ) ;
2898
      ( void ) move ( aa, dest, sp.fixed, 1 ) ;
2899
      mka.regmove = fregno ( frg.dble, frg.fr ) ;
2900
      if(!optop(e)){
2901
	check_floating_exception(e,sp,FSR_ANY);
2902
      }
2903
      return ( mka ) ;
2904
    }
2905
  }
2906
 
2907
  case and_tag : {
2908
    /* Bitwise and */
2909
    mka.regmove = comm_op ( e, sp, dest, i_and ) ;
2910
    return ( mka ) ;
2911
  }
2912
 
2913
  case or_tag : {
2914
    /* Bitwise or */
2915
    mka.regmove = comm_op ( e, sp, dest, i_or ) ;
2916
    return ( mka ) ;
2917
  }
2918
 
2919
  case xor_tag : {
2920
    /* Bitwise xor */
2921
    mka.regmove = comm_op ( e, sp, dest, i_xor ) ;
2922
    return ( mka ) ;
2923
  }
2924
 
2925
  case not_tag : {
2926
    /* Bitwise not */
2927
    mka.regmove = monop ( e, sp, dest, i_not ) ;
2928
    return ( mka ) ;
2929
  }
2930
 
2931
  case locptr_tag :
2932
  {
2933
    int ptr = reg_operand(son(e),sp);
2934
    int ansr = regfrmdest(&dest,sp);
2935
    baseoff b;
2936
    ans aa;
2937
    b.base = ptr;
2938
    b.offset = -3*PTR_SZ>>3;
2939
    ld_ro_ins(i_ld,b,ansr);
2940
    setregalt(aa,ansr);
2941
    mka.regmove = move(aa,dest,guardreg(ansr,sp).fixed,0);
2942
    return mka;
2943
  }
2944
 
2945
 
2946
  case real_tag :
2947
  case string_tag : {
2948
    /* Evaluated constants */
2949
    ans aa ;
2950
    instore isa ;
2951
    bool sgned = issgn ( sh ( e ) ) ;
2952
    if ( shape_size ( sh ( e ) ) >= 32 ) sgned = 1 ;
2953
    isa = evaluated ( e, 0, 1 ) ;
2954
    setinsalt ( aa, isa ) ;
2955
    mka.regmove = move ( aa, dest, sp.fixed, sgned ) ;
2956
    return ( mka ) ;
2957
  }
2958
 
2959
  case val_tag : {
2960
    /* Load constant */
2961
    int r ;
2962
    space nsp ;
2963
    if(name(sh(e)) == u64hd || name(sh(e)) == s64hd){
2964
      instore is;
2965
      flt64 bval;
2966
      ans aa;
2967
      where newdest;
2968
      int rt = getreg(sp.fixed);
2969
      nsp = guardreg (rt, sp);
2970
      /*assert(discrim(dest.answhere) == notinreg);*/
2971
      newdest = dest;
2972
      if (discrim(dest.answhere) == notinreg &&
2973
		(is = insalt (dest.answhere), !is.adval)) {
2974
	/* destination is indirect */
2975
	int r = getreg ( nsp.fixed ) ;
2976
	ld_ins ( i_ld, is.b, r ) ;
2977
	nsp = guardreg ( r, nsp ) ;
2978
	is.adval = 1 ;
2979
	is.b.base = r ;
2980
	is.b.offset = 0 ;
2981
	setinsalt ( newdest.answhere, is ) ;
2982
      }
2983
      bval = exp_to_f64(e);
2984
      ir_ins(i_mov,bval.small,rt);
2985
      setregalt(aa,rt);
2986
      newdest.ashwhere.ashsize = newdest.ashwhere.ashalign = 32;
2987
      (void)move(aa,newdest,nsp.fixed,1);
2988
      newdest.answhere.val.instoreans.b.offset += 4;
2989
      ir_ins(i_mov,bval.big,rt);
2990
      (void)move(aa,newdest,nsp.fixed,1);
2991
      return mka;
2992
    }
2993
    else{
2994
      long v = no ( e ) ;
2995
      if ( v == 0 ) goto null_tag_case ;
2996
      if ( issgn ( sh ( e ) ) ) {
2997
	long sz = shape_size ( sh ( e ) ) ;
2998
	if ( sz == 8 ) {
2999
	  v &= 0xff ;
3000
	  v -= ( ( v & 0x80 ) << 1 ) ;
3001
	} else if ( sz == 16 ) {
3002
	  v &= 0xffff ;
3003
	  v -= ( ( v & 0x8000 ) << 1 ) ;
3004
	}
3005
      }
3006
      switch ( discrim ( dest.answhere ) ) {
3007
	case inreg : {
3008
	  r = regalt ( dest.answhere ) ;
3009
	  ir_ins ( i_mov, v, r ) ;
3010
	  break ;
3011
	}
3012
	default : {
3013
	  ans aa ;
3014
	  if ( v == 0 ) {
3015
	    r = R_G0 ;
3016
	  } else {
3017
	    r = getreg ( sp.fixed ) ;
3018
	    ir_ins ( i_mov, v, r ) ;
3019
	  }
3020
	  setregalt ( aa, r ) ;
3021
	  ( void ) move ( aa, dest, guardreg ( r, sp ).fixed, 1 ) ;
3022
	}
3023
      }
3024
      mka.regmove = r ;
3025
      return ( mka ) ;
3026
    }
3027
  }
3028
 
3029
  case null_tag :
3030
    null_tag_case : {
3031
      /* Load zero */
3032
      ans aa ;
3033
      setregalt ( aa, R_G0 ) ;
3034
      mka.regmove = move ( aa, dest, sp.fixed, 1 ) ;
3035
      return ( mka ) ;
3036
    }
3037
 
3038
  case round_tag : {
3039
    /* Floating point to integer conversion */
3040
    ans aa ;
3041
    space nsp ;
3042
    int li, ln = 1 ;
3043
    int lab1, lab2, error_lab ;
3044
    int sfr = -1, dfr, tfr, error_set = 1;
3045
    int r = GETREG ( dest, sp ) ;
3046
    int s = shape_size ( sh ( son ( e ) ) ) ;
3047
 
3048
	    /* Rounding mode : 0 = to near, 1 = up, 2 = down, 3 = to zero */
3049
    int rm = ( int ) round_number ( e ) ;
3050
    bool check_ranges = !optop(e);
3051
    if (r == R_G0) r = getreg(sp.fixed);
3052
 
3053
    if(!optop(e)) {
3054
      if (error_treatment_is_trap(e)) {
3055
	error_lab = new_label ();
3056
	error_set = 0;
3057
      }
3058
      else
3059
	error_lab = no(son(pt(e)));
3060
    }
3061
    if(!optop(e) && !exceptions_initialised /* && !error_treatment_is_trap(e) */){
3062
      exceptions_initialised = 1;
3063
      turn_off_trap_on_exceptions(sp);
3064
    }
3065
    /* Get two floating registers */
3066
    if ( use_long_double && name ( sh ( son ( e ) ) ) == doublehd ) {
3067
      quad_op ( son ( e ), nilexp, sp, dest, 100 ) ;
3068
      sfr = getfreg ( sp.flt ) ;
3069
      rrf_ins ( i_fmovd, 0, sfr << 1 ) ;
3070
    } else {
3071
      sfr = freg_operand ( son ( e ), sp, getfreg ( sp.flt ) ) ;
3072
    }
3073
    nsp = guardfreg ( sfr, sp ) ;
3074
    dfr = getfreg ( nsp.flt ) ;
3075
 
3076
    /* Apart from round signed to zero we need an extra register */
3077
    if ( rm != f_toward_zero || name ( sh ( e ) ) == ulonghd ) {
3078
      nsp = guardfreg ( dfr, nsp ) ;
3079
      tfr = getfreg ( nsp.flt ) ;
3080
      if ( s == 32 ) {
3081
	rrf_ins ( i_fstod, sfr << 1, tfr << 1 ) ;
3082
	s = 64 ;
3083
      } else {
3084
	rrf_ins ( i_fmovd, sfr << 1, tfr << 1 ) ;
3085
      }
3086
    } else {
3087
      tfr = sfr ;
3088
    }
3089
 
3090
    /*
3091
      The default rounding mode is RND_ZERO.  If we let
3092
      NOT_INT ( d ) be 0 if d is an integer and 1 otherwise
3093
      then the other rounding modes may be expressed as :
3094
 
3095
      RND_NEAR ( d ) :
3096
      d >= 0.0 ? RND_ZERO ( d + 0.5 ) : RND_ZERO ( d - 0.5 )
3097
 
3098
      RND_UP ( d ) :
3099
      d >= 0.0 ? RND_ZERO ( d ) + NOT_INT ( d ) : RND_ZERO ( d )
3100
 
3101
      RND_DOWN ( d ) :
3102
      d >= 0.0 ? RND_ZERO ( d ) : RND_ZERO ( d ) - NOT_INT ( d )
3103
      */
3104
 
3105
	    /* The non-standard modes have two cases */
3106
    if ( rm != f_toward_zero && rm != f_round_as_state) {
3107
      lab1 = new_label () ;
3108
      lab2 = new_label () ;
3109
      /* Is tfr >= 0.0? */
3110
      fconst ( dfr, 0, 0 ) ;
3111
      rrf_ins ( i_fcmpd, tfr << 1, dfr << 1 ) ;
3112
      fbr_ins ( i_fbge, lab1 ) ;
3113
      if ( rm == f_to_nearest ) {
3114
	/* For round to near add +/- 0.5 to tfr */
3115
	fconst ( dfr, -1075838976, 0 ) ;	/* -0.5 */
3116
	uncond_ins ( i_ba, lab2 ) ;
3117
	set_label ( lab1 ) ;
3118
	fconst ( dfr, 1071644672, 0 ) ;	/* 0.5 */
3119
	set_label ( lab2 ) ;
3120
	rrrf_ins ( i_faddd, tfr << 1, dfr << 1, tfr << 1 ) ;
3121
      } else {
3122
	/* The others genuinely have two cases */
3123
	ln = 2 ;
3124
      }
3125
    }
3126
 
3127
    for ( li = 0 ; li < ln ; li++ ) {
3128
      /* For each case ... */
3129
      if ( name ( sh ( e ) ) == ulonghd ) {
3130
	/* Floating to unsigned conversion is tricky */
3131
	int ulab1 = new_label () ;
3132
	int ulab2 = new_label () ;
3133
	/* Compare tfr with	2147483648.0 ... */
3134
	fconst ( dfr, 1105199104, 0 ) ;
3135
	rrf_ins ( i_fcmpd, tfr << 1, dfr << 1 ) ;
3136
	fbr_ins ( i_fbge, ulab1 ) ;
3137
	/* ... if it is smaller */
3138
 
3139
	/* if it is less than zero, and mode is towards smaller */
3140
	if(!optop(e) /* && !error_treatment_is_trap(e) */
3141
	   && (rm == f_toward_zero || rm == f_toward_smaller)) {
3142
	  if(rm == f_toward_smaller) {
3143
	    /* check .lt. -0.5 */
3144
	    fconst(dfr,-1075838976,0);
3145
	  }
3146
	  else {
3147
	    /* check .le. -1.0 */
3148
	    fconst(dfr,-1074790400,0);
3149
	  }
3150
	  rrf_ins(i_fcmpd,tfr<<1,dfr<<1);
3151
	  fbr_ins(i_fbl,error_lab);
3152
	}
3153
	rrf_ins ( i_fdtoi, tfr << 1, dfr << 1 ) ;
3154
	stf_ins ( i_st, dfr << 1, mem_temp ( 0 ) ) ;
3155
	ld_ro_ins ( i_ld, mem_temp ( 0 ), r ) ;
3156
	uncond_ins ( i_ba, ulab2 ) ;
3157
	/* ... if it is bigger */
3158
	set_label ( ulab1 ) ;
3159
	rrrf_ins ( i_fsubd, tfr << 1, dfr << 1, tfr << 1 ) ;
3160
	rrf_ins ( i_fdtoi, tfr << 1, dfr << 1 ) ;
3161
	stf_ins ( i_st, dfr << 1, mem_temp ( 0 ) ) ;
3162
	ld_ro_ins ( i_ld, mem_temp ( 0 ), r ) ;
3163
	rir_ins ( i_xor, r, ( long ) ( 0x80000000L ), r ) ;
3164
	set_label ( ulab2 ) ;
3165
      } else {
3166
	/* Floating to signed conversion is easy */
3167
	ins_p ins = ( s == 32 ? i_fstoi : i_fdtoi ) ;
3168
	if(check_ranges && (name(sh(e))==slonghd || name(sh(e))==ulonghd)) {
3169
	  check_range_and_do_error_jump(sh(e),tfr,error_lab,
3170
					guardfreg(tfr,sp),rm);
3171
	}
3172
	rrf_ins ( ins, tfr << 1, dfr << 1 ) ;
3173
	stf_ins ( i_st, dfr << 1, mem_temp ( 0 ) ) ;
3174
	ld_ro_ins ( i_ld, mem_temp ( 0 ), r ) ;
3175
 
3176
      }
3177
      /* Deal with tricky rounding modes */
3178
      if ( rm == f_toward_larger || rm == f_toward_smaller ) {
3179
	/* Pick the right branch */
3180
	if ( ( rm == f_toward_larger && li == 1 ) || 
3181
	     ( rm == f_toward_smaller && li == 0 ) ) {
3182
	  /* Get the integer into dfr */
3183
	  rrf_ins ( i_fitod, dfr << 1, dfr << 1 ) ;
3184
	  /* Is tfr equal to its integer part? */
3185
	  rrf_ins ( i_fcmpd, tfr << 1, dfr << 1 ) ;
3186
	  fbr_ins ( i_fbe, lab2 ) ;
3187
	  /* If not adjust the result by one */
3188
	  if(!optop(e) & name(sh(e)) == ulonghd) {
3189
	    /* watch out for unwanted wrap on addition */
3190
	    condri_ins(i_be,r,-1,error_lab);
3191
	  }
3192
	  rir_ins ( i_add, r, ( long ) ( rm == f_toward_larger?1:-1 ),r ) ;
3193
	}
3194
	/* Deal with the two cases */
3195
	if ( li == 0 ) {
3196
	  uncond_ins ( i_ba, lab2 ) ;
3197
	  set_label ( lab1 ) ;
3198
	} else {
3199
	  set_label ( lab2 ) ;
3200
	}
3201
      }
3202
    }
3203
 
3204
 
3205
    /* Shorten to type if needed */
3206
    switch ( name ( sh ( e ) ) ) {
3207
      case ucharhd : {
3208
	if (check_ranges){
3209
	  test_unsigned(r,255,error_lab);
3210
	}
3211
	rir_ins ( i_and, r, 0xff, r ) ;
3212
	break ;
3213
      }
3214
      case scharhd : {
3215
	if (check_ranges){
3216
	  test_signed(r,-128,127,error_lab);
3217
	}
3218
	rir_ins ( i_sll, r, 24, r ) ;
3219
	rir_ins ( i_sra, r, 24, r ) ;
3220
	break ;
3221
      }
3222
      case uwordhd : {
3223
	if(check_ranges){
3224
	  test_unsigned(r,0xffff,error_lab);
3225
	}
3226
	rir_ins ( i_and, r, 0xffff, r ) ;
3227
	break ;
3228
      }
3229
      case swordhd : {
3230
	if(check_ranges){
3231
	  test_signed(r,-0x8000,0x7fff,error_lab);
3232
	}
3233
	rir_ins ( i_sll, r, 16, r ) ;
3234
	rir_ins ( i_sra, r, 16, r ) ;
3235
	break ;
3236
      }
3237
      default: {
3238
	if(!optop(e))
3239
	  uncond_ins(i_bvs,error_lab);
3240
      }
3241
    }
3242
    if (!error_set) {
3243
      int overlab = new_label ();
3244
      uncond_ins (i_b, overlab);
3245
      set_label (error_lab);
3246
      assert (!optop(e) && error_treatment_is_trap(e));
3247
      do_exception (f_overflow);
3248
      set_label (overlab);
3249
    }
3250
    setregalt ( aa, r ) ;
3251
    mka.regmove = move ( aa, dest, sp.fixed, 1 ) ;
3252
    return ( mka ) ;
3253
  }
3254
 
3255
  case int_to_bitf_tag : {
3256
    /* Integer to bitfield conversion */
3257
    ans aa ;
3258
    space nsp ;
3259
    int size_res = shape_size ( sh ( e ) ) ;
3260
    int size_op = shape_size ( sh ( son ( e ) ) ) ;
3261
    int r = reg_operand ( son ( e ), sp ) ;
3262
    assert(0);
3263
 
3264
    if ( size_res != size_op && size_res != 32 ) {
3265
      int destr = GETREG ( dest, sp ) ;
3266
      rir_ins ( i_and, r, ( long ) ( ( 1 << size_res ) - 1 ),
3267
		destr ) ;
3268
      r = destr ;
3269
    }
3270
    /* r is appropriately truncated operand */
3271
    nsp = guardreg ( r, sp ) ;
3272
    setregalt ( aa, r ) ;
3273
    ( void ) move ( aa, dest, nsp.fixed, 0 ) ;
3274
    return ( mka ) ;
3275
  }
3276
 
3277
  case bitf_to_int_tag : {
3278
    /* Bitfield to integer conversion */
3279
    where w ;
3280
    int r = GETREG ( dest, sp ) ;
3281
    long sz = shape_size ( sh ( son ( e ) ) ) ;
3282
    bool src_sgned = issgn ( sh ( son ( e ) ) ) ;
3283
    bool target_sgned = issgn ( sh ( e ) ) ;
3284
#if 0
3285
    /* Some cases are simple moves */
3286
    if ( ( name ( son ( e ) ) == cont_tag ||
3287
	   name ( son ( e ) ) == name_tag ) &&
3288
	 ( sz == 8 || sz == 16 || sz == 32 ) ) {
3289
      where intreg ;
3290
      int olds = sh ( son ( e ) ) ;
3291
      setregalt ( intreg.answhere, r ) ;
3292
      intreg.ashwhere.ashsize = sz ;
3293
      intreg.ashwhere.ashalign = sz ;
3294
      sh ( son ( e ) ) = sh ( e ) ;
3295
      w = locate ( son ( e ), sp, sh ( e ), r ) ;
3296
      ( void ) move ( w.answhere, intreg, guard ( w, sp ).fixed,
3297
		      issgn ( sh ( e ) ) ) ;
3298
      ( void ) move ( intreg.answhere, dest, sp.fixed, 1 ) ;
3299
      sh ( son ( e ) ) = olds ;
3300
      keepreg ( e, r ) ;
3301
      return ( mka ) ;
3302
    }
3303
#endif
3304
    /* Do shift/and */
3305
    setregalt ( w.answhere, r ) ;
3306
    w.ashwhere = ashof ( sh ( son ( e ) ) ) ;
3307
    ( void ) code_here ( son ( e ), sp, w ) ;
3308
 
3309
    if ( sz != 32 && src_sgned != target_sgned ) {
3310
      /* Get correct sign */
3311
      if ( target_sgned ) {
3312
	long shift_by = ( long ) ( 32 - sz ) ;
3313
	rir_ins ( i_sll, r, shift_by, r ) ;
3314
	rir_ins ( i_sra, r, shift_by, r ) ;
3315
      } else {
3316
	long and_by = ( long ) ( ( 1 << sz ) - 1 ) ;
3317
	rir_ins ( i_and, r, and_by, r ) ;
3318
      }
3319
    }
3320
    ( void ) move ( w.answhere, dest, guardreg ( r, sp ).fixed, 0 ) ;
3321
    keepreg ( e, r ) ;
3322
    return ( mka ) ;
3323
  }
3324
  case alloca_tag : {
3325
    mka.lab = specialmake ( (checkalloc(e))?6:5,son(e), sp, dest, exitlab ) ;
3326
    return ( mka ) ;
3327
  }
3328
 
3329
  case last_local_tag: {
3330
    int r = regfrmdest(&dest,sp);
3331
    ans aa;
3332
    rir_ins(i_add,R_SP,proc_state.maxargs>>3,r);
3333
    setregalt(aa,r);
3334
    mka.regmove = move(aa,dest,sp.fixed,1);
3335
    return mka;
3336
  }
3337
 
3338
  case local_free_tag: {
3339
    exp s = son(e);
3340
    int r = reg_operand(s,sp);
3341
    exp off = bro(s);
3342
    fprintf(as_file,"!local free tag \n");
3343
    if(name(off) == val_tag){
3344
      assert(name(sh(off)) == offsethd);
3345
      rir_ins(i_add,r,((no(off)>>3)+7)&~7,r);
3346
    }
3347
    else{
3348
      int rtmp = reg_operand(off,guardreg(r,sp));
3349
      rir_ins(i_add,rtmp,7,rtmp);
3350
      rir_ins(i_and,rtmp,~7,rtmp);
3351
      rrr_ins(i_add,r,rtmp,r);
3352
    }
3353
    rir_ins(i_sub,r,proc_state.maxargs>>3,R_SP);
3354
    return mka;
3355
  }
3356
  case local_free_all_tag: {
3357
    rir_ins(i_sub,R_FP,proc_state.frame_size,R_SP);
3358
    return mka;
3359
  }
3360
 
3361
  case compound_tag : {
3362
    /* Compound values */
3363
    int r ;
3364
    space nsp ;
3365
    instore str ;
3366
    exp t = son ( e ) ;
3367
 
3368
    /* Initialse bitfield by constructing and appropriate constant */
3369
    /* Must do it this way as SPARC has no bitfield instructions. */
3370
    /* Other compounds are initialised from register values below */
3371
    if ( has_bitfield ( e ) ) {
3372
      ans aa ;
3373
      instore isa ;
3374
 
3375
      /* word-align bitfields for ease of access */
3376
      if ( dest.ashwhere.ashalign < 32 ) {
3377
	dest.ashwhere.ashalign = 32 ;
3378
      }
3379
 
3380
      /* generate constant value... */
3381
      fix_nonbitfield ( e ) ;
3382
      isa = evaluated ( e, 0, 1 ) ;
3383
      /* ... and place it in dest */
3384
      setinsalt ( aa, isa ) ;
3385
      mka.regmove = move ( aa, dest, sp.fixed, 1 ) ;
3386
      return ( mka ) ;
3387
    }
3388
 
3389
    nsp = sp ;
3390
    switch ( discrim ( dest.answhere ) ) {
3391
 
3392
      case notinreg : {
3393
	str = insalt ( dest.answhere ) ;
3394
	if ( !str.adval ) {
3395
	  int r2 = getreg ( sp.fixed ) ;
3396
	  nsp = guardreg ( r2, sp ) ;
3397
	  ld_ins ( i_ld, str.b, r2 ) ;
3398
	  str.adval = 1 ;
3399
	  str.b.base = r2 ;
3400
	  str.b.offset = 0 ;
3401
	}
3402
	for ( ; ; ) {
3403
	  where newdest ;
3404
	  instore newis ;
3405
	  newis = str ;
3406
	  newis.b.offset += no ( t ) ;
3407
 
3408
	  setinsalt ( newdest.answhere, newis ) ;
3409
	  newdest.ashwhere = ashof ( sh ( bro ( t ) ) ) ;
3410
	  ( void ) code_here ( bro ( t ), nsp, newdest ) ;
3411
	  if ( last ( bro ( t ) ) ) return ( mka ) ;
3412
	  t = bro ( bro ( t ) ) ;
3413
	}
3414
	/* NOT REACHED */
3415
      }
3416
 
3417
      case insomereg : {
3418
	int *sr = someregalt ( dest.answhere ) ;
3419
	if ( *sr != -1 ) fail ( "Illegal register" ) ;
3420
	*sr = getreg ( sp.fixed ) ;
3421
	setregalt ( dest.answhere, *sr ) ;
3422
	/* FALL THROUGH */
3423
      }
3424
 
3425
      case inreg : {
3426
	long v ;
3427
	int null_dest;
3428
	int bits_used = 0;
3429
 
3430
	( void ) code_here ( bro ( t ), sp, dest ) ;
3431
	r = regalt ( dest.answhere ) ;
3432
	null_dest = (r == R_G0);
3433
	/* if the destination is G0, then don't
3434
	   try to put out the compound, but do
3435
	   evaluate the arguments 
3436
	   Further, compounds > 32 bits into G0 are
3437
	   valid, others are NOT */
3438
 
3439
	assert ( name ( t ) == val_tag ) ;
3440
	v = no ( t ) ;
3441
	if ( v != 0 ) {
3442
	  if ( al2 ( sh ( t ) ) >= 8 ) v <<= 3 ;
3443
	  if (!null_dest)
3444
	    rir_ins ( i_sll, r, v, r ) ;
3445
	}
3446
	bits_used += (shape_size(sh(t)) + v);
3447
	assert (null_dest || bits_used <= 32);
3448
 
3449
	nsp = guardreg ( r, sp ) ;
3450
	while ( !last ( bro ( t ) ) ) {
3451
	  int z ;
3452
	  t = bro ( bro ( t ) ) ;
3453
	  assert ( name ( t ) == val_tag ) ;
3454
	  z = reg_operand ( bro ( t ), nsp ) ;
3455
	  v = no ( t ) ;
3456
	  if ( v != 0 ) {
3457
	    if ( al2 ( sh ( t ) ) >= 8 ) v <<= 3 ;
3458
	    if (!null_dest)
3459
	      rir_ins ( i_sll, z, v, z ) ;
3460
	  }
3461
	  bits_used += (shape_size(sh(t)) + v);
3462
	  assert (null_dest || bits_used <= 32);
3463
 
3464
	  if (!null_dest)
3465
	    rrr_ins ( i_or, r, z, r ) ;
3466
	}
3467
	return ( mka ) ;
3468
      }
3469
      default:
3470
      {
3471
	/* fall through to fail */
3472
      }
3473
    }
3474
    fail ( "Illegal compound expression" ) ;
3475
    return ( mka ) ;
3476
  }
3477
 
3478
  case nof_tag :
3479
  case concatnof_tag : {
3480
    /* Arrays */
3481
    space nsp ;
3482
    instore str ;
3483
    int r, disp = 0 ;
3484
    exp t = son ( e ) ;
3485
 
3486
    nsp = sp ;
3487
    switch ( discrim ( dest.answhere ) ) {
3488
      case notinreg : {
3489
	str = insalt ( dest.answhere ) ;
3490
	if ( !str.adval ) {
3491
	  int r2 = getreg ( sp.fixed ) ;
3492
	  nsp = guardreg ( r2, sp ) ;
3493
	  ld_ins ( i_ld, str.b, r2 ) ;
3494
	  str.adval = 1 ;
3495
	  str.b.base = r2 ;
3496
	  str.b.offset = 0 ;
3497
	}
3498
	for ( ; ; ) {
3499
	  where newdest ;
3500
	  instore newis ;
3501
	  if(t == nilexp) return mka;
3502
	  newis = str ;
3503
	  newis.b.offset += disp ;
3504
	  setinsalt ( newdest.answhere, newis ) ;
3505
	  newdest.ashwhere = ashof ( sh ( t ) ) ;
3506
	  ( void ) code_here ( t, nsp, newdest ) ;
3507
	  if ( last ( t ) ) return ( mka ) ;
3508
	  disp += ( rounder ( shape_size ( sh ( t ) ),
3509
			      shape_align ( sh ( bro ( t ) ) ) ) >> 3 ) ;
3510
	  t = bro ( t ) ;
3511
	}
3512
	/* NOT REACHED */
3513
      }
3514
 
3515
      case insomereg : {
3516
	int *sr = someregalt ( dest.answhere ) ;
3517
	if ( *sr != -1 ) fail ( "Illegal register" ) ;
3518
	*sr = getreg ( sp.fixed ) ;
3519
	setregalt ( dest.answhere, *sr ) ;
3520
	/* FALL THROUGH */
3521
      }
3522
 
3523
      case inreg : {
3524
	if (t == nilexp) return mka;
3525
	( void ) code_here ( t, sp, dest ) ;
3526
	r = regalt ( dest.answhere ) ;
3527
	nsp = guardreg ( r, sp ) ;
3528
	while ( !last ( t ) ) {
3529
	  int z ;
3530
	  disp += rounder ( shape_size ( sh ( t ) ),
3531
			    shape_align ( sh ( bro ( t ) ) ) ) ;
3532
	  t = bro ( t ) ;
3533
	  z = reg_operand ( t, nsp ) ;
3534
	  rir_ins ( i_sll, z, ( long ) disp, z ) ;
3535
	  rrr_ins ( i_or, r, z, r ) ;
3536
	}
3537
	return ( mka ) ;
3538
      }
3539
      default: {
3540
	/* fall through to fail */
3541
      }
3542
    }
3543
    fail ( "Illegal array expression" ) ;
3544
    return ( mka ) ;
3545
  }
3546
 
3547
  case ncopies_tag : {
3548
    space nsp ;
3549
    instore str ;
3550
    int i, r, disp = 0 ;
3551
    exp t = son ( e ) ;
3552
 
3553
    nsp = sp ;
3554
    switch ( discrim ( dest.answhere ) ) {
3555
 
3556
      case notinreg : {
3557
	str = insalt ( dest.answhere ) ;
3558
	if (!str.adval) {
3559
	  int r2 = getreg ( sp.fixed ) ;
3560
	  nsp = guardreg ( r2, sp ) ;
3561
	  ld_ins ( i_ld, str.b, r2 ) ;
3562
	  str.adval = 1 ;
3563
	  str.b.base = r2 ;
3564
	  str.b.offset = 0 ;
3565
	}
3566
	for ( i = 1 ; i <= no ( e ) ; i++ ) {
3567
	  where newdest ;
3568
	  instore newis ;
3569
	  newis = str ;
3570
	  newis.b.offset += disp ;
3571
	  setinsalt ( newdest.answhere, newis ) ;
3572
	  newdest.ashwhere = ashof ( sh ( t ) ) ;
3573
	  (void)code_here ( t, nsp, newdest ) ;
3574
	  disp += ( rounder ( shape_size ( sh ( t ) ),
3575
			      shape_align ( sh ( t ) ) ) >> 3 ) ;
3576
	}
3577
	return ( mka ) ;
3578
      }
3579
 
3580
      case insomereg : {
3581
	int *sr = someregalt ( dest.answhere ) ;
3582
	if ( *sr != -1 ) fail ( "Illegal register" ) ;
3583
	*sr = getreg ( sp.fixed ) ;
3584
	setregalt ( dest.answhere, *sr ) ;
3585
	/* FALL THROUGH */
3586
      }
3587
 
3588
      case inreg : {
3589
	( void ) code_here ( t, sp, dest ) ;
3590
	r = regalt ( dest.answhere ) ;
3591
	nsp = guardreg ( r, sp ) ;
3592
	for ( i = 1 ; i <= no ( e ) ; i++ ) {
3593
	  int z ;
3594
	  disp += rounder ( shape_size ( sh ( t ) ),
3595
			    shape_align ( sh ( t ) ) ) ;
3596
	  z = reg_operand ( t, nsp ) ;
3597
	  rir_ins ( i_sll, z, ( long ) disp, z ) ;
3598
	  rrr_ins ( i_or, r, z, r ) ;
3599
	}
3600
	return ( mka ) ;
3601
      }
3602
      default:
3603
      {
3604
	/* fall through to fail */
3605
      }
3606
    }
3607
    fail ( "Illegal array expression" ) ;
3608
    return ( mka ) ;
3609
  }
3610
 
3611
  case ident_tag : {
3612
    where placew ;
3613
    int r = NOREG ;
3614
    bool remember = 0 ;
3615
 
3616
    if ( name ( sh ( son ( e ) ) ) == ptrhd &&
3617
	 name ( son ( e ) ) != cont_tag ) {
3618
      /* we should never be identifing a pointer to bits */
3619
      if ( al1 ( sh ( son ( e ) ) ) == 1 ) {
3620
	/* ??? changed al1 to al2 here */
3621
	/* and back ???? */
3622
#if 0
3623
	fail ( "ident ref bits" ) ;
3624
#endif
3625
      }
3626
    }
3627
 
3628
    if ( props ( e ) & defer_bit ) {
3629
      /* The tag of this declaration is transparently 
3630
	 identified with its definition, without reserving 
3631
	 more space. Skip it for code generation.  It may be
3632
	 a renaming of a parameter though, so we can 
3633
	 generate a .stab. */
3634
      return ( make_code ( bro ( son ( e ) ), sp, dest, exitlab ) ) ;
3635
    }
3636
 
3637
    if ( son ( e ) == nilexp ) {
3638
      /* historical - unused tags are now removed cleanly */
3639
      placew = nowhere ;
3640
    } 
3641
    else if (name(son(e)) == caller_name_tag){
3642
      /*      int disp = ((no(son(son(e)))>>3)<<4) +R_SP;*/
3643
      exp ote = find_ote(e,no(son(e)));
3644
 
3645
      no(e) = ((no(ote)>>3)<<4) + R_SP;
3646
      placew = nowhere;
3647
    }
3648
    else {
3649
      int n = no ( e ) ;
3650
      ash a ;
3651
      a = ashof ( sh ( son ( e ) ) ) ;
3652
      /* unlike mips, do this first as params in fixed regs
3653
	 treated differently */
3654
      if ( isparam ( e ) ) {
3655
	if(name(son(e)) != formal_callee_tag){
3656
	  instore is ;
3657
	  /* bit disp of params */
3658
	  int n2 = no ( son ( e ) ) ;
3659
 
3660
	  if ( props ( son ( e ) ) > 0 ) {
3661
	    /* param in input reg given by props(son(e) ) */
3662
	    int end = rounder ( no ( son ( e ) ) +
3663
				shape_size ( sh ( son ( e ) ) ), 32 );
3664
 
3665
	    if ( no ( e ) == R_NO_REG ) {
3666
	      /* store input regs used (may be more than one) */
3667
	      int max_reg;
3668
	      bool struct_par =
3669
		!( is_floating ( name ( sh ( son ( e ) ) ) ) ||
3670
		   valregable ( sh ( son ( e ) ) ) ) ;
3671
#ifdef GENCOMPAT
3672
	      if (May_have_callees) {
3673
#else
3674
	      if(in_general_proc) {
3675
#endif
3676
		if(Has_vcallees) {
3677
		  max_reg = 4;
3678
		}
3679
		else {
3680
		  max_reg = 5;
3681
		}
3682
	      }
3683
	      else {
3684
		max_reg = 6;
3685
	      }
3686
 
3687
				/* once required !struct_par */
3688
	      is.adval = 1 ;
3689
	      is.b.base = R_FP ;
3690
	      is.b.offset = n2 + proc_state.params_offset ;
3691
	      setinsalt ( placew.answhere, is ) ;
3692
	      no ( e ) = n2 * 2 + R_FP ;
3693
	      if ( !struct_par ) {
3694
		int i = n2 ;
3695
		while ( ( i < end ) &&
3696
			( i < ( 32 * ( max_reg) ) ) ) {
3697
				/* round-down to word boundary */
3698
		  i &= ~31 ;
3699
		  is.b.offset =
3700
		    ( i + proc_state.params_offset ) >> 3 ;
3701
		  st_ins ( i_st, R_I0 + ( i >> 5 ), is.b ) ;
3702
		  i += 32 ;
3703
		}
3704
	      } 
3705
              else {
3706
				/* should use SVR4 ABI */
3707
				/* do not stack struct/unions */
3708
	      }
3709
	    } 
3710
	    else {
3711
	      /* use register */
3712
	      if ( ( props ( e ) & infreg_bits ) != 0 ) {
3713
		freg frg ;
3714
		frg.fr = ( int ) props ( son ( e ) ) ;
3715
		frg.dble = ( bool ) ( a.ashsize == 64 ) ;
3716
		setfregalt ( placew.answhere, frg ) ;
3717
	    } 
3718
            else {
3719
		setregalt ( placew.answhere,(int)props( son ( e ) ) ) ;
3720
	      }
3721
	    }
3722
 
3723
	    /* is last param a vararg in reg? */
3724
	    if ( ((!Has_no_vcallers) || isvis ( e )) && props ( son ( e ) ) != 0 &&
3725
		 /*pt ( e ) != nilexp &&*/ 
3726
		 last_param ( e ) ) {
3727
	      /* dump *all* remaining input regs to stack
3728
		 for varargs */
3729
	      int r2 = end ;
3730
	      int max_reg;
3731
#ifdef GENCOMPAT
3732
	      if (May_have_callees) {
3733
#else
3734
	      if(in_general_proc) {
3735
#endif
3736
		if(Has_vcallees) {
3737
		  max_reg = 4;
3738
		}
3739
		else {
3740
		  max_reg = 5;
3741
		}
3742
	      }
3743
	      else {
3744
		max_reg = 6;
3745
	      }
3746
	      is.adval = 1 ;
3747
	      is.b.base = R_FP ;
3748
	      while ( r2 < ( 32 * ( max_reg)) ) {
3749
		is.b.offset =
3750
		  ( r2 + proc_state.params_offset ) >> 3 ;
3751
		st_ins ( i_st, R_I0 + ( r2 >> 5 ), is.b ) ;
3752
		r2 += 32 ;
3753
	      }
3754
	    }
3755
	  } 
3756
	  else {
3757
	    /* parameter on the stack - offset given by n2 */
3758
	    is.adval = 1 ;
3759
	    is.b.base = R_FP ;
3760
	    is.b.offset = ( n2 + proc_state.params_offset ) >> 3 ;
3761
	    setinsalt ( placew.answhere, is ) ;
3762
	    no ( e ) = n2 * 2 + R_FP ;
3763
	    remember = 1 ;
3764
	  }
3765
	}
3766
	else{
3767
	  no(e) = no(son(e)) +BITS2BYTES(-proc_state.locals_offset+ 
3768
					 proc_state.frame_size)+
3769
	    (/*Has_vcallees?local_reg:*/R_FP);
3770
	  placew = nowhere;
3771
	}
3772
      }
3773
      else if ( ( props ( e ) & inreg_bits ) != 0 ) {
3774
	/* tag in some fixed pt reg */
3775
	if ( n == 0 ) {
3776
	  /* if it hasn't been already allocated into a s-reg
3777
	     allocate tag into fixed t-reg */
3778
	  long s = sp.fixed ;
3779
	  if ( props ( e ) & notparreg ) {
3780
	    s |= PARAM_TREGS ;
3781
	  }
3782
	  if ( props ( e ) & notresreg ) {
3783
	    s |= RMASK ( R_O0 ) ;
3784
	  }
3785
 	  n = getreg ( s ) ;
3786
	  no ( e ) = n ;
3787
	} 
3788
	else if ( n == R_O0 ) {
3789
	  /* use result reg optimisation */
3790
	  assert ( ! ( props ( e ) & notparreg ) ) ;
3791
	  /* just as an error check */
3792
	  ( void ) needreg ( R_O0, sp ) ;
3793
	} 
3794
	else {
3795
	  assert ( IS_SREG ( n ) ) ;
3796
	}
3797
	setregalt ( placew.answhere, n ) ;
3798
      } 
3799
      else if ( ( props ( e ) & infreg_bits ) != 0 ) {
3800
	/* tag in some float reg */
3801
	freg frg ;
3802
 
3803
	if ( n == 0 ) {
3804
	  /* if it hasn't been already allocated into a s-reg
3805
	     allocate tag into float-reg ...  */
3806
	  long s = sp.flt ;
3807
	  if ( props ( e ) & notparreg ) {
3808
	    s |= PARAM_FLT_TREGS ;	/* LINT */
3809
	  }
3810
	  n = getfreg ( s ) ;
3811
	  no ( e ) = n ;
3812
	} 
3813
	else if ( n == R_DEFER_F0 ) {
3814
	  n = R_F0 ;
3815
	  no ( e ) = R_F0 ;
3816
	} 
3817
	else {
3818
	  assert ( IS_FLT_SREG ( n ) ) ;	/* LINT */
3819
	}
3820
	frg.fr = n ;
3821
	frg.dble = ( bool ) ( a.ashsize == 64 ) ;
3822
	setfregalt ( placew.answhere, frg ) ;
3823
      } 
3824
      else {
3825
	/* allocate on stack */
3826
	instore is ;
3827
 
3828
	is.b = boff ( e ) ;
3829
	is.adval = 1 ;
3830
	setinsalt ( placew.answhere, is ) ;
3831
	remember = 1 ;
3832
      }
3833
      placew.ashwhere = a ;
3834
    }		
3835
    /* evaluate the initialisation of tag, putting it into
3836
       place allocated */
3837
    if(isparam(e) && name(son(e)) == formal_callee_tag){
3838
      exp se = son(e);
3839
      exp d = e;
3840
      if((props(d) & inanyreg)!=0){
3841
	ans a;
3842
	instore is;
3843
	is.b.base = R_FP;
3844
	is.b.offset = (no(e)-callee_size)>>3;
3845
	is.adval = 0;
3846
	setinsalt(a,is);
3847
	(void)move(a,placew,sp.fixed,is_signed(sh(se)));
3848
      }
3849
    }
3850
    else
3851
      r = code_here ( son ( e ), sp, placew ) ;
3852
 
3853
    if ( remember && r != NOREG ) {
3854
      /* if it was temporarily in a register, track it to
3855
	 optimise future access */
3856
      exp nm = pt(e);
3857
      while (nm) {	/* find a name_tag of correct shape */
3858
#ifdef NEWDIAGS
3859
	if (isdiaginfo(nm))
3860
	  ;
3861
	else
3862
#endif
3863
	if ( isvar ( e ) && name(sh(nm)) == ptrhd && 
3864
		al1(sh(nm)) == shape_align(sh(son(e)))) {
3865
	  keepcont ( nm, r ) ;
3866
	  break;
3867
	} 
3868
	else
3869
	if ( !isvar ( e ) && eq_shape (sh(nm), sh(son(e)))) {
3870
	  keepreg ( nm, r ) ;
3871
	  break;
3872
	}
3873
	nm = pt(nm);
3874
      }
3875
    }
3876
 
3877
    /* and evaluate the body of the declaration */
3878
    assert ( bro ( son ( e ) ) != e ) ;
3879
    mka = make_code ( bro ( son ( e ) ), guard ( placew, sp ),
3880
		      dest, exitlab ) ;
3881
    return ( mka ) ;
3882
  }
3883
 
3884
  case cond_tag : {
3885
    exp first = son ( e ) ;
3886
    exp second = bro ( son ( e ) ) ;
3887
    exp test ;
3888
 
3889
    if ( discrim ( dest.answhere ) == insomereg ) {
3890
      /* must make choice of register to contain answer to cond */
3891
      int *sr = someregalt ( dest.answhere ) ;
3892
      if ( *sr != -1 ) fail ( "somereg *2" ) ;
3893
      *sr = getreg ( sp.fixed ) ;
3894
      setregalt ( dest.answhere, *sr ) ;
3895
    }
3896
 
3897
    if ( name ( first ) == goto_tag && pt ( first ) == second ) {
3898
      /* first is goto second */
3899
      no ( son ( second ) ) = 0 ;
3900
      return ( make_code ( second, sp, dest, exitlab ) ) ;
3901
    }
3902
#if 0
3903
    /* not correct, see email from Mark Brandreth DRA, 22 Jan 92 */
3904
    else if ( name ( first ) == test_tag && pt ( first ) == second ) {
3905
      /* nugatory test */
3906
      no ( son ( second ) ) = 0 ;
3907
      ( void ) code_here ( son ( first ), sp, nowhere ) ;
3908
      ( void ) code_here ( bro ( son ( first ) ), sp, nowhere ) ;
3909
      return ( make_code ( second, sp, dest, exitlab ) ) ;
3910
    }
3911
#endif
3912
    else if ( name ( second ) == labst_tag &&
3913
	      name ( bro ( son ( second ) ) ) == top_tag ) {
3914
      /* second is empty */
3915
      int endl = ( exitlab == 0 ) ? new_label () : exitlab ;
3916
      no ( son ( second ) ) = endl ;
3917
      make_code ( first, sp, dest, endl ) ;
3918
      mka.lab = endl ;
3919
      return ( mka ) ;
3920
    } 
3921
    else if ( name ( second ) == labst_tag &&
3922
		name ( bro ( son ( second ) ) ) == goto_tag ) {
3923
      /* second is goto */
3924
      exp g = bro ( son ( second ) ) ;
3925
      no ( son ( second ) ) = no ( son ( pt ( g ) ) ) ;
3926
      return ( make_code ( first, sp, dest, exitlab ) ) ;
3927
    }
3928
 
3929
    if ( test = testlast ( first, second ), test != nilexp ) {
3930
      /* effectively an empty then part */
3931
      int l = ( exitlab != 0 ) ? exitlab : new_label () ;
3932
      exp orig = pt(test);	/* hold in case of extra_diags */
3933
 
3934
      /* make test jump to exitlab - see test_tag */
3935
      ptno ( test ) = -l ;
3936
      settest_number(test,  obranch(test_number(test))) ;
3937
				/* settest_number preserves the Rev bit */
3938
      no ( son ( second ) ) = new_label () ;
3939
      make_code ( first, sp, dest, l ) ;
3940
      make_code ( second, sp, dest, l ) ;
3941
      mka.lab = l ;
3942
      pt(test) = orig;	/* test no longer used, so restore for extra_diags */
3943
      return ( mka ) ;
3944
    } 
3945
    else {
3946
      int fl ;
3947
      no ( son ( second ) ) = new_label () ;
3948
      fl = make_code ( first, sp, dest, exitlab ).lab ;
3949
      {
3950
	int l = ( fl != 0 ) ? fl :
3951
	  ( ( exitlab != 0 ) ? exitlab : new_label () ) ;
3952
	if(name(sh(first))!=bothd) uncond_ins ( i_b, l ) ;
3953
	clear_all () ;
3954
	make_code ( second, sp, dest, l ) ;
3955
	mka.lab = l ;
3956
	return ( mka ) ;
3957
      }
3958
    }
3959
  }
3960
 
3961
  case ass_tag :
3962
  case assvol_tag : {
3963
    exp lhs = son ( e ) ;
3964
    exp rhs = bro ( lhs ) ;
3965
    where assdest ;
3966
    space nsp ;
3967
    int contreg = NOREG ;
3968
    int hdrhs = ( int ) name ( sh ( rhs ) ) ;
3969
    bool is_float = ( bool ) is_floating ( hdrhs ) ;
3970
#if use_long_double
3971
    if ( hdrhs == doublehd ) is_float = 0 ;
3972
#endif
3973
 
3974
    /* lose chvar_tag on rhs if no res, remember to invalidate reg */
3975
    /* remove name ( e ) == ass_tag tests now assbits_tag has gone */
3976
 
3977
    if ( name ( e ) == assvol_tag ) {
3978
      /* Assign to volatile location.  Disable register location
3979
	 tracing.  Disable peephole optimisation (not possible
3980
	 on SunOS 4.1.1 ) */
3981
      clear_all () ;
3982
      setvolatile () ;
3983
    }
3984
 
3985
    if ( name ( e ) == ass_tag &&
3986
	 ((name(rhs)==apply_tag || name(rhs)==apply_general_tag) 
3987
	  || is_muldivrem_call ( rhs ) ) &&
3988
	 ( ( is_float ) || valregable ( sh ( rhs ) ) ) ) {
3989
      where apply_res ;
3990
 
3991
      /* set up apply_res */
3992
      if ( is_float ) {
3993
	freg frg ;
3994
	frg.fr = 0 ;
3995
	frg.dble = ( bool ) ( hdrhs != shrealhd ) ;
3996
	setfregalt ( apply_res.answhere, frg ) ;
3997
      } 
3998
      else {
3999
	setregalt ( apply_res.answhere, R_O0 ) ;
4000
      }
4001
      apply_res.ashwhere = ashof ( sh ( rhs ) ) ;
4002
 
4003
      ( void ) code_here ( rhs, sp, apply_res ) ;
4004
      nsp = guard ( apply_res, sp ) ;
4005
 
4006
      assdest = locate ( lhs, nsp, sh ( rhs ), 0 ) ;
4007
      ( void ) move ( apply_res.answhere, assdest, nsp.fixed, 1 ) ;
4008
      ( void ) move ( apply_res.answhere, dest, nsp.fixed, 1 ) ;
4009
      clear_dep_reg ( lhs ) ;
4010
      return ( mka ) ;
4011
    }
4012
 
4013
#if 1
4014
#ifndef NO_REGREG_ST
4015
    /* see if we can use [ reg + reg ] addressing for this store */
4016
    if ( name ( lhs ) == addptr_tag ) {
4017
      exp addptr_sons = son ( lhs ) ;
4018
      ash ashe ;
4019
      int ashsize ;
4020
      ashe = ashof ( sh ( rhs ) ) ;
4021
      ashsize = ( int ) ( ashe.ashsize ) ;
4022
 
4023
      if ( last ( bro ( addptr_sons ) ) &&
4024
	   ashe.ashalign == ashsize &&
4025
	   ( ashsize == 8 || ashsize == 16 ||
4026
	     ashsize == 32 || ( is_float && !param_aligned(bro(addptr_sons)) )
4027
	   ) ) {
4028
	int lhs_addptr_reg ;
4029
	int rhs_addptr_reg ;
4030
	ans aa ;
4031
 
4032
	lhs_addptr_reg = reg_operand ( addptr_sons, sp ) ;
4033
	nsp = guardreg ( lhs_addptr_reg, sp ) ;
4034
	rhs_addptr_reg = reg_operand ( bro ( addptr_sons ), nsp ) ;
4035
	nsp = guardreg ( rhs_addptr_reg, nsp ) ;
4036
 
4037
	if ( is_float ) {
4038
	  freg dfreg ;
4039
	  dfreg.fr = freg_operand ( rhs, nsp,
4040
				    getfreg ( nsp.flt ) ) ;
4041
	  dfreg.dble = ( bool ) ( ashsize == 64 ) ;
4042
 
4043
	  stf_rr_ins ( i_st_sz ( ashsize ), dfreg.fr << 1,
4044
		       lhs_addptr_reg, rhs_addptr_reg ) ;
4045
	  setfregalt ( aa, dfreg ) ;
4046
	} 
4047
        else {
4048
	  /* use dest reg if possible? */
4049
	  int assreg = reg_operand ( rhs, nsp ) ;
4050
	  st_rr_ins ( i_st_sz ( ashsize ), assreg,
4051
		      lhs_addptr_reg, rhs_addptr_reg ) ;
4052
	  setregalt ( aa, assreg ) ;
4053
	}
4054
 
4055
	( void ) move ( aa, dest, sp.fixed, 1 ) ; /* nsp.fixed? */
4056
	clear_dep_reg ( lhs ) ;
4057
	return ( mka ) ;
4058
      }
4059
    }
4060
#endif
4061
#endif
4062
    assdest = locate ( lhs, sp, sh ( rhs ), 0 ) ;
4063
    nsp = guard ( assdest, sp ) ;
4064
 
4065
    if ( assdest.ashwhere.ashalign == 1 ) {
4066
      /* assignment of a bitfield, get address in proper form */
4067
      instore is ;
4068
      instore_bits isb;
4069
 
4070
      switch ( discrim ( assdest.answhere ) ) {
4071
 
4072
	case inreg : {
4073
	  isb.b.base = regalt ( assdest.answhere ) ;
4074
	  isb.b.offset_bits = 0 ;
4075
	  isb.adval = 1 ;
4076
	  break ;
4077
	}
4078
 
4079
	case notinreg : {
4080
	  is = insalt ( assdest.answhere ) ;
4081
	  if ( !is.adval ) {
4082
	    int r = getreg ( nsp.fixed ) ;
4083
	    ld_ins ( i_ld, is.b, r ) ;
4084
	    nsp = guardreg ( r, nsp ) ;
4085
	    isb.adval = 1 ;
4086
	    isb.b.base = r ;
4087
	    isb.b.offset_bits = 0 ;
4088
	  } else {
4089
	    isb.adval = is.adval;
4090
	    isb.b.base = is.b.base;
4091
	    isb.b.offset_bits = BYTES2BITS(is.b.offset) ;
4092
	  }
4093
	  break ;
4094
	}
4095
#if 0
4096
	case bitad : {
4097
	  isb = bitadalt ( assdest.answhere ) ;
4098
	  break ;
4099
	}
4100
#endif
4101
	default : {
4102
	  fail ( "wrong assbits" ) ;
4103
	  break ;
4104
	}
4105
      }
4106
#if 0
4107
      setbitadalt ( assdest.answhere, isb ) ;
4108
#endif
4109
    } else if ( name ( e ) == ass_tag &&
4110
		discrim ( assdest.answhere ) == notinreg ) {
4111
      instore is ;
4112
      is = insalt ( assdest.answhere ) ;
4113
      if ( !is.adval ) {
4114
	/* this is an indirect assignment, so make it direct
4115
	   by loading pointer into reg (and remember it) */
4116
	int r = getreg ( nsp.fixed ) ;
4117
	ld_ins ( i_ld, is.b, r ) ;
4118
	nsp = guardreg ( r, nsp ) ;
4119
	is.adval = 1 ;
4120
	is.b.base = r ;
4121
	is.b.offset = 0 ;
4122
	setinsalt ( assdest.answhere, is ) ;
4123
	keepexp ( lhs, assdest.answhere ) ;
4124
      }
4125
    }
4126
 
4127
#if 1
4128
    if ( name ( e ) == ass_tag && is_float &&
4129
	 discrim ( assdest.answhere ) == notinreg ) {
4130
      /* Ensure floating point values assigned using floating
4131
	 point regs so floating point reg tracking works better.
4132
	 move () uses fixed regs for mem to mem, so must pre-load
4133
	 to floating point reg */
4134
      int f = freg_operand ( rhs, nsp, getfreg ( nsp.flt ) ) ;
4135
      freg frg ;
4136
      ans aa ;
4137
 
4138
      frg.fr = f ;
4139
      frg.dble = ( bool ) ( hdrhs != shrealhd ) ;
4140
      setfregalt ( aa, frg ) ;
4141
 
4142
      nsp = guardfreg ( f, nsp ) ;
4143
      ( void ) move ( aa, assdest, nsp.fixed, 1 ) ;
4144
      ( void ) move ( aa, dest, nsp.fixed, 1 ) ;
4145
 
4146
      clear_dep_reg ( lhs ) ;
4147
      return ( mka ) ;
4148
    }
4149
#endif
4150
 
4151
    /* evaluate source into assignment destination .... */
4152
    contreg = code_here ( rhs, guard(assdest,nsp), assdest ) ;
4153
 
4154
    /* ... and move it into dest - could use assignment as value */
4155
 
4156
    switch ( discrim ( assdest.answhere ) ) {
4157
 
4158
      case inreg : {
4159
	int a = regalt ( assdest.answhere ) ;
4160
	/* remember that source has been evaluated into a */
4161
	keepreg ( rhs, a ) ;
4162
	/* forget register dependencies on destination */
4163
	clear_dep_reg ( lhs ) ;
4164
	( void ) move ( assdest.answhere, dest, nsp.fixed, 1 ) ;
4165
	break ;
4166
      }
4167
 
4168
      case infreg : {
4169
	int r ;
4170
	freg frg ;
4171
	frg = fregalt ( assdest.answhere ) ;
4172
	r = frg.fr + 32 ;
4173
	if ( frg.dble ) r = -r ;
4174
	/* remember that source has been evaluated into a */
4175
	keepreg ( rhs, r ) ;
4176
	/* forget register dependencies on destination */
4177
	clear_dep_reg ( lhs ) ;
4178
	( void ) move ( assdest.answhere, dest, nsp.fixed, 1 ) ;
4179
	break ;
4180
      }
4181
 
4182
      case notinreg :
4183
#if 0
4184
      case bitad : {
4185
	if ( contreg != NOREG && name ( e ) == ass_tag ) {
4186
	  ans aa ;
4187
	  space nnsp ;
4188
 
4189
	  if ( contreg > 0 && contreg < 31 ) {
4190
	    setregalt ( aa, contreg ) ;
4191
	    nnsp = guardreg ( contreg, sp ) ;
4192
	  } else {
4193
	    freg frg ;
4194
	    frg.fr = ABS_OF ( contreg ) - 32 ;
4195
	    frg.dble = ( bool ) ( contreg < 0 ) ;
4196
	    nnsp = nsp ;
4197
	    setfregalt ( aa, frg ) ;
4198
	  }
4199
	  ( void ) move ( aa, dest, nnsp.fixed, 1 ) ;
4200
	  /* forget register dependencies on destination */
4201
	  clear_dep_reg ( lhs ) ;
4202
	  /* remember that dest contains source, provided
4203
	     that it is not dependent on it */
4204
	  if ( name ( lhs ) == name_tag ) {
4205
	    exp dc = son ( lhs ) ;
4206
	    if ( son ( dc ) != nilexp ) dc = son ( dc ) ;
4207
	    if ( shape_size ( sh ( dc ) ) ==
4208
		 shape_size ( sh ( rhs ) ) ) {
4209
	      keepcont ( lhs, contreg ) ;
4210
	    }
4211
	  } else if ( !dependson ( lhs, 0, lhs ) ) {
4212
	    keepcont ( lhs, contreg ) ;
4213
	  }
4214
	  return ( mka ) ;
4215
	}
4216
	/* forget register dependencies on destination */
4217
	clear_dep_reg ( lhs ) ;
4218
	( void ) move ( assdest.answhere, dest, nsp.fixed, 1 ) ;
4219
	break ;
4220
      }
4221
#endif
4222
      case insomereg : {
4223
	clear_dep_reg ( lhs ) ;
4224
	/* forget register dependencies on destination */
4225
	( void ) move ( assdest.answhere, dest,
4226
			guard ( assdest, sp ).fixed, 1 ) ;
4227
	break ;
4228
      }
4229
      case insomefreg:
4230
      {
4231
	fail("Insomefreg not expected here...\n");
4232
      } 
4233
    }
4234
 
4235
    if ( name ( e ) == assvol_tag ) setnovolatile () ;
4236
    return ( mka ) ;
4237
  }
4238
 
4239
  case case_tag : {
4240
    /* evaluate controlling integer into reg r */
4241
    int r = reg_operand ( son ( e ), sp ) ;
4242
    space nsp ;
4243
    mm lims ;
4244
    exp z = bro ( son ( e ) ) ;
4245
    exp zt = z ;
4246
    long n ;
4247
    long l ;
4248
    long u = 0x80000000 ;
4249
    unsigned long approx_range ; 
4250
    bool use_jump_vector ;
4251
    nsp = guardreg ( r, sp ) ;
4252
 
4253
	    /* calculate crude criterion for using jump vector or branches */
4254
    l = no ( zt ) ;
4255
    for ( n = 1 ; ; n++ ) {
4256
      if ( u + 1 != no ( zt ) && son ( zt ) != nilexp ) {
4257
	n++ ;
4258
      }
4259
      if ( last ( zt ) ) {
4260
	u = ( son ( zt ) != nilexp ) ? no ( son ( zt ) ) :
4261
	  no ( zt ) ;
4262
	break ;
4263
      }
4264
      if ( son ( zt ) != nilexp ) {
4265
	u = no ( son ( zt ) ) ;
4266
      } else {
4267
	if ( u + 1 == no ( zt ) ) u += 1 ;
4268
      }
4269
 
4270
      zt = bro ( zt ) ;
4271
    }
4272
 
4273
    /* now l is lowest controlling value, u is highest and n is
4274
	       number of cases */
4275
 
4276
    if ( u - l < 0 ) {
4277
      /* u - l overflowed into -ve, use huge */
4278
      approx_range = 0x7fffffff ;
4279
    } else {
4280
      approx_range = ( unsigned long ) ( u - l ) ;
4281
    }
4282
 
4283
    if ( approx_range < 16 ) {
4284
      /* small jump vector needed, decide on instructions
4285
	 executed only */
4286
      unsigned jump_vector_cnt = ( ( l >= 0 && l <= 4 ) ? 8 : 9 ) ;
4287
      unsigned cmp_jmp_step_cnt = 2 + ( !SIMM13_SIZE ( l ) ) +
4288
	( !SIMM13_SIZE ( u ) ) ;
4289
      /* cmp & jmp, delay slot filled plus possibly load of
4290
		   large consts */
4291
		/* assume default used as often as case, is this good? */
4292
		/* likelyhood of default against single case */
4293
      unsigned default_weight = 1 ;
4294
      unsigned total_case_test_chain_cnt =
4295
	( ( ( ( n + 1 ) * cmp_jmp_step_cnt ) * n ) / 2 ) + 1 ;
4296
      /* unused delay slot on last case */
4297
      unsigned default_test_chain_cnt =
4298
	( n * cmp_jmp_step_cnt ) + 1 ;
4299
      /* unused delay slot */
4300
      unsigned average_test_chain_cnt =
4301
	( total_case_test_chain_cnt + 
4302
	  ( default_test_chain_cnt * default_weight ) ) /
4303
	( n + default_weight ) ;
4304
      use_jump_vector = jump_vector_cnt <= average_test_chain_cnt ;
4305
    } else {
4306
      /* space-time product criterion for jump vector instead
4307
		   of tests and branches */
4308
      unsigned long range_factor = approx_range + 9 ;
4309
      unsigned long n_factor = ( ( unsigned long ) n * n ) / 2 ;
4310
      use_jump_vector = range_factor <= n_factor ;	/* LINT */
4311
    }
4312
 
4313
    if (is_signed(sh(son(e)))) {
4314
      assert ( l <= u ) ;
4315
    } else {
4316
      assert ( (unsigned long) l <= (unsigned long) u ) ;
4317
    }
4318
    assert ( n >= 0 ) ;
4319
 
4320
    if ( use_jump_vector ) {
4321
      /* use jump vector, 8/9 insts overhead */
4322
      int endlab = new_label () ;
4323
      int veclab = next_data_lab () ;
4324
      baseoff zeroveclab ;
4325
      int mr = getreg ( nsp.fixed ) ;
4326
      nsp = guardreg ( mr, sp ) ;
4327
 
4328
      zeroveclab.offset = 0 ;
4329
      zeroveclab.base = veclab ;
4330
 
4331
      if ( l >= 0 && l <= 4 ) {
4332
	/* between 0 and 4 dummy table entries used to
4333
	   avoid subtract */
4334
	condri_ins ( i_bgeu, r, ( long ) ( u + 1 ), endlab ) ;
4335
	rir_ins ( i_sll, r, 2, mr ) ;
4336
	n = 0 ;
4337
      } else {
4338
	/* subtract to index jump vector */
4339
	rir_ins ( i_sub, r, l, mr ) ;
4340
	condri_ins ( i_bgeu, mr, ( long ) ( u - l + 1 ), endlab ) ;
4341
	rir_ins ( i_sll, mr, 2, mr ) ;
4342
	n = l ;
4343
      }
4344
 
4345
      if ( PIC_code ) {
4346
	char *rn = "%g1" ;
4347
	assert ( (nsp.fixed & RMASK (R_O7)) == 0 ) ;
4348
	fprintf ( as_file, "1:\n\tcall\t2f\n" ) ;
4349
	fprintf ( as_file, "\tsethi\t%%hi(%sD%d-1b),%s\n",
4350
		  lab_prefix, veclab, rn ) ;
4351
	fprintf ( as_file, "2:\n\tor\t%s,%%lo(%sD%d-1b),%s\n",
4352
		  rn, lab_prefix, veclab, rn ) ;
4353
	rrr_ins ( i_add, R_TMP, mr, R_TMP ) ;
4354
	ld_rr_ins ( i_ld, R_O7, R_TMP, R_TMP ) ;
4355
	clear_reg(R_O7);
4356
	clear_reg(R_TMP);
4357
	fprintf ( as_file, "\tjmp\t%%o7+%s\n\tnop\n", rn ) ;
4358
      } else {
4359
	set_ins ( zeroveclab, R_TMP ) ;
4360
	ld_rr_ins ( i_ld, mr, R_TMP, R_TMP ) ;
4361
	extj_reg_ins ( i_jmp, R_TMP, -1 ) ;
4362
      }
4363
 
4364
      /* build the jump vector, can be to .text or .data on SunOS
4365
		   must be in .rodata for System V 
4366
		   but must be .text if PIC_code */
4367
      if ( sysV_assembler && !PIC_code )
4368
	 insection ( rodata_section ) ;
4369
 
4370
      outs ( "\t.align\t4\n" ) ;
4371
      outlab ( veclab ) ;
4372
      outs ( ":\n" ) ;
4373
      for ( ; ; ) {
4374
	for ( ; no ( z ) != n ; n++ ) {
4375
	  outs ( "\t.word\t" ) ;
4376
	  outs ( lab_prefix ) ;
4377
	  outn ( endlab ) ;
4378
	  if ( PIC_code ) outs ( "-1b" ) ;
4379
	  outnl () ;
4380
	}
4381
	u = ( son ( z ) == nilexp ) ? n : no ( son ( z ) ) ;
4382
	for ( ; n != u+1 ; n++ ) {	/* comparison independent of sign */
4383
	  outs ( "\t.word\t" ) ;
4384
	  outs ( lab_prefix ) ;
4385
	  outn ( no ( son ( pt ( z ) ) ) ) ;
4386
	  if ( PIC_code ) outs ( "-1b" ) ;
4387
	  outnl () ;
4388
	}
4389
	if ( last ( z ) ) break ;
4390
	z = bro ( z ) ;
4391
      }
4392
 
4393
      if ( sysV_assembler && !PIC_code )
4394
	 insection ( text_section ) ;
4395
 
4396
#ifdef NEWDWARF
4397
      lost_count_ins();
4398
#endif
4399
 
4400
      clear_all () ;
4401
      set_label ( endlab ) ;
4402
#ifdef NEWDWARF
4403
      START_BB ();
4404
#endif
4405
      return ( mka ) ;
4406
    } else
4407
    if (is_signed(sh(son(e)))) {
4408
      /* use branches - tests are ordered */
4409
      int over = 0 ;
4410
      lims = maxmin ( sh ( son ( e ) ) ) ;
4411
      for ( ; ; ) {
4412
	int lab = no ( son ( pt ( z ) ) ) ;
4413
	long l = no ( z ) ;
4414
	if ( son ( z ) == nilexp ) {
4415
	  /* only single test required */
4416
	  condri_ins ( i_be, r, l, lab ) ;
4417
	  if ( l == lims.maxi ) {
4418
	    lims.maxi -= 1 ;
4419
	  } else if ( l == lims.mini ) {
4420
	    lims.mini += 1 ;
4421
	  }
4422
	} else if ( u = no ( son ( z ) ), l > lims.mini ) {
4423
	  if ( u >= lims.maxi ) {
4424
	    /* have already tested lower */
4425
	    condri_ins ( i_bge, r, l, lab ) ;
4426
	    lims.maxi = l - 1 ;
4427
	  } else {
4428
	    if ( over == 0 ) {
4429
	      over = new_label () ;
4430
	    }
4431
	    condri_ins ( i_bl, r, l, over ) ;
4432
	    condri_ins ( i_ble, r, u, lab ) ;
4433
	    lims.mini = u + 1 ;
4434
	  }
4435
	} else if ( u < lims.maxi ) {
4436
	  /* lower is <= lower limit of shape */
4437
	  condri_ins ( i_ble, r, u, lab ) ;
4438
	  lims.mini = u + 1 ;
4439
	} else {
4440
	  /* upper is >= upper limit of shape */
4441
	  uncond_ins ( i_b, lab ) ;
4442
	}
4443
	if ( last ( z ) ) {
4444
	  if ( over != 0 ) {
4445
	    clear_all () ;
4446
	    set_label ( over ) ;
4447
#ifdef NEWDWARF
4448
	    START_BB ();
4449
#endif
4450
	  }
4451
	  return ( mka ) ;
4452
	}
4453
	z = bro ( z ) ;
4454
      }
4455
    }
4456
    else {
4457
      /* unsigned, use branches - tests are ordered */
4458
      int over = 0 ;
4459
      unsigned long maxi;
4460
      unsigned long mini;
4461
      lims = maxmin ( sh ( son ( e ) ) ) ;
4462
      maxi = (unsigned)lims.maxi;
4463
      mini = (unsigned)lims.mini;
4464
      for ( ; ; ) {
4465
	int lab = no ( son ( pt ( z ) ) ) ;
4466
	unsigned long l = no ( z ) ;
4467
	if ( son ( z ) == nilexp ) {
4468
	  /* only single test required */
4469
	  condri_ins ( i_be, r, l, lab ) ;
4470
	  if ( l == maxi ) {
4471
	    maxi -= 1 ;
4472
	  } else if ( l == mini ) {
4473
	    mini += 1 ;
4474
	  }
4475
	} else if ( u = no ( son ( z ) ), l > mini ) {
4476
	  if ( u >= maxi ) {
4477
	    /* have already tested lower */
4478
	    condri_ins ( i_bgeu, r, l, lab ) ;
4479
	    maxi = l - 1 ;
4480
	  } else {
4481
	    if ( over == 0 ) {
4482
	      over = new_label () ;
4483
	    }
4484
	    condri_ins ( i_blu, r, l, over ) ;
4485
	    condri_ins ( i_bleu, r, u, lab ) ;
4486
	    mini = u + 1 ;
4487
	  }
4488
	} else if ( u < maxi ) {
4489
	  /* lower is <= lower limit of shape */
4490
	  condri_ins ( i_bleu, r, u, lab ) ;
4491
	  mini = u + 1 ;
4492
	} else {
4493
	  /* upper is >= upper limit of shape */
4494
	  uncond_ins ( i_b, lab ) ;
4495
	}
4496
	if ( last ( z ) ) {
4497
	  if ( over != 0 ) {
4498
	    clear_all () ;
4499
	    set_label ( over ) ;
4500
#ifdef NEWDWARF
4501
	    START_BB ();
4502
#endif
4503
	  }
4504
	  return ( mka ) ;
4505
	}
4506
	z = bro ( z ) ;
4507
      }
4508
    }
4509
  }
4510
  case movecont_tag:
4511
  {
4512
    exp frome = son(e);	/* names with a trailing e to avoid keywords */
4513
    exp toe   = bro(frome);
4514
    exp nbytes= bro(toe);
4515
    int overlaps = !isnooverlap(e);
4516
 
4517
    overlaps = 1;	/* for now use memmove always */
4518
 
4519
    if (overlaps || (name(nbytes) != val_tag))
4520
      {
4521
	int param_reg = R_O0 ;	 /* next param reg to use */
4522
	space nsp;
4523
	nsp.fixed = sp.fixed;
4524
	nsp.flt = sp.flt;
4525
 
4526
	mka.lab = exitlab ;
4527
	mka.regmove = NOREG ;
4528
 
4529
	{
4530
	  /* evaluate parameters in turn */
4531
	  /* the following is needed because the two different 
4532
	     library function to be called require a different
4533
	     ordering of parameters */
4534
	  if(sysV_abi){
4535
	    nsp = guardreg(param_reg+1,nsp);
4536
	    reg_operand_here(frome,nsp,param_reg+1);
4537
	    nsp = guardreg(param_reg,nsp);
4538
	    reg_operand_here(bro(frome),nsp,param_reg);
4539
	  }
4540
	  else{
4541
	    nsp = guardreg(param_reg,nsp);
4542
	    reg_operand_here(frome,nsp,param_reg);
4543
	    nsp = guardreg(param_reg+1,nsp);
4544
	    reg_operand_here(bro(frome),nsp,param_reg+1);
4545
	  }
4546
	  nsp = guardreg(param_reg+2,nsp);
4547
	  reg_operand_here(bro(bro(frome)),nsp,param_reg+2);
4548
#if 0	       
4549
	  for ( argp=frome, arg_cnt = 0 ;
4550
	       arg_cnt < 3 ;
4551
	       arg_cnt++, argp = bro(argp) )
4552
	    {
4553
	      /* fixed point parameter in a single reg */
4554
	      nsp = guardreg ( param_reg, nsp ) ;
4555
	      reg_operand_here ( argp, nsp, param_reg ) ;
4556
	      param_reg++ ;     
4557
	    }
4558
#endif
4559
	}
4560
	extj_special_ins ( i_call, sysV_abi ? "memmove" : "_bcopy", 3);
4561
	clear_all();
4562
      }
4563
#if 0
4564
    /* IF YOU EVER COMPLETE THIS INLINE VERSION THEN FIX
4565
       needscan, muldvrem AS WELL */
4566
    else			/* inline block move in oprators.c */
4567
      {
4568
	lhsreg = reg_operand ( addptr_sons, sp ) ;
4569
	rhsreg = reg_operand ( bro ( addptr_sons ),
4570
			       guardreg ( lhsreg, sp ) ) ;
4571
      }
4572
#endif
4573
 
4574
    return mka;
4575
  }
4576
  case set_stack_limit_tag : {
4577
    int r = reg_operand(son(e),sp);
4578
    baseoff b;
4579
    b = find_tag(TDF_STACKLIM);
4580
    st_ins(i_st,r,b);
4581
    return mka;
4582
  }
4583
  case give_stack_limit_tag : {
4584
    ans aa;
4585
    baseoff b;
4586
    int r = regfrmdest(&dest,sp);
4587
    b = find_tag(TDF_STACKLIM);
4588
    ld_ins(i_ld,b,r);
4589
    setregalt(aa,r);
4590
    move(aa,dest,guardreg(r,sp).fixed,1);
4591
    return mka;
4592
  }
4593
 
4594
  case cont_tag :
4595
  case contvol_tag : {
4596
    if ( name ( e ) == contvol_tag ) {
4597
      /* Load contents of volatile location.  Disable register
4598
	 location tracing.  Disable peephole optimisation (not
4599
	 possible with SPARC assembler ) */
4600
      clear_all () ;
4601
      setvolatile () ;
4602
    }
4603
#if 1
4604
#ifndef NO_REGREG_LOADS
4605
    /* see if we can use [ reg + reg ] addressing for this load */
4606
    if ( name ( son ( e ) ) == addptr_tag ) {
4607
      exp addptr_sons = son ( son ( e ) ) ;
4608
      ash ashe ;
4609
      int ashsize ;
4610
      bool is_float = ( bool ) is_floating ( name ( sh ( e ) ) ) ;
4611
      ashe = ashof ( sh ( e ) ) ;
4612
      ashsize = ( int ) ashe.ashsize ;
4613
 
4614
      if ( last ( bro ( addptr_sons ) ) &&
4615
	   ashe.ashalign == ashsize &&
4616
	   ( ashsize == 8 || ashsize == 16 ||
4617
	     ashsize == 32 || ( is_float && !param_aligned(bro(addptr_sons)) )
4618
	   ) ) {
4619
	int lhsreg ;
4620
	int rhsreg ;
4621
	bool sgned = ( bool ) ( ( ashsize >= 32 ) ||
4622
				issgn ( sh ( e ) ) ) ;
4623
	ans aa ;
4624
 
4625
	lhsreg = reg_operand ( addptr_sons, sp ) ;
4626
	rhsreg = reg_operand ( bro ( addptr_sons ),
4627
			       guardreg ( lhsreg, sp ) ) ;
4628
 
4629
	if ( is_float ) {
4630
	  freg dfreg ;
4631
	  if ( discrim ( dest.answhere ) == infreg ) {
4632
	    dfreg = fregalt ( dest.answhere ) ;
4633
	  } 
4634
          else {
4635
	    dfreg.fr = getfreg ( sp.flt ) ;
4636
	  }
4637
	  dfreg.dble = ( bool ) ( ashsize == 64 ) ;
4638
 
4639
	  ldf_rr_ins ( i_ld_sz ( ashsize, sgned ), lhsreg,
4640
		       rhsreg, dfreg.fr << 1 ) ;
4641
	  setfregalt ( aa, dfreg ) ;
4642
	} else {
4643
	  int dreg = ( ( discrim ( dest.answhere) == inreg ) ?
4644
		       dest.answhere.val.regans :
4645
		       getreg ( sp.fixed ) ) ;
4646
	  ld_rr_ins ( i_ld_sz ( ashsize, sgned ), lhsreg,
4647
		      rhsreg, dreg ) ;
4648
	  setregalt ( aa, dreg ) ;
4649
	}
4650
 
4651
	mka.regmove = move ( aa, dest, sp.fixed, sgned ) ;
4652
	if ( name ( e ) == contvol_tag ) {
4653
	  mka.regmove = NOREG ;
4654
	  setnovolatile () ;
4655
	}
4656
	return ( mka ) ;
4657
      }
4658
    }
4659
#endif /* NO_REGREG_LOADS */
4660
#endif
4661
    /* FALL THROUGH */
4662
  }
4663
 
4664
  case name_tag :
4665
  case field_tag :
4666
  case reff_tag :
4667
  case addptr_tag :
4668
  case subptr_tag : {
4669
    where w ;
4670
    bool sgned ;
4671
    int dr = ( ( discrim ( dest.answhere ) == inreg ) ?
4672
	       dest.answhere.val.regans : 0 ) ;
4673
    if ( name ( e ) == contvol_tag ) {
4674
      clear_all () ;
4675
      setvolatile () ;
4676
    }
4677
    /* address of arg */
4678
    w = locate ( e, sp, sh ( e ), dr ) ;
4679
    sgned = ( bool ) ( ( ( w.ashwhere.ashsize >= 32 ) ||
4680
			 ( issgn ( sh ( e ) )  ? 1 : 0 ) ) ) ;
4681
    /* load real into float reg, move uses fixed reg */
4682
    mka.regmove = move ( w.answhere, dest,
4683
			 ( guard ( w, sp ) ).fixed, sgned ) ;
4684
    if ( name ( e ) == contvol_tag ) {
4685
      setnovolatile () ;
4686
      mka.regmove = NOREG ;
4687
    }
4688
    return ( mka ) ;
4689
  }
4690
  case current_env_tag : {
4691
    int dreg ;
4692
    ans aa ;
4693
 
4694
    outs("\t.optim\t\"-O0\"\n");/*as -O2 replaces add to R_FP!*/
4695
    dreg = ( ( discrim ( dest.answhere ) == inreg ) ?
4696
	     regalt ( dest.answhere ) : getreg ( sp.fixed ) ) ;
4697
    if(callee_offset(e)) {
4698
      rir_ins(i_add,callee_start_reg,0,dreg);
4699
    }
4700
    else {
4701
      rir_ins ( i_add, R_FP, 0, dreg ) ; 
4702
    }
4703
    setregalt ( aa, dreg ) ;
4704
    ( void ) move ( aa, dest, guardreg ( dreg, sp ).fixed, 0 ) ;
4705
    mka.regmove = dreg;
4706
    return mka;
4707
  }
4708
  case env_offset_tag : {
4709
    baseoff b;
4710
    exp id = son(e);	/* as per tags.h, son is ident, not name */
4711
    assert (name(id) == ident_tag);
4712
    /* b = boff(id); */
4713
    b.base = R_FP;
4714
    if(name(son(id)) == formal_callee_tag) {
4715
      b.base = callee_start_reg;
4716
    }
4717
    b.offset = boff_env_offset(id);
4718
    /*assert(b.base == R_FP);*/	/* if not then can't index from current_env */
4719
 
4720
    /* next part is lifted from val_tag code */
4721
    {
4722
      int r ;
4723
      long v = b.offset ;
4724
 
4725
      switch ( discrim ( dest.answhere ) ) {
4726
	case inreg : {
4727
	  r = regalt ( dest.answhere ) ;
4728
	  ir_ins ( i_mov, v, r ) ;
4729
	  break ;
4730
	}
4731
	default : {
4732
	  ans aa ;
4733
	  if ( v == 0 ) {
4734
	    r = R_G0 ;
4735
	  } else {
4736
	    r = getreg ( sp.fixed ) ;
4737
	    ir_ins ( i_mov, v, r ) ;
4738
	  }
4739
	  setregalt ( aa, r ) ;
4740
	  ( void ) move ( aa, dest, guardreg ( r, sp ).fixed, 1 ) ;
4741
	}
4742
      }
4743
      mka.regmove = r ;
4744
      return ( mka ) ;
4745
    }
4746
  }
4747
  case long_jump_tag :  {
4748
    exp l = son ( e ) ;
4749
    exp r = bro ( l ) ;
4750
    int a1 = reg_operand ( l, sp ), a2, r_spare ;
4751
    space nsp ;
4752
 
4753
    nsp = guardreg ( a1, sp ) ;
4754
    a2 = reg_operand ( r, nsp ) ;
4755
    r_spare = getreg( guardreg(a2,nsp).fixed);
4756
#ifdef NEWDWARF
4757
    if (current_dg_info) {
4758
	current_dg_info->data.i_lj.brk = set_dw_text_label ();
4759
	current_dg_info->data.i_lj.j.k = WH_REG;
4760
	current_dg_info->data.i_lj.j.u.l = a2;
4761
    }
4762
#endif
4763
    outs("\t.optim\t\"-O0\"\n");
4764
    lngjmp(a1,a2, r_spare);
4765
    return mka;
4766
  }
4767
  case offset_pad_tag :   {
4768
    int roff = reg_operand(son(e),sp);
4769
    int rdest = regfrmdest(&dest,sp);
4770
    ans aa;
4771
    if(al2(sh(son(e))) >= al2(sh(e))){
4772
      if (al2(sh(e))!=1 || al2(sh(son(e))) ==1){
4773
	rr_ins(i_mov,roff,rdest);
4774
      }
4775
      else
4776
	rir_ins(i_sll,roff,3,rdest);
4777
    }
4778
    else{
4779
      int al = (al2(sh(son(e)))==1)?al2(sh(e)):(al2(sh(e))/8);
4780
      rir_ins(i_add,roff,al-1,rdest);
4781
      rir_ins(i_and,rdest,-al,rdest);
4782
      if(al2(sh(son(e)))==1){
4783
	rir_ins(i_sra,rdest,3,rdest);
4784
      }
4785
    }
4786
    setregalt(aa,rdest);
4787
    mka.regmove = move(aa,dest,guardreg(rdest,sp).fixed,0);
4788
    return mka;
4789
  }
4790
#ifdef trap_tag
4791
    case trap_tag : {
4792
      if (no(e) == f_overflow) {
4793
	do_exception(f_overflow);
4794
      }
4795
      else if (no(e) == f_nil_access) {
4796
	do_exception(f_nil_access);
4797
      }
4798
      else {
4799
	do_exception(f_stack_overflow);
4800
      }
4801
      return mka;
4802
    }
4803
#endif
4804
    case special_tag :{
4805
      if(no(e) == 0){
4806
	/* output a floating point operation */
4807
	int fr = getfreg(sp.flt);
4808
	fconst(fr,0,0);
4809
	rrrf_ins(i_fadds,fr<<1,fr<<1,fr<<1);
4810
      }
4811
      return mka;
4812
    }
4813
#ifdef has_asm
4814
    case asm_tag : {
4815
      if (props(e)) {
4816
	if (name(son(e)) == string_tag)
4817
	  outs (nostr(son(e)));
4818
	else
4819
	if (name(son(e)) == val_tag)
4820
	  outn (no(son(e)));
4821
	else
4822
	if (asm_in(e)) {
4823
	  exp s = son(e);
4824
	  if (name(s)==name_tag && !isvar(son(s))) {
4825
	    int r = regofval(s);
4826
	    if (r != R_NO_REG)
4827
	      out_asm_reg (r, 0);
4828
	    else
4829
	    if (r = fregofval(s), r != R_NO_REG)
4830
	      out_asm_reg (r, 1);
4831
	    else
4832
	      out_asm_boff (boff(son(s)), no(s)/8);
4833
	  }
4834
	  else
4835
	  if (name(s)==cont_tag && name(son(s))==name_tag && isvar(son(son(s)))) {
4836
	    int r = regofval(son(s));
4837
	    if (r != R_NO_REG)
4838
	      out_asm_reg (-r, 0);
4839
	    else
4840
	    if (r = fregofval(son(s)), r != R_NO_REG)
4841
	      out_asm_reg (r, 1);
4842
	    else
4843
	      out_asm_boff (boff(son(son(s))), no(son(s))/8);
4844
	  }
4845
	  else
4846
	    failer ("unsupported ASM operand");
4847
	}
4848
	else
4849
	if (asm_var(e)) {
4850
	  exp s = son(e);
4851
	  if (name(s)==name_tag && isvar(son(s))) {
4852
	    int r = regofval(s);
4853
	    if (r != R_NO_REG)
4854
	      out_asm_reg (-r, 0);
4855
	    else
4856
	    if (r = fregofval(s), r != R_NO_REG)
4857
	      out_asm_reg (r, 1);
4858
	    else
4859
	      out_asm_boff (boff(son(s)), no(s)/8);
4860
	  }
4861
	  else
4862
	    failer ("unsupported ASM operand");
4863
	}
4864
	else
4865
	  failer ("illegal asm");
4866
      }
4867
      else {
4868
	outs ("\n\t! ASM sequence start\n");
4869
        code_here ( son(e), sp, nowhere ) ;
4870
	outs ("\t! ASM sequence ends\n\n");
4871
      }
4872
      clear_all ();
4873
#ifdef NEWDWARF
4874
      lost_count_ins();
4875
#endif
4876
      return mka;
4877
    }
4878
#endif
4879
  }
4880
  /* Uncovered cases */
4881
  fail ( "TDF construct not done yet in make_code" ) ;
4882
  return ( mka ) ;
4883
}
4884
 
4885
 
4886
#ifdef NEWDIAGS
4887
struct make_code_args {
4888
	exp e;
4889
	space sp;
4890
	where dest;
4891
	int exitlab;
4892
	makeans res;
4893
};
4894
 
4895
static void make_code_2 
4896
    PROTO_N ( ( args ) )
4897
    PROTO_T ( void * args )
4898
{
4899
  struct make_code_args * x = (struct make_code_args *) args;
4900
  x->res = make_code_1 (x->e, x->sp, x->dest, x->exitlab);
4901
  return;
4902
}
4903
 
4904
dg_where find_diag_res 
4905
    PROTO_N ( ( args ) )
4906
    PROTO_T ( void * args )
4907
{
4908
  struct make_code_args * x = (struct make_code_args *) args;
4909
  dg_where w;
4910
  switch (x->dest.answhere.d) {
4911
    case inreg: {
4912
      w.k = WH_REG;
4913
      w.u.l = regalt(x->dest.answhere);
4914
      break;
4915
    }
4916
    case infreg: {
4917
      w.k = WH_REG;
4918
      w.u.l = fregalt(x->dest.answhere).fr + 32;
4919
      break;
4920
    }
4921
    case insomereg: {
4922
      w.k = WH_REG;
4923
      w.u.l = *someregalt(x->dest.answhere);
4924
      break;
4925
    }
4926
    case insomefreg: {
4927
      w.k = WH_REG;
4928
      w.u.l = *somefregalt(x->dest.answhere).fr + 32;
4929
      break;
4930
    }
4931
    case notinreg: {
4932
      instore is;
4933
      is = insalt(x->dest.answhere);
4934
      w.k = (IS_FIXREG (is.b.base) ? WH_REGOFF : WH_CODELAB);
4935
      w.u.l = is.b.base;
4936
      w.o = is.b.offset;		/* is.adval ? */
4937
      break;
4938
    }
4939
    default:
4940
      fail ("unexpected diag_res dest");
4941
  }
4942
  return w;
4943
}
4944
 
4945
 
4946
makeans make_code 
4947
    PROTO_N ( ( e, sp, dest, exitlab ) )
4948
    PROTO_T ( exp e X space sp X where dest X int exitlab )
4949
{
4950
  dg_info was_current = current_dg_info;
4951
  current_dg_info = nildiag;
4952
  if (extra_diags) {
4953
    switch (name (e)) {
4954
      case apply_tag:
4955
      case apply_general_tag: {
4956
	dg_info d = dgf(e);
4957
	while (d && d->key != DGA_CALL)
4958
	  d = d->more;
4959
	if (!d) {
4960
	  d = new_dg_info (DGA_CALL);
4961
	  d->data.i_call.clnam = (char*)0;
4962
	  d->data.i_call.pos = no_short_sourcepos;
4963
	  d->data.i_call.ck = 0;
4964
	  dgf(e) = combine_diaginfo (dgf(e), d);
4965
	}
4966
	break;
4967
      }
4968
      case test_tag: {
4969
	dg_info d = dgf(e);
4970
	if (dw_doing_branch_tests)
4971
	  break;
4972
	while (d && d->key != DGA_TEST)
4973
	  d = d->more;
4974
	if (!d) {
4975
	  d = new_dg_info (DGA_TEST);
4976
	  d->data.i_tst.pos = no_short_sourcepos;
4977
	  d->data.i_tst.inv = 0;
4978
	  dgf(e) = combine_diaginfo (dgf(e), d);
4979
	}
4980
	break;
4981
      }
4982
      case goto_tag: {
4983
	short_sourcepos p;
4984
	dg_info d = dgf(e);
4985
	if (dw_doing_branch_tests)
4986
	  break;
4987
	p = no_short_sourcepos;
4988
	while (d && d->key != DGA_JUMP) {
4989
	  if (d->key == DGA_SRC)
4990
	    p = d->data.i_src.startpos;
4991
	  d = d->more;
4992
	}
4993
	if (!d) {
4994
	  d = new_dg_info (DGA_JUMP);
4995
	  d->data.i_tst.pos = p;
4996
	  dgf(e) = combine_diaginfo (dgf(e), d);
4997
	}
4998
	break;
4999
      }
5000
      case goto_lv_tag:
5001
      case return_to_label_tag:
5002
      case long_jump_tag:
5003
      case tail_call_tag: {
5004
	short_sourcepos p;
5005
	dg_info d = dgf(e);
5006
	p = no_short_sourcepos;
5007
	while (d && d->key != DGA_LJ) {
5008
	  if (d->key == DGA_SRC)
5009
	    p = d->data.i_src.startpos;
5010
	  d = d->more;
5011
	}
5012
	if (!d) {
5013
	  d = new_dg_info (DGA_LJ);
5014
	  d->data.i_lj.pos = p;
5015
	  dgf(e) = combine_diaginfo (dgf(e), d);
5016
	}
5017
	break;
5018
      }
5019
    }
5020
  }
5021
  if (dgf(e) != nildiag && name(e) != proc_tag && name(e) != general_proc_tag) {
5022
    struct make_code_args args;
5023
    current_dg_exp = args.e = e;
5024
    args.sp = sp;
5025
    args.dest = dest;
5026
    args.exitlab = exitlab;
5027
    CODE_DIAG_INFO (dgf(e), 0, &make_code_2, (void*)&args);
5028
    current_dg_info = was_current;
5029
    return args.res;
5030
  }
5031
  else {
5032
    makeans a;
5033
    a = make_code_1 (e, sp, dest, exitlab);
5034
    current_dg_info = was_current;
5035
    return a;
5036
  }
5037
}
5038
 
5039
 
5040
 
5041
static void done_arg
5042
    PROTO_N ( (args) )
5043
    PROTO_T ( void * args )
5044
{
5045
  UNUSED (args);
5046
  return;
5047
}
5048
 
5049
void diag_arg
5050
    PROTO_N ( (e, sp, dest) )
5051
    PROTO_T ( exp e X space sp X where dest )
5052
{
5053
  if (dgf(e)) {
5054
    struct make_code_args args;
5055
    current_dg_exp = args.e = e;
5056
    args.sp = sp;
5057
    args.dest = dest;
5058
    args.exitlab = 0;
5059
    CODE_DIAG_INFO (dgf(e), 0, &done_arg, (void*)&args);
5060
  }
5061
  return;
5062
}
5063
#endif