Home | History | Annotate | Download | only in head
      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