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