xref: /illumos-gate/usr/src/head/ieeefp.h (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
24  *
25  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28 
29 /*	Copyright (c) 1988 AT&T */
30 /*	  All Rights Reserved */
31 
32 
33 #ifndef _IEEEFP_H
34 #define	_IEEEFP_H
35 
36 #ifdef	__cplusplus
37 extern "C" {
38 #endif
39 
40 /*
41  * Floating point enviornment for machines that support
42  * the IEEE 754 floating-point standard.  This file currently
43  * supports the 80*87, and SPARC families.
44  *
45  * This header defines the following interfaces:
46  *	1) Classes of floating point numbers
47  *	2) Rounding Control
48  *	3) Exception Control
49  *	4) Exception Handling
50  *	5) Utility Macros
51  *	6) Full Exception Environment Control
52  */
53 
54 /*
55  * CLASSES of floating point numbers *************************
56  * IEEE floating point values fall into 1 of the following 10
57  * classes
58  */
59 typedef	enum	fpclass_t {
60 	FP_SNAN = 0,	/* signaling NaN */
61 	FP_QNAN = 1,	/* quiet NaN */
62 	FP_NINF = 2,	/* negative infinity */
63 	FP_PINF = 3,	/* positive infinity */
64 	FP_NDENORM = 4, /* negative denormalized non-zero */
65 	FP_PDENORM = 5, /* positive denormalized non-zero */
66 	FP_NZERO = 6,	/* -0.0 */
67 	FP_PZERO = 7,   /* +0.0 */
68 	FP_NNORM = 8,	/* negative normalized non-zero */
69 	FP_PNORM = 9	/* positive normalized non-zero */
70 } fpclass_t;
71 
72 extern fpclass_t fpclass(double);	/* get class of double value */
73 extern int	finite(double);
74 extern int	unordered(double, double);
75 
76 /*
77  * ROUNDING CONTROL ******************************************
78  *
79  * At all times, floating-point math is done using one of four
80  * mutually-exclusive rounding modes.
81  */
82 
83 #if defined(__i386) || defined(__amd64)
84 
85 /*
86  * NOTE: the values given are chosen to match those used by the
87  * 80*87 rounding mode field in the control word.
88  */
89 typedef	enum	fp_rnd {
90 	FP_RN = 0,	/* round to nearest representable number, tie -> even */
91 	FP_RM = 1,	/* round toward minus infinity */
92 	FP_RP = 2,	/* round toward plus infinity */
93 	FP_RZ = 3	/* round toward zero (truncate) */
94 } fp_rnd;
95 
96 #endif
97 
98 #if defined(__sparc)
99 
100 /*
101  * NOTE: the values given are chosen to match those used by the
102  * RD (Round Direction) field of the FSR (Floating Point State Register).
103  */
104 typedef	enum	fp_rnd {
105 	FP_RN = 0,	/* round to nearest representable number, tie -> even */
106 	FP_RZ = 1,	/* round toward zero (truncate) */
107 	FP_RP = 2,	/* round toward plus infinity */
108 	FP_RM = 3	/* round toward minus infinity */
109 } fp_rnd;
110 
111 #endif
112 
113 extern fp_rnd	fpsetround(fp_rnd);	/* set rounding mode, return previous */
114 extern fp_rnd	fpgetround(void);	/* return current rounding mode */
115 
116 /*
117  * EXCEPTION CONTROL *****************************************
118  *
119  */
120 
121 #define	fp_except	int
122 
123 #define	FP_DISABLE	0	/* exception will be ignored */
124 #define	FP_ENABLE	1	/* exception will cause SIGFPE */
125 #define	FP_CLEAR	0	/* exception has not occurred */
126 #define	FP_SET		1	/* exception has occurred */
127 
128 #if defined(__i386) || defined(__amd64)
129 
130 /*
131  * There are six floating point exceptions, which can be individually
132  * ENABLED (== 1) or DISABLED (== 0).  When an exception occurs
133  * (ENABLED or not), the fact is noted by changing an associated
134  * "sticky bit" from CLEAR (==0) to SET (==1).
135  *
136  * NOTE: the bit positions in fp_except are chosen to match those of
137  * the 80*87 control word mask bits.  Although the 87 chips actually
138  * ENABLE exceptions with a mask value of 0 (not 1, as on the 3b), it
139  * is felt that switching these values may create more problems than
140  * it solves.
141  */
142 
143 /* an fp_except can have the following (not exclusive) values: */
144 #define	FP_X_INV	0x01	/* invalid operation exception */
145 #define	FP_X_DNML	0x02	/* denormalization exception */
146 #define	FP_X_DZ		0x04	/* divide-by-zero exception */
147 #define	FP_X_OFL	0x08	/* overflow exception */
148 #define	FP_X_UFL	0x10	/* underflow exception */
149 #define	FP_X_IMP	0x20	/* imprecise (loss of precision) */
150 
151 #endif
152 
153 #if defined(__sparc)
154 
155 /*
156  * There are five floating-point exceptions, which can be individually
157  * ENABLED (== 1) or DISABLED (== 0).  When an exception occurs
158  * (ENABLED or not), the fact is noted by changing an associated
159  * "sticky bit" from CLEAR (==0) to SET (==1).
160  *
161  * NOTE: the bit positions in an fp_except are chosen to match that in
162  * the Trap Enable Mask of the FSR (Floating Point State Register).
163  */
164 
165 /* an fp_except can have the following (not exclusive) values: */
166 #define	FP_X_INV	0x10	/* invalid operation exception */
167 #define	FP_X_OFL	0x08	/* overflow exception */
168 #define	FP_X_UFL	0x04	/* underflow exception */
169 #define	FP_X_DZ		0x02	/* divide-by-zero exception */
170 #define	FP_X_IMP	0x01	/* imprecise (loss of precision) */
171 
172 #endif
173 
174 extern fp_except fpgetmask(void);		/* current exception mask */
175 extern fp_except fpsetmask(fp_except);		/* set mask, return previous */
176 extern fp_except fpgetsticky(void);		/* return logged exceptions */
177 extern fp_except fpsetsticky(fp_except);	/* change logged exceptions */
178 
179 /*
180  * UTILITY MACROS ********************************************
181  */
182 
183 extern int isnanf(float);
184 extern int isnand(double);
185 
186 #if defined(__i386) || defined(__amd64)
187 
188 /*
189  * EXCEPTION HANDLING ****************************************
190  *
191  * When a signal handler catches an FPE, it will have a freshly initialized
192  * coprocessor.  This allows signal handling routines to make use of
193  * floating point arithmetic, if need be.  The previous state of the 87
194  * chip is available, however.  There are two ways to get at this information,
195  * depending on how the signal handler was set up.
196  *
197  * If the handler was set via signal() or sigset(), the old, SVR3, method
198  * should be used: the signal handler assumes that it has a single parameter,
199  * which is of type struct _fpstackframe, defined below.  By investigating
200  * this parameter, the cause of the FPE may be determined.  By modifying it,
201  * the state of the coprocessor can be changed upon return to the main task.
202  * THIS METHOD IS OBSOLETE, AND MAY NOT BE SUPPORTED IN FUTURE RELEASES.
203  *
204  * If the handler was set via sigaction(), the new, SVR4, method should be
205  * used: the third argument to the handler will be a pointer to a ucontext
206  * structure (see sys/ucontext.h).  The uc_mcontext.fpregs member of the
207  * ucontext structure holds the saved floating-point registers.  This can be
208  * examined and/or modified.  By modifying it, the state of the coprocessor
209  * can be changed upon return to the main task.
210  */
211 
212 struct _fpreg {	/* structure of a temp real fp register */
213 	unsigned short significand[4];	/* 64 bit mantissa value */
214 	unsigned short exponent;	/* 15 bit exponent and sign bit */
215 };
216 
217 #if defined(__i386)
218 
219 /*
220  * AMD64 users should use sigaction() as described above.
221  */
222 
223 struct _fpstackframe {		/* signal handler's argument */
224 	long signo;		/* signal number arg */
225 	long regs[19];		/* all registers */
226 	struct _fpstate *fpsp;	/* address of saved 387 state */
227 	char *wsp;		/* address of saved Weitek state */
228 };
229 
230 #endif
231 
232 #if defined(__i386) || defined(__amd64)
233 
234 #if defined(__amd64)
235 #define	_fpstate _fpstate32
236 #endif
237 
238 struct _fpstate {		/* saved state info from an exception */
239 	unsigned int	cw,	/* control word */
240 			sw,	/* status word after fnclex-not useful */
241 			tag,	/* tag word */
242 			ipoff,	/* %eip register */
243 			cssel,	/* code segment selector */
244 			dataoff, /* data operand address */
245 			datasel; /* data operand selector */
246 	struct _fpreg _st[8];	/* saved register stack */
247 	unsigned int status;	/* status word saved at exception */
248 	unsigned int mxcsr;
249 	unsigned int xstatus;	/* status word saved at exception */
250 	unsigned int __pad[2];
251 	unsigned int xmm[8][4];
252 };
253 
254 #if defined(__amd64)
255 #undef	_fpstate
256 #endif
257 
258 #endif	/* __i386 || __amd64 */
259 
260 /*
261  * The structure of the 80*87 status and control words, and the mxcsr
262  * register are given by the following structures.
263  */
264 struct _cw87 {
265 	unsigned
266 		mask:	6,	/* exception masks */
267 		res1:	2,	/* not used */
268 		prec:	2,	/* precision control field */
269 		rnd:	2,	/* rounding control field */
270 		inf:	1,	/* infinity control (not on 387) */
271 		res2:	3;	/* not used */
272 };
273 
274 struct _sw87 {
275 	unsigned
276 		excp:	6,	/* exception sticky bits */
277 		res1:	1,	/* not used */
278 		errs:	1,	/* error summary-set if unmasked excp */
279 		c012:	3,	/* condition code bits 0..2 */
280 		stkt:	3,	/* stack top pointer */
281 		c3:	1,	/* condition code bit 3 */
282 		busy:	1;	/* coprocessor busy */
283 };
284 
285 struct _mxcsr {
286 	unsigned
287 		excp:	6,	/* exception sticky bits */
288 		daz:	1,	/* denormals are zeroes */
289 		mask:	6,	/* exception masks */
290 		rnd:	2,	/* rounding control */
291 		fzero:	1;	/* flush to zero */
292 };
293 
294 #endif
295 
296 #ifdef	__cplusplus
297 }
298 #endif
299 
300 #endif	/* _IEEEFP_H */
301