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