xref: /illumos-gate/usr/src/head/ieeefp.h (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T */
28 /*	  All Rights Reserved */
29 
30 
31 #ifndef _IEEEFP_H
32 #define	_IEEEFP_H
33 
34 #pragma ident	"%Z%%M%	%I%	%E% SMI"
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 #if defined(__STDC__)
73 extern fpclass_t fpclass(double);	/* get class of double value */
74 extern int	finite(double);
75 extern int	unordered(double, double);
76 #else
77 extern fpclass_t fpclass();	/* get class of double value */
78 #endif
79 
80 /*
81  * ROUNDING CONTROL ******************************************
82  *
83  * At all times, floating-point math is done using one of four
84  * mutually-exclusive rounding modes.
85  */
86 
87 #if defined(__i386) || defined(__amd64)
88 
89 /*
90  * NOTE: the values given are chosen to match those used by the
91  * 80*87 rounding mode field in the control word.
92  */
93 typedef	enum	fp_rnd {
94 	FP_RN = 0,	/* round to nearest representable number, tie -> even */
95 	FP_RM = 1,	/* round toward minus infinity */
96 	FP_RP = 2,	/* round toward plus infinity */
97 	FP_RZ = 3	/* round toward zero (truncate) */
98 } fp_rnd;
99 
100 #endif
101 
102 #if defined(__sparc)
103 
104 /*
105  * NOTE: the values given are chosen to match those used by the
106  * RD (Round Direction) field of the FSR (Floating Point State Register).
107  */
108 typedef	enum	fp_rnd {
109 	FP_RN = 0,	/* round to nearest representable number, tie -> even */
110 	FP_RZ = 1,	/* round toward zero (truncate) */
111 	FP_RP = 2,	/* round toward plus infinity */
112 	FP_RM = 3	/* round toward minus infinity */
113 } fp_rnd;
114 
115 #endif
116 
117 #if defined(__STDC__)
118 extern fp_rnd	fpsetround(fp_rnd);	/* set rounding mode, return previous */
119 extern fp_rnd	fpgetround(void);	/* return current rounding mode */
120 
121 #else
122 extern fp_rnd	fpsetround();		/* set rounding mode, return previous */
123 extern fp_rnd	fpgetround();		/* return current rounding mode */
124 
125 #endif
126 
127 /*
128  * EXCEPTION CONTROL *****************************************
129  *
130  */
131 
132 #define	fp_except	int
133 
134 #define	FP_DISABLE	0	/* exception will be ignored */
135 #define	FP_ENABLE	1	/* exception will cause SIGFPE */
136 #define	FP_CLEAR	0	/* exception has not occurred */
137 #define	FP_SET		1	/* exception has occurred */
138 
139 #if defined(__i386) || defined(__amd64)
140 
141 /*
142  * There are six floating point exceptions, which can be individually
143  * ENABLED (== 1) or DISABLED (== 0).  When an exception occurs
144  * (ENABLED or not), the fact is noted by changing an associated
145  * "sticky bit" from CLEAR (==0) to SET (==1).
146  *
147  * NOTE: the bit positions in fp_except are chosen to match those of
148  * the 80*87 control word mask bits.  Although the 87 chips actually
149  * ENABLE exceptions with a mask value of 0 (not 1, as on the 3b), it
150  * is felt that switching these values may create more problems than
151  * it solves.
152  */
153 
154 /* an fp_except can have the following (not exclusive) values: */
155 #define	FP_X_INV	0x01	/* invalid operation exception */
156 #define	FP_X_DNML	0x02	/* denormalization exception */
157 #define	FP_X_DZ		0x04	/* divide-by-zero exception */
158 #define	FP_X_OFL	0x08	/* overflow exception */
159 #define	FP_X_UFL	0x10	/* underflow exception */
160 #define	FP_X_IMP	0x20	/* imprecise (loss of precision) */
161 
162 #endif
163 
164 #if defined(__sparc)
165 
166 /*
167  * There are five floating-point exceptions, which can be individually
168  * ENABLED (== 1) or DISABLED (== 0).  When an exception occurs
169  * (ENABLED or not), the fact is noted by changing an associated
170  * "sticky bit" from CLEAR (==0) to SET (==1).
171  *
172  * NOTE: the bit positions in an fp_except are chosen to match that in
173  * the Trap Enable Mask of the FSR (Floating Point State Register).
174  */
175 
176 /* an fp_except can have the following (not exclusive) values: */
177 #define	FP_X_INV	0x10	/* invalid operation exception */
178 #define	FP_X_OFL	0x08	/* overflow exception */
179 #define	FP_X_UFL	0x04	/* underflow exception */
180 #define	FP_X_DZ		0x02	/* divide-by-zero exception */
181 #define	FP_X_IMP	0x01	/* imprecise (loss of precision) */
182 
183 #endif
184 
185 #if defined(__STDC__)
186 extern fp_except fpgetmask(void);		/* current exception mask */
187 extern fp_except fpsetmask(fp_except);		/* set mask, return previous */
188 extern fp_except fpgetsticky(void);		/* return logged exceptions */
189 extern fp_except fpsetsticky(fp_except);	/* change logged exceptions */
190 
191 #else
192 extern fp_except fpgetmask();	/* current exception mask */
193 extern fp_except fpsetmask();	/* set mask, return previous */
194 extern fp_except fpgetsticky();	/* return logged exceptions */
195 extern fp_except fpsetsticky();	/* change logged exceptions */
196 
197 #endif
198 
199 /*
200  * UTILITY MACROS ********************************************
201  */
202 
203 #if defined(__STDC__)
204 extern int isnanf(float);
205 extern int isnand(double);
206 
207 #else
208 extern int isnand();
209 #define	isnanf(x)	(((*(long *)&(x) & 0x7f800000L) == 0x7f800000L) && \
210 			    ((*(long *)&(x) & 0x007fffffL) != 0x00000000L))
211 #endif
212 
213 #if defined(__i386) || defined(__amd64)
214 
215 /*
216  * EXCEPTION HANDLING ****************************************
217  *
218  * When a signal handler catches an FPE, it will have a freshly initialized
219  * coprocessor.  This allows signal handling routines to make use of
220  * floating point arithmetic, if need be.  The previous state of the 87
221  * chip is available, however.  There are two ways to get at this information,
222  * depending on how the signal handler was set up.
223  *
224  * If the handler was set via signal() or sigset(), the old, SVR3, method
225  * should be used: the signal handler assumes that it has a single parameter,
226  * which is of type struct _fpstackframe, defined below.  By investigating
227  * this parameter, the cause of the FPE may be determined.  By modifying it,
228  * the state of the coprocessor can be changed upon return to the main task.
229  * THIS METHOD IS OBSOLETE, AND MAY NOT BE SUPPORTED IN FUTURE RELEASES.
230  *
231  * If the handler was set via sigaction(), the new, SVR4, method should be
232  * used: the third argument to the handler will be a pointer to a ucontext
233  * structure (see sys/ucontext.h).  The uc_mcontext.fpregs member of the
234  * ucontext structure holds the saved floating-point registers.  This can be
235  * examined and/or modified.  By modifying it, the state of the coprocessor
236  * can be changed upon return to the main task.
237  */
238 
239 struct _fpreg {	/* structure of a temp real fp register */
240 	unsigned short significand[4];	/* 64 bit mantissa value */
241 	unsigned short exponent;	/* 15 bit exponent and sign bit */
242 };
243 
244 #if defined(__i386)
245 
246 /*
247  * AMD64 users should use sigaction() as described above.
248  */
249 
250 struct _fpstackframe {		/* signal handler's argument */
251 	long signo;		/* signal number arg */
252 	long regs[19];		/* all registers */
253 	struct _fpstate *fpsp;	/* address of saved 387 state */
254 	char *wsp;		/* address of saved Weitek state */
255 };
256 
257 #endif
258 
259 #if defined(__i386) || defined(__amd64)
260 
261 #if defined(__amd64)
262 #define	_fpstate _fpstate32
263 #endif
264 
265 struct _fpstate {		/* saved state info from an exception */
266 	unsigned int	cw,	/* control word */
267 			sw,	/* status word after fnclex-not useful */
268 			tag,	/* tag word */
269 			ipoff,	/* %eip register */
270 			cssel,	/* code segment selector */
271 			dataoff, /* data operand address */
272 			datasel; /* data operand selector */
273 	struct _fpreg _st[8];	/* saved register stack */
274 	unsigned int status;	/* status word saved at exception */
275 	unsigned int mxcsr;
276 	unsigned int xstatus;	/* status word saved at exception */
277 	unsigned int __pad[2];
278 	unsigned int xmm[8][4];
279 };
280 
281 #if defined(__amd64)
282 #undef	_fpstate
283 #endif
284 
285 #endif	/* __i386 || __amd64 */
286 
287 /*
288  * The structure of the 80*87 status and control words, and the mxcsr
289  * register are given by the following structures.
290  */
291 struct _cw87 {
292 	unsigned
293 		mask:	6,	/* exception masks */
294 		res1:	2,	/* not used */
295 		prec:	2,	/* precision control field */
296 		rnd:	2,	/* rounding control field */
297 		inf:	1,	/* infinity control (not on 387) */
298 		res2:	3;	/* not used */
299 };
300 
301 struct _sw87 {
302 	unsigned
303 		excp:	6,	/* exception sticky bits */
304 		res1:	1,	/* not used */
305 		errs:	1,	/* error summary-set if unmasked excp */
306 		c012:	3,	/* condition code bits 0..2 */
307 		stkt:	3,	/* stack top pointer */
308 		c3:	1,	/* condition code bit 3 */
309 		busy:	1;	/* coprocessor busy */
310 };
311 
312 struct _mxcsr {
313 	unsigned
314 		excp:	6,	/* exception sticky bits */
315 		daz:	1,	/* denormals are zeroes */
316 		mask:	6,	/* exception masks */
317 		rnd:	2,	/* rounding control */
318 		fzero:	1;	/* flush to zero */
319 };
320 
321 #endif
322 
323 #ifdef	__cplusplus
324 }
325 #endif
326 
327 #endif	/* _IEEEFP_H */
328