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 */