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
    Copyright (c) 1993 Open Software Foundation, Inc.
3
 
4
 
5
    All Rights Reserved
6
 
7
 
8
    Permission to use, copy, modify, and distribute this software
9
    and its documentation for any purpose and without fee is hereby
10
    granted, provided that the above copyright notice appears in all
11
    copies and that both the copyright notice and this permission
12
    notice appear in supporting documentation.
13
 
14
 
15
    OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING
16
    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17
    PARTICULAR PURPOSE.
18
 
19
 
20
    IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
21
    CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22
    LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
23
    NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
24
    WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
*/
26
 
27
/*
28
    		 Crown Copyright (c) 1997
29
 
30
    This TenDRA(r) Computer Program is subject to Copyright
31
    owned by the United Kingdom Secretary of State for Defence
32
    acting through the Defence Evaluation and Research Agency
33
    (DERA).  It is made available to Recipients with a
34
    royalty-free licence for its use, reproduction, transfer
35
    to other parties and amendment for any purpose not excluding
36
    product development provided that any such use et cetera
37
    shall be deemed to be acceptance of the following conditions:-
38
 
39
        (1) Its Recipients shall ensure that this Notice is
40
        reproduced upon any copies or amended versions of it;
41
 
42
        (2) Any amended version of it shall be clearly marked to
43
        show both the nature of and the organisation responsible
44
        for the relevant amendment or amendments;
45
 
46
        (3) Its onward transfer from a recipient to another
47
        party shall be deemed to be that party's acceptance of
48
        these conditions;
49
 
50
        (4) DERA gives no warranty or assurance as to its
51
        quality or suitability for any purpose and DERA accepts
52
        no liability whatsoever in relation to any use to which
53
        it may be put.
54
*/
55
 
56
 
57
 
58
/**********************************************************************
59
$Author: release $
60
$Date: 1998/02/04 15:48:44 $
61
$Revision: 1.2 $
62
$Log: error.c,v $
63
 * Revision 1.2  1998/02/04  15:48:44  release
64
 * Added OSF copyright message.
65
 *
66
 * Revision 1.1.1.1  1998/01/17  15:55:56  release
67
 * First version to be checked into rolling release.
68
 *
69
 * Revision 1.2  1996/10/04  16:00:25  pwe
70
 * add banners and mod for PWE ownership
71
 *
72
**********************************************************************/
73
 
74
 
75
#include "config.h"
76
#include <limits.h>
77
#include "memtdf.h"
78
#include "codegen.h"
79
#include "comment.h"
80
#include "translat.h"
81
#include "makecode.h"
82
#include "stack.h"
83
#include "instruct.h"
84
#include "externs.h"
85
#include "error.h"
86
#include "myassert.h"
87
#include "flpttypes.h"
88
#include "me_fns.h"
89
 
90
/* Labels to call the error handler */
91
/* NOTE there are three one for each ERROR_CODE */
92
/* nil_access,overflow,stack_overflow */
93
 
94
static long nil_access_lab=0;
95
static long overflow_lab=0;
96
static long stack_overflow_lab=0;
97
 
98
void init_proc_errors PROTO_S ((exp));
99
void output_error_labels PROTO_S ((void));
100
long get_nil_access_lab PROTO_S ((void));
101
long get_overflow_lab PROTO_S ((void));
102
long get_stack_overflow_lab PROTO_S ((void));
103
 
104
 
105
void test_signed PROTO_S ((int,long,long,long));
106
void test_unsigned PROTO_S ((int,long,long));
107
static long trap_label PROTO_S ((exp));
108
static void do_exception PROTO_S ((int));
109
static void call_TDFhandler PROTO_S ((void));
110
 
111
 
112
/* integer error treatments */
113
int abs_error_treatment PROTO_S ((exp,space,where));
114
int chvar_error_treatment PROTO_S ((exp,space,where));
115
void div_error_treatment PROTO_S ((int,int,exp));
116
int minus_error_treatment PROTO_S ((exp,space,where));
117
int mult_error_treatment PROTO_S ((exp,space,where));
118
int plus_error_treatment PROTO_S ((exp,space,where));
119
int neg_error_treatment PROTO_S ((exp,space,where));
120
void rem_error_treatment PROTO_S ((int,int,exp));
121
void round_error_treatment PROTO_S ((exp *));
122
 
123
/* floating error treatments */
124
void chfl_error_treatment PROTO_S ((exp,int));
125
void do_fmop_error_jump PROTO_S ((exp,int,int));
126
void do_fop_error_jump PROTO_S ((exp,int,int,int));
127
 
