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