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