xref: /inferno-os/libmath/FPcontrol-Irix.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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