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