1 /* Load programs with -lfpe. See man pages for fpc and /usr/include/sigfpe.h, sys/fpu.h. */
2 #include <stdlib.h>
3 #include <sigfpe.h>
4 #include <sys/fpu.h>
5 typedef unsigned int ulong;
6 #include "mathi.h"
7
8 /*
9 * Irix does not permit a use handled SIGFPE since the floating point unit
10 * cannot be IEEE754 compliant without some software, so we must vector using
11 * the library
12 */
13 extern void trapFPE(unsigned exception[5], int value[2]);
14
15 void
FPinit(void)16 FPinit(void)
17 {
18 union fpc_csr csr;
19 int i;
20 for(i=1; i<=4; i++) {
21 sigfpe_[i].repls = _USER_DETERMINED;
22 sigfpe_[i].abort = 2;
23 }
24 handle_sigfpes(_ON,
25 _EN_UNDERFL|_EN_OVERFL|_EN_DIVZERO|_EN_INVALID,
26 trapFPE,
27 _ABORT_ON_ERROR, 0);
28 }
29
30
31 ulong
getFPstatus(void)32 getFPstatus(void)
33 {
34 ulong fsr = 0;
35 union fpc_csr csr;
36 csr.fc_word = get_fpc_csr();
37 if(csr.fc_struct.se_inexact) fsr |= INEX;
38 if(csr.fc_struct.se_overflow) fsr |= OVFL;
39 if(csr.fc_struct.se_underflow) fsr |= UNFL;
40 if(csr.fc_struct.se_divide0) fsr |= ZDIV;
41 if(csr.fc_struct.se_invalid) fsr |= INVAL;
42 return fsr;
43 }
44
45 ulong
FPstatus(ulong fsr,ulong mask)46 FPstatus(ulong fsr, ulong mask)
47 {
48 ulong old = getFPstatus();
49 union fpc_csr csr;
50 csr.fc_word = get_fpc_csr();
51 fsr = (fsr&mask) | (old&~mask);
52 csr.fc_struct.se_inexact = (fsr&INEX)?1:0;
53 csr.fc_struct.se_overflow = (fsr&OVFL)?1:0;
54 csr.fc_struct.se_underflow = (fsr&UNFL)?1:0;
55 csr.fc_struct.se_divide0 = (fsr&ZDIV)?1:0;
56 csr.fc_struct.se_invalid = (fsr&INVAL)?1:0;
57 set_fpc_csr(csr.fc_word);
58 return(old&mask);
59 }
60
61 ulong
getFPcontrol(void)62 getFPcontrol(void)
63 {
64 ulong fcr = 0;
65 union fpc_csr csr;
66 double junk = fabs(1.); /* avoid bug mentioned in sigfpes man page [ehg] */
67 csr.fc_word = get_fpc_csr();
68 switch(csr.fc_struct.rounding_mode){
69 case ROUND_TO_NEAREST: fcr = RND_NR; break;
70 case ROUND_TO_MINUS_INFINITY: fcr = RND_NINF; break;
71 case ROUND_TO_PLUS_INFINITY: fcr = RND_PINF; break;
72 case ROUND_TO_ZERO: fcr = RND_Z; break;
73 }
74 if(csr.fc_struct.en_inexact) fcr |= INEX;
75 if(csr.fc_struct.en_overflow) fcr |= OVFL;
76 if(csr.fc_struct.en_underflow) fcr |= UNFL;
77 if(csr.fc_struct.en_divide0) fcr |= ZDIV;
78 if(csr.fc_struct.en_invalid) fcr |= INVAL;
79 return fcr;
80 }
81
82 ulong
FPcontrol(ulong fcr,ulong mask)83 FPcontrol(ulong fcr, ulong mask)
84 {
85 ulong old = getFPcontrol();
86 union fpc_csr csr;
87 csr.fc_word = get_fpc_csr();
88 fcr = (fcr&mask) | (old&~mask);
89 csr.fc_struct.en_inexact = (fcr&INEX)?1:0;
90 csr.fc_struct.en_overflow = (fcr&OVFL)?1:0;
91 csr.fc_struct.en_underflow = (fcr&UNFL)?1:0;
92 csr.fc_struct.en_divide0 = (fcr&ZDIV)?1:0;
93 csr.fc_struct.en_invalid = (fcr&INVAL)?1:0;
94 switch(fcr&RND_MASK){
95 case RND_NR: csr.fc_struct.rounding_mode = ROUND_TO_NEAREST; break;
96 case RND_NINF: csr.fc_struct.rounding_mode = ROUND_TO_MINUS_INFINITY; break;
97 case RND_PINF: csr.fc_struct.rounding_mode = ROUND_TO_PLUS_INFINITY; break;
98 case RND_Z: csr.fc_struct.rounding_mode = ROUND_TO_ZERO; break;
99 }
100 set_fpc_csr(csr.fc_word);
101 return(old&mask);
102 }
103