128
 
129
/*
130
 * init_proc_errors: initialises variables used
131
 */
132
void init_proc_errors PROTO_N ((e)) PROTO_T (exp e)
133
{
134
  /* clear the error code labels */
135
  nil_access_lab = 0;
136
  overflow_lab = 0;
137
  stack_overflow_lab = 0;
138
 
139
  if (proc_has_checkstack(e))
140
  {
141
    baseoff b;
142
    int cr = next_creg();
143
    long err_lab = get_stack_overflow_lab();
144
 
145
    b = find_tg("__TDFstacklim");
146
    ld_ins(i_l,b,R_TMP0);
147
    cmp_rr_ins(i_cmp,R_SP,R_TMP0,cr);
148
    long_bc_ins(i_blt,cr,err_lab,UNLIKELY_TO_JUMP);
149
  }
150
  return;
151
}
152
/*
153
 * output_error_labels:
154
 * Sets up the labels at the end of the proc to handle
155
 * the three error codes
156
 */
157
void output_error_labels PROTO_Z ()
158
{
159
  if (nil_access_lab != 0)
160
  {
161
    set_label(nil_access_lab);
162
    do_exception(f_nil_access);
163
  }
164
  if (overflow_lab != 0)
165
  {
166
    set_label(overflow_lab);
167
    do_exception(f_overflow);
168
  }
169
  if (stack_overflow_lab!=0)
170
  {
171
    set_label(stack_overflow_lab);
172
    rir_ins(i_a,R_SP,p_frame_size,R_SP); /* collapse stack frame */
173
    do_exception(f_stack_overflow);
174
  }
175
  return;
176
}
177
/*
178
 * get_nil_access_lab returns the label to jump to
179
 * when a nil_access error_code is created
180
 * or sets it if it is un-initialized
181
 */
182
long get_nil_access_lab PROTO_Z ()
183
{
184
  if (nil_access_lab == 0)
185
  {
186
    nil_access_lab = new_label();
187
  }
188
  return nil_access_lab;
189
}
190
/*
191
 * get_overflow_lab returns the label to jump to
192
 * when an overflow error_code is created
193
 * or sets it if it is un-initialized
194
 */
195
long get_overflow_lab PROTO_Z ()
196
{
197
  if (overflow_lab == 0)
198
  {
199
    overflow_lab = new_label();
200
  }
201
  return overflow_lab;
202
}
203
/*
204
 * get_stack_overflow_lab returns the label to jump to
205
 * when a stack_overflow error_code is created
206
 * or sets it if it is un-initialized
207
 */
208
long get_stack_overflow_lab PROTO_Z ()
209
{
210
  if (stack_overflow_lab == 0)
211
  {
212
    stack_overflow_lab = new_label();
213
  }
214
  return stack_overflow_lab;
215
}
216
/*
217
 * do_trap is called from make_code and branches to
218
 * the corresponding error label depending on which
219
 * error code needs to be invoked
220
 */
221
void do_trap PROTO_N ((e)) PROTO_T (exp e )
222
{
223
  int err_code = no(e);
224
  long err_lab;
225
 
226
  if (err_code == f_nil_access)
227
  {
228
    err_lab = get_nil_access_lab();
229
  }
230
  else if (err_code == f_overflow)
231
  {
232
    err_lab = get_overflow_lab();
233
  }
234
  else if (err_code == f_stack_overflow)
235
  {
236
    err_lab = get_stack_overflow_lab();
237
  }
238
  else
239
  {
240
    fail("do_trap::Unknown error code");
241
  }
242
  uncond_ins(i_b,err_lab);
243
  clear_all();
244
  return;
245
}
246
 
247
/*
248
 * test_signed: tests whether a register lies
249
 * between two values and
250
 * jumps to label if it does not 
251
 */
252
void test_signed PROTO_N ((r,lower,upper,lab)) 
253
    PROTO_T (int r X long lower X long upper X long lab)
254
{
255
  int creg1=next_creg();
256
  int creg2=next_creg();
257
  cmp_ri_ins(i_cmp,r,lower,creg1);
258
  long_bc_ins(i_blt,creg1,lab,UNLIKELY_TO_JUMP);
259
  cmp_ri_ins(i_cmp,r,upper,creg2);
260
  long_bc_ins(i_bgt,creg2,lab,UNLIKELY_TO_JUMP);
261
  return;
262
}
263
/*
264
 * test_unsigned: tests whether a register is greater than an unsigned number
265
 */
266
void test_unsigned PROTO_N ((r,maxval,lab)) PROTO_T (int r X long maxval X long lab)
267
{
268
  int creg=next_creg();
269
  cmp_ri_ins(i_cmpl,r,maxval,creg);
270
  long_bc_ins(i_bgt,creg,lab,UNLIKELY_TO_JUMP);
271
  return;
272
}
273
 
274
/*
275
 * trap_label: Gives a label for the destination of the error
276
 */
277
static long trap_label PROTO_N ((e)) PROTO_T (exp e)
278
{
279
  if (NO_ERROR_TREATMENT(e))
280
  {
281
    fail("No error treatment");
282
    return 0;
283
  }
284
  else if (ERROR_TREATMENT_IS_TRAP(e))
285
  {
286
    return get_overflow_lab();
287
  }
288
  else
289
  {
290
    /* Error jump to destination */
291
    return no(son(pt(e)));
292
  }
293
}
294
/* 
295
 * Generates a call to the TDFhandler for exceptions
296
 */
297
static void do_exception PROTO_N ((ex)) PROTO_T (int ex)
298
{
299
  ld_const_ins(ex,R_FIRST_PARAM);/* __TDFhandler takes as its first parameter, the error code */
300
  call_TDFhandler();
301
  return;
302
}
303
static void call_TDFhandler PROTO_Z ()
304
{
305
  baseoff b;
306
  b = find_tg("__TDFhandler");
307
  ld_ins(i_l,b,R_TMP0);
308
 
309
  b.base = R_TMP0;
310
  b.offset = 0;
311
  ld_ro_ins(i_l,b,R_TMP0);comment("Jump to error handler");
312
  /* We don't come back from calling error handler */
313
  mt_ins(i_mtctr,R_TMP0);
314
  z_ins(i_bctr);
315
  return;
316
}
317
 
318
 
319
 
320
/*****************************/
321
/*                           */
322
/* INTEGER  error treatments */
323
/*                           */
324
/*****************************/
325
 
326
/*
327
 * ABS
328
 */
329
int abs_error_treatment PROTO_N ((e,sp,dest))
330
    PROTO_T (exp e X space sp X where dest)
331
{
332
  int r = reg_operand(son(e),sp);
333
  int destr = regfrmdest(&dest,sp);
334
  long trap = trap_label(e);
335
  ans aa;
336
  int cr;
337
  space nsp;
338
  nsp = guardreg(destr,sp);
339
  switch(name(sh(e)))
340
  {
341
   case ucharhd:
342
   case uwordhd:
343
   case ulonghd:
344
    break;
345
   case scharhd:	
346
    cr = next_creg();
347
    cmp_ri_ins(i_cmp,r,0xffffff80,cr);
348
    long_bc_ins(i_beq,cr,trap,UNLIKELY_TO_JUMP);
349
    break;
350
   case swordhd:
351
    cr = next_creg();
352
    cmp_ri_ins(i_cmp,r,0xffff8000,cr);
353
    long_bc_ins(i_beq,cr,trap,UNLIKELY_TO_JUMP);
354
    break;
355
   case slonghd:
356
    cr = next_creg();
357
    cmp_ri_ins(i_cmp,r,0x80000000,cr);
358
    long_bc_ins(i_beq,cr,trap,UNLIKELY_TO_JUMP);
359
    break;
360
   default:
361
    fail("Unknown Integer shape for abs_tag\n");
362
  }
363
  rr_ins(i_abs,r,destr);
364
  setregalt(aa,destr);
365
  return move(aa,dest,nsp.fixed,1);
366
}
367
 
368
/*
369
 * CHVAR
370
 */
371
int chvar_error_treatment PROTO_N ((e,sp,dest))
372
    PROTO_T (exp e X space sp X where dest)
373
{
374
  int r = reg_operand(son(e),sp);
375
  ans aa;
376
  int new_shpe = name(sh(e));
377
  long trap = trap_label(e);
378
  bool sgned = is_signed(sh(son(e)));
379
 
380
  setregalt(aa,r);
381
  switch(new_shpe)		/* switch on the new shape */
382
  {
383
   case scharhd:
384
    {
385
      if(sgned)
386
      {
387
	test_signed(r,-128,127,trap);
388
      }
389
      else
390
      {
391
	test_unsigned(r,127,trap);
392
      }
393
      break;
394
    }
395
   case ucharhd:
396
    {
397
      test_unsigned(r,255,trap);
398
    }
399
    break;
400
   case swordhd:
401
    {
402
      if(sgned)
403
      {
404
	test_signed(r,-0x8000,0x7fff,trap);
405
      }
406
      else
407
      {
408
	test_unsigned(r,0x7fff,trap);
409
      }
410
    }
411
    break;
412
   case uwordhd:
413
    {
414
      test_unsigned(r,0xffff,trap);
415
    }
416
    break;
417
   case slonghd:
418
    if(!sgned)
419
    {
420
      test_unsigned(r,0x7fffffff,trap);
421
    }
422
    break;
423
   case ulonghd:
424
    if(sgned)
425
    {
426
      test_unsigned(r,0x7fffffff,trap);
427
    }
428
    break;
429
   default:
430
    fail("Unknown integer shape in chvar_tag");
431
  }
432
  return move(aa,dest,sp.fixed,1);
433
}
434
/*
435
 * DIV0,DIV1,DIV2
436
 */
437
void div_error_treatment PROTO_N ((l,r,e))
438
    PROTO_T (int l X int r X exp e )
439
{
440
  int creg  = next_creg();
441
  int creg2 = next_creg();
442
  int creg3 = next_creg();
443
 
444
  long trap = trap_label(e);
445
  long lab ;
446
 
447
  long minus_infinity=0;
448
 
449
  /* First test for division by zero */
450
  cmp_ri_ins(i_cmp,r,0,creg);  
451
  long_bc_ins(i_beq,creg,trap,UNLIKELY_TO_JUMP);
452
 
453
  /* Test for -(infinity)/-1 for signed*/
454
  if (is_signed(sh(e)))
455
  {
456
    lab=new_label();
457
    cmp_ri_ins(i_cmp,r,-1,creg2);
458
    bc_ins(i_bne,creg2,lab,LIKELY_TO_JUMP);
459
    switch(name(sh(e)))
460
    {
461
     case slonghd:minus_infinity = 0x80000000;break;
462
     case swordhd:minus_infinity = 0xffff8000;break;
463
     case scharhd:minus_infinity = 0xffffff80;break;
464
     default:fail("Should not get here\n");
465
    }
466
    cmp_ri_ins(i_cmp,l,minus_infinity,creg3);
467
    long_bc_ins(i_beq,creg3,trap,UNLIKELY_TO_JUMP);
468
    set_label(lab);
469
  }
470
  return;
471
}
472
 
473
 
474
 
475
/*
476
 * MINUS_TAG
477
 */
478
int minus_error_treatment PROTO_N ((e,sp,dest)) 
479
    PROTO_T (exp e X space sp X where dest)
480
{
481
  int lhs_reg=reg_operand(son(e),sp);
482
  int rhs_reg;
483
  int destr;
484
  long trap = trap_label(e);
485
  ans aa;
486
  rhs_reg=reg_operand(bro(son(e)),guardreg(lhs_reg,sp));
487
  destr=regfrmdest(&dest,sp);
488
  setregalt(aa,destr);
489
  /* Both sides evaluated lhs in lhs_reg ,rhs in rhs_reg*/
490
  switch(name(sh(e)))
491
  {
492
   case slonghd:
493
    {
494
      rrr_ins(i_sfo,rhs_reg,lhs_reg,destr);
495
      mf_ins(i_mcrxr,0);
496
      long_bc_ins(i_bgt,0,trap,UNLIKELY_TO_JUMP);
497
      break;
498
    }
499
   case ulonghd:
500
    {
501
      rrr_ins(i_sfo,rhs_reg,lhs_reg,destr);
502
      mf_ins(i_mcrxr,0);
503
      long_bc_ins(i_bne,0,trap,UNLIKELY_TO_JUMP);
504
      break;
505
    }
506
   case swordhd:
507
    {
508
      rrr_ins(i_sf,rhs_reg,lhs_reg,destr);
509
      test_signed(destr,-0x8000,0x7fff,trap);
510
      break;
511
    }
512
   case uwordhd:
513
    {
514
      rrr_ins(i_sf,rhs_reg,lhs_reg,destr);
515
      test_unsigned(destr,0xffff,trap);
516
      break;
517
    }
518
   case scharhd:
519
    {
520
      rrr_ins(i_sf,rhs_reg,lhs_reg,destr);
521
      test_signed(destr, -128, 127, trap);
522
      break;
523
    }
524
   case ucharhd:
525
    {
526
      rrr_ins(i_sf,rhs_reg,lhs_reg,destr);
527
      test_unsigned(destr, 255, trap);
528
      break;
529
    }
530
   default:
531
    fail("NOT integer in minus with o/f");
532
  }
533
  return move(aa, dest, sp.fixed, 1);
534
}
535
 
536
/*
537
 * MULT_TAG
538
 */
539
int mult_error_treatment PROTO_N ((e,sp,dest)) PROTO_T (exp e X space sp X where dest)
540
{
541
  int lhs_reg=reg_operand(son(e),sp);
542
  int rhs_reg;
543
  int destr;
544
  long trap = trap_label(e);
545
  space nsp;
546
  ans aa;
547
  nsp=guardreg(lhs_reg,sp);
548
  rhs_reg=reg_operand(bro(son(e)),nsp);
549
  nsp=guardreg(rhs_reg,nsp);
550
  destr=regfrmdest(&dest,sp);
551
  setregalt(aa,destr);
552
  /* Both sides evaluated lhs in lhs_reg,rhs in rhs_reg*/
553
  switch(name(sh(e)))
554
  {
555
   case slonghd:
556
    {
557
      rrr_ins(i_mulso,lhs_reg,rhs_reg,destr);
558
      /* This should set the SO and OV bits of XER both to 1 if there is
559
	 an overflow */
560
      mf_ins(i_mcrxr,0);
561
      long_bc_ins(i_bgt,0,trap,UNLIKELY_TO_JUMP);
562
      break;
563
    }
564
   case ulonghd:
565
    {
566
      int creg=next_creg();
567
 
568
      if(architecture==POWERPC_CODE)
569
      {
570
	/* easy since we have mulhwu */
571
	rrr_ins(i_mulhwu,lhs_reg,rhs_reg,R_TMP0);
572
      }
573
      else
574
      {
575
	int tmp_reg;
576
	space nsp;
577
	int lab   = new_label();
578
	int lab2  = new_label();
579
	int creg  = next_creg();
580
	int creg2 = next_creg();
581
	int creg3 = next_creg();
582
	nsp = guardreg(lhs_reg,sp);
583
	nsp = guardreg(rhs_reg,nsp);
584
 
585
	tmp_reg=getreg(nsp.fixed);
586
	ld_const_ins(0,tmp_reg);
587
	cmp_ri_ins(i_cmp,lhs_reg,0,creg);
588
	bc_ins(i_bgt,creg,lab,LIKELY_TO_JUMP);
589
	mov_rr_ins(lhs_reg,tmp_reg);comment(NIL);
590
	set_label(lab);
591
	cmp_ri_ins(i_cmp,rhs_reg,0,creg2);
592
	bc_ins(i_bgt,creg2,lab2,LIKELY_TO_JUMP);
593
	rrr_ins(i_a,rhs_reg,tmp_reg,tmp_reg);
594
	set_label(lab2);
595
	rir_ins(i_sl,tmp_reg,1,tmp_reg);
596
	rrr_ins(i_mul,lhs_reg,rhs_reg,R_TMP0);
597
	rrr_ins(i_a,R_TMP0,tmp_reg,tmp_reg);
598
	cmp_ri_ins(i_cmp,tmp_reg,0,creg3);
599
	long_bc_ins(i_bne,creg3,trap,UNLIKELY_TO_JUMP);
600
 
601
      }
602
 
603
      cmp_ri_ins(i_cmp,R_TMP0,0,creg);
604
      long_bc_ins(i_bne,creg,trap,UNLIKELY_TO_JUMP);
605
      rrr_ins(i_muls,lhs_reg,rhs_reg,destr);
606
      /* if the high part of the answer is non-zero branch to trap */
607
      break;
608
    }
609
   case swordhd:
610
    {
611
      rrr_ins(i_muls,lhs_reg,rhs_reg,destr);
612
      test_signed(destr,-0x8000,0x7fff,trap);
613
      break;
614
    }
615
   case uwordhd:
616
    {
617
      rrr_ins(i_muls,lhs_reg,rhs_reg,destr);
618
      test_unsigned(destr,0xffff,trap);
619
      break;
620
    }
621
   case scharhd:
622
    {
623
      rrr_ins(i_muls,lhs_reg,rhs_reg,destr);
624
      test_signed(destr, -128, 127, trap);
625
      break;
626
    }
627
   case ucharhd:
628
    {
629
      rrr_ins(i_muls,lhs_reg,rhs_reg,destr);
630
      test_unsigned(destr, 255, trap);
631
      break;
632
    }
633
   default:
634
    fail("NOT integer in mult with o/f");
635
  }
636
  return move(aa, dest, nsp.fixed, 1);
637
}
638
 
639
/*
640
 * PLUS_TAG
641
 */
642
int plus_error_treatment PROTO_N ((e,sp,dest)) 
643
    PROTO_T (exp e X space sp X where dest )
644
{
645
  int lhs_reg=reg_operand(son(e),sp);
646
  int rhs_reg;
647
  int destr;
648
  long trap = trap_label(e);
649
  ans aa;
650
 
651
  rhs_reg = reg_operand(bro(son(e)),guardreg(lhs_reg,sp));
652
  destr=regfrmdest(&dest,sp);
653
  setregalt(aa,destr);
654
  switch(name(sh(e)))
655
  {
656
   case slonghd:
657
    {
658
      rrr_ins(i_ao,lhs_reg,rhs_reg,destr);
659
      mf_ins(i_mcrxr,0);
660
      long_bc_ins(i_bgt,0,trap,UNLIKELY_TO_JUMP);
661
      break;
662
 
663
    }
664
   case ulonghd:
665
    {
666
      rrr_ins(i_ao,lhs_reg,rhs_reg,destr);
667
      mf_ins(i_mcrxr,0);
668
      long_bc_ins(i_beq,0,trap,UNLIKELY_TO_JUMP);
669
      break;
670
    }
671
   case swordhd:
672
    {
673
      rrr_ins(i_a,lhs_reg,rhs_reg,destr);
674
      test_signed(destr,-0x8000,0x7fff,trap);
675
      break;
676
    }
677
   case uwordhd:
678
    {
679
      rrr_ins(i_a,lhs_reg,rhs_reg,destr);
680
      test_unsigned(destr,0xffff,trap);
681
      break;
682
    }
683
   case scharhd:
684
    {
685
      rrr_ins(i_a,lhs_reg,rhs_reg,destr);
686
      test_signed(destr, -128, 127, trap);
687
      break;
688
    }
689
   case ucharhd:
690
    {
691
      rrr_ins(i_a,lhs_reg,rhs_reg,destr);
692
      test_unsigned(destr, 255, trap);
693
      break;
694
    }
695
   default:
696
    fail("NOT integer shape in plus with overflow");
697
  }
698
  return move(aa, dest, sp.fixed, 0);
699
}
700
#if 0
701
/* 
702
 * ROUND
703
 * This is now done in installl_fns.c 
704
 */
705
void round_error_treatment PROTO_N ((e)) PROTO_T (exp *e)
706
{
707
  /* float --> int */
708
  exp round = *e;
709
  exp fl =son(*e);
710
  shape fl_shpe = sh(fl);
711
  bool trap = ERROR_TREATMENT_IS_TRAP(round);
712
  bool lower_strict,upper_strict;
713
  exp lower_bound;
714
  exp lower_adjustment;
715
  exp upper_bound;
716
  exp upper_adjustment;
717
  exp lower;
718
  exp upper;
719
  exp test_lower;
720
  exp test_upper;
721
  exp id;
722
  exp lab;
723
  exp clear;
724
  exp zero1;
725
  exp zero2;
726
  exp seq1;
727
  exp seq2;
728
  exp cond;
729
 
730
  ASSERT(shape_size(sh(round))==32);
731
  if (name(sh(round))==ulonghd)
732
  {
733
    lower_bound = me_u3(fl_shpe,me_shint(ulongsh,0)       ,float_tag);
734
    upper_bound = me_u3(fl_shpe,me_shint(ulongsh,UINT_MAX),float_tag);
735
  }
736
  else
737
  {
738
    lower_bound = me_u3(fl_shpe,me_shint(slongsh,INT_MIN),float_tag);
739
    upper_bound = me_u3(fl_shpe,me_shint(slongsh,INT_MAX),float_tag);
740
  }
741
  switch(round_number(round))
742
  {
743
   case R2ZERO:/* -1+l < f < 1+u */
744
    {
745
      lower_adjustment = me_u3(fl_shpe,me_shint(slongsh,-1),float_tag);
746
      upper_adjustment = me_u3(fl_shpe,me_shint(slongsh,1),float_tag);
747
      lower_strict = 1;
748
      upper_strict = 1;
749
      break;
750
    }
751
   case 4:/* round as state is same as round to nearest */
752
   case R2NEAR:/* -0.5+l < f < 0.5+u */
753
    {
754
      exp minus_one;
755
      exp one;
756
      exp two;
757
 
758
      minus_one = me_u3(fl_shpe,me_shint(slongsh,-1),float_tag);
759
      two = me_u3(fl_shpe,me_shint(slongsh,2),float_tag);
760
      lower_adjustment = me_b3(fl_shpe,minus_one,two,fdiv_tag);
761
      one = me_u3(fl_shpe,me_shint(slongsh,1),float_tag);
762
      two = me_u3(fl_shpe,me_shint(slongsh,2),float_tag);
763
      upper_adjustment = me_b3(fl_shpe,one,two,fdiv_tag);
764
      lower_strict = 1;
765
      upper_strict = 1;
766
      break;
767
    }
768
 
769
   case R2PINF:/* -1 +l < f =< u */
770
    {
771
      lower_adjustment = me_u3(fl_shpe,me_shint(slongsh,-1),float_tag);
772
      upper_adjustment = me_u3(fl_shpe,me_shint(slongsh,0),float_tag);
773
      lower_strict = 1;
774
      upper_strict = 0;
775
      break;
776
    }
777
 
778
   case R2NINF:/* l =< f < 1+u */
779
    {
780
      lower_adjustment = me_u3(fl_shpe,me_shint(slongsh,0),float_tag);
781
      upper_adjustment = me_u3(fl_shpe,me_shint(slongsh,1),float_tag);
782
      lower_strict = 0;
783
      upper_strict = 1;
784
      break;
785
    }
786
  }
787
 
788
  lower = me_b3(fl_shpe,lower_bound,lower_adjustment,fplus_tag);
789
  upper = me_b3(fl_shpe,upper_bound,upper_adjustment,fplus_tag);
790
 
791
  id = me_startid(fl_shpe,fl,0);/* start ident */
792
 
793
  clear = getexp(f_bottom,nilexp,0,nilexp,nilexp,0,0,clear_tag);
794
 
795
  if(trap)
796
  {
797
    exp t = getexp(f_bottom,nilexp,0,nilexp,nilexp,0,f_overflow,trap_tag);
798
    lab = me_b3(f_bottom,clear,t,labst_tag);
799
  }
800
  else
801
  {
802
    exp g = getexp(f_bottom,nilexp,0,nilexp,pt(round),0,0,goto_tag);
803
    lab = me_b3(f_bottom,clear,g,labst_tag);
804
  }
805
 
806
 
807
  test_lower = me_q1(no_nat_option,
808
		     lower_strict?f_greater_than:f_greater_than_or_equal,
809
		     &lab,
810
		     me_obtain(id),
811
		     lower,
812
		     test_tag);
813
  test_upper = me_q1(no_nat_option,
814
		     upper_strict?f_less_than:f_less_than_or_equal,
815
		     &lab,
816
		     me_obtain(id),
817
		     upper,
818
		     test_tag);
819
  zero1 = me_u3(f_top,test_lower,0);
820
  seq1 = me_b3(sh(test_upper),zero1,test_upper,seq_tag);
821
  cond = me_b3(f_top,seq1,lab,cond_tag);
822
  zero2 = me_u3(f_top,cond,0);
823
  seq2 = me_b3(fl_shpe,zero2,me_obtain(id),seq_tag);
824
  id = me_complete_id(id,seq2);
825
 
826
  seterrhandle(round,0);
827
 
828
  setlast(id);
829
  bro(id) = round;
830
  son(round) = id;
831
}
832
#endif
833
 
834
/*
835
 * NEG
836
 */
837
int neg_error_treatment PROTO_N ((e,sp,dest))
838
    PROTO_T (exp e X space sp X where dest )
839
{
840
  int r = reg_operand(son(e),sp);
841
  int destr = regfrmdest(&dest,sp);
842
  long trap = trap_label(e);
843
  ans aa;
844
  int cr; 
845
  space nsp;
846
  nsp = guardreg(destr,sp);
847
 
848
  switch (name(sh(e)))
849
  {
850
   case ucharhd:
851
   case uwordhd:
852
   case ulonghd:
853
    rr_ins(i_neg_cr,r,destr);
854
    long_bc_ins(i_bne,CRF0,trap,LIKELY_TO_JUMP);
855
    break;
856
   case scharhd:
857
    cr = next_creg();
858
    cmp_ri_ins(i_cmp,r,0xffffff80,cr);
859
    rr_ins(i_neg,r,destr);
860
    long_bc_ins(i_beq,cr,trap,UNLIKELY_TO_JUMP);
861
    break;
862
   case swordhd:
863
    cr = next_creg();
864
    cmp_ri_ins(i_cmp,r,0xffff8000,cr);
865
    rr_ins(i_neg,r,destr);
866
    long_bc_ins(i_beq,cr,trap,UNLIKELY_TO_JUMP);
867
    break;
868
   case slonghd:
869
    cr = next_creg();
870
    cmp_ri_ins(i_cmp,r,0x80000000,cr);
871
    rr_ins(i_neg,r,destr);
872
    long_bc_ins(i_beq,cr,trap,UNLIKELY_TO_JUMP);
873
    break;
874
   default:
875
    fail("Unknown Integer shape for neg tag\n");
876
  }
877
  setregalt(aa,destr);
878
  return move(aa,dest,nsp.fixed,1);
879
}
880
/*
881
 * REM0,REM1,REM2
882
 */
883
void rem_error_treatment PROTO_N ((l,r,e))
884
    PROTO_T (int l X int r X exp e )
885
{
886
  int creg  = next_creg();
887
  long trap = trap_label(e);
888
 
889
  cmp_ri_ins(i_cmp,r,0,creg);  
890
  long_bc_ins(i_beq,creg,trap,UNLIKELY_TO_JUMP);
891
  return;
892
}
893
 
894
/*****************************/
895
/*                           */
896
/* FLOATING error treatments */
897
/*                           */
898
/*****************************/
899
void chfl_error_treatment PROTO_N ((e,f)) PROTO_T (exp e X int f)
900
{
901
  long trap = trap_label(e);
902
 
903
  ASSERT(name(e)==chfl_tag);
904
  rrf_ins(i_frsp_cr,f,f);
905
  mcrfs_ins(CRF0,0);
906
  long_bc_ins(i_bso,CRF0,trap,UNLIKELY_TO_JUMP);
907
  return;
908
}
909
 
910
 
911
void do_fmop_error_jump PROTO_N ((e,fs,fd)) 
912
    PROTO_T (exp e X int fs X int fd )
913
{
914
  long trap = trap_label(e);
915
  Instruction_P ins;
916
 
917
  switch(name(e))
918
  {
919
   case fabs_tag:ins=i_fabs;break;
920
   case fneg_tag:ins=i_fneg;break;
921
   default:fail("Unknown error jump for fmop");break;
922
  }
923
  rrf_ins(ins,fs,fd);
924
  mcrfs_ins(CRF0,0);
925
  long_bc_ins(i_bso,CRF0,trap,UNLIKELY_TO_JUMP);
926
  if(is_single_precision(sh(e)))
927
  {
928
    rrf_ins(i_frsp,fd,fd);
929
    mcrfs_ins(CRF0,0);
930
    long_bc_ins(i_bso,CRF0,trap,UNLIKELY_TO_JUMP);
931
  }
932
  return;
933
}
934
void do_fop_error_jump PROTO_N ((e,fs1,fs2,fd)) 
935
    PROTO_T (exp e X int fs1 X int fs2 X int fd )
936
{
937
  long trap = trap_label(e);
938
  Instruction_P ins;
939
 
940
  switch (name(e))
941
  {
942
   case fplus_tag: ins = i_fa;break;
943
   case fminus_tag:ins = i_fs;break;
944
   case fmult_tag: ins = i_fm;break;
945
   case fdiv_tag:  ins = i_fd;break;
946
   default:fail("Unknown error jump for fop");
947
  }
948
  rrrf_ins(ins,fs1,fs2,fd);
949
  mcrfs_ins(CRF0,0);
950
  long_bc_ins(i_bso,CRF0,trap,UNLIKELY_TO_JUMP);
951
  switch(name(e))
952
  {
953
    /* div by 0 */
954
   case fdiv_tag:
955
    {
956
      mcrfs_ins(CRF0,1);
957
      long_bc_ins(i_bgt,CRF0,trap,UNLIKELY_TO_JUMP);
958
    }
959
  }
960
  if(is_single_precision(sh(e)))
961
  {
962
    rrf_ins(i_frsp,fd,fd);
963
    mcrfs_ins(CRF0,0);
964
    long_bc_ins(i_bso,CRF0,trap,UNLIKELY_TO_JUMP);
965
  }
966
  return;
967
}