ieeefp.h revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
#ifndef _IEEEFP_H
#define _IEEEFP_H
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Floating point enviornment for machines that support
* the IEEE 754 floating-point standard. This file currently
* supports the 80*87, and SPARC families.
*
* This header defines the following interfaces:
* 1) Classes of floating point numbers
* 2) Rounding Control
* 3) Exception Control
* 4) Exception Handling
* 5) Utility Macros
* 6) Full Exception Environment Control
*/
/*
* CLASSES of floating point numbers *************************
* IEEE floating point values fall into 1 of the following 10
* classes
*/
typedef enum fpclass_t {
FP_SNAN = 0, /* signaling NaN */
FP_QNAN = 1, /* quiet NaN */
FP_NINF = 2, /* negative infinity */
FP_PINF = 3, /* positive infinity */
FP_NDENORM = 4, /* negative denormalized non-zero */
FP_PDENORM = 5, /* positive denormalized non-zero */
FP_NZERO = 6, /* -0.0 */
FP_PZERO = 7, /* +0.0 */
FP_NNORM = 8, /* negative normalized non-zero */
FP_PNORM = 9 /* positive normalized non-zero */
} fpclass_t;
#if defined(__STDC__)
extern fpclass_t fpclass(double); /* get class of double value */
extern int finite(double);
extern int unordered(double, double);
#else
extern fpclass_t fpclass(); /* get class of double value */
#endif
/*
* ROUNDING CONTROL ******************************************
*
* At all times, floating-point math is done using one of four
* mutually-exclusive rounding modes.
*/
#if defined(__i386) || defined(__amd64)
/*
* NOTE: the values given are chosen to match those used by the
* 80*87 rounding mode field in the control word.
*/
typedef enum fp_rnd {
FP_RN = 0, /* round to nearest representable number, tie -> even */
FP_RM = 1, /* round toward minus infinity */
FP_RP = 2, /* round toward plus infinity */
FP_RZ = 3 /* round toward zero (truncate) */
} fp_rnd;
#endif
#if defined(__sparc)
/*
* NOTE: the values given are chosen to match those used by the
* RD (Round Direction) field of the FSR (Floating Point State Register).
*/
typedef enum fp_rnd {
FP_RN = 0, /* round to nearest representable number, tie -> even */
FP_RZ = 1, /* round toward zero (truncate) */
FP_RP = 2, /* round toward plus infinity */
FP_RM = 3 /* round toward minus infinity */
} fp_rnd;
#endif
#if defined(__STDC__)
extern fp_rnd fpsetround(fp_rnd); /* set rounding mode, return previous */
extern fp_rnd fpgetround(void); /* return current rounding mode */
#else
extern fp_rnd fpsetround(); /* set rounding mode, return previous */
extern fp_rnd fpgetround(); /* return current rounding mode */
#endif
/*
* EXCEPTION CONTROL *****************************************
*
*/
#define fp_except int
#define FP_DISABLE 0 /* exception will be ignored */
#define FP_ENABLE 1 /* exception will cause SIGFPE */
#define FP_CLEAR 0 /* exception has not occurred */
#define FP_SET 1 /* exception has occurred */
#if defined(__i386) || defined(__amd64)
/*
* There are six floating point exceptions, which can be individually
* ENABLED (== 1) or DISABLED (== 0). When an exception occurs
* (ENABLED or not), the fact is noted by changing an associated
* "sticky bit" from CLEAR (==0) to SET (==1).
*
* NOTE: the bit positions in fp_except are chosen to match those of
* the 80*87 control word mask bits. Although the 87 chips actually
* ENABLE exceptions with a mask value of 0 (not 1, as on the 3b), it
* is felt that switching these values may create more problems than
* it solves.
*/
/* an fp_except can have the following (not exclusive) values: */
#define FP_X_INV 0x01 /* invalid operation exception */
#define FP_X_DNML 0x02 /* denormalization exception */
#define FP_X_DZ 0x04 /* divide-by-zero exception */
#define FP_X_OFL 0x08 /* overflow exception */
#define FP_X_UFL 0x10 /* underflow exception */
#define FP_X_IMP 0x20 /* imprecise (loss of precision) */
#endif
#if defined(__sparc)
/*
* There are five floating-point exceptions, which can be individually
* ENABLED (== 1) or DISABLED (== 0). When an exception occurs
* (ENABLED or not), the fact is noted by changing an associated
* "sticky bit" from CLEAR (==0) to SET (==1).
*
* NOTE: the bit positions in an fp_except are chosen to match that in
* the Trap Enable Mask of the FSR (Floating Point State Register).
*/
/* an fp_except can have the following (not exclusive) values: */
#define FP_X_INV 0x10 /* invalid operation exception */
#define FP_X_OFL 0x08 /* overflow exception */
#define FP_X_UFL 0x04 /* underflow exception */
#define FP_X_DZ 0x02 /* divide-by-zero exception */
#define FP_X_IMP 0x01 /* imprecise (loss of precision) */
#endif
#if defined(__STDC__)
extern fp_except fpgetmask(void); /* current exception mask */
extern fp_except fpsetmask(fp_except); /* set mask, return previous */
extern fp_except fpgetsticky(void); /* return logged exceptions */
extern fp_except fpsetsticky(fp_except); /* change logged exceptions */
#else
extern fp_except fpgetmask(); /* current exception mask */
extern fp_except fpsetmask(); /* set mask, return previous */
extern fp_except fpgetsticky(); /* return logged exceptions */
extern fp_except fpsetsticky(); /* change logged exceptions */
#endif
/*
* UTILITY MACROS ********************************************
*/
#if defined(__STDC__)
extern int isnanf(float);
extern int isnand(double);
#else
extern int isnand();
#define isnanf(x) (((*(long *)&(x) & 0x7f800000L) == 0x7f800000L) && \
((*(long *)&(x) & 0x007fffffL) != 0x00000000L))
#endif
#if defined(__i386) || defined(__amd64)
/*
* EXCEPTION HANDLING ****************************************
*
* When a signal handler catches an FPE, it will have a freshly initialized
* coprocessor. This allows signal handling routines to make use of
* floating point arithmetic, if need be. The previous state of the 87
* chip is available, however. There are two ways to get at this information,
* depending on how the signal handler was set up.
*
* If the handler was set via signal() or sigset(), the old, SVR3, method
* should be used: the signal handler assumes that it has a single parameter,
* which is of type struct _fpstackframe, defined below. By investigating
* this parameter, the cause of the FPE may be determined. By modifying it,
* the state of the coprocessor can be changed upon return to the main task.
* THIS METHOD IS OBSOLETE, AND MAY NOT BE SUPPORTED IN FUTURE RELEASES.
*
* If the handler was set via sigaction(), the new, SVR4, method should be
* used: the third argument to the handler will be a pointer to a ucontext
* structure (see sys/ucontext.h). The uc_mcontext.fpregs member of the
* ucontext structure holds the saved floating-point registers. This can be
* examined and/or modified. By modifying it, the state of the coprocessor
* can be changed upon return to the main task.
*/
struct _fpreg { /* structure of a temp real fp register */
unsigned short significand[4]; /* 64 bit mantissa value */
unsigned short exponent; /* 15 bit exponent and sign bit */
};
#if defined(__i386)
/*
* AMD64 users should use sigaction() as described above.
*/
struct _fpstackframe { /* signal handler's argument */
long signo; /* signal number arg */
long regs[19]; /* all registers */
struct _fpstate *fpsp; /* address of saved 387 state */
char *wsp; /* address of saved Weitek state */
};
#endif
#if defined(__i386) || defined(__amd64)
#if defined(__amd64)
#define _fpstate _fpstate32
#endif
struct _fpstate { /* saved state info from an exception */
unsigned int cw, /* control word */
sw, /* status word after fnclex-not useful */
tag, /* tag word */
ipoff, /* %eip register */
cssel, /* code segment selector */
dataoff, /* data operand address */
datasel; /* data operand selector */
struct _fpreg _st[8]; /* saved register stack */
unsigned int status; /* status word saved at exception */
unsigned int mxcsr;
unsigned int xstatus; /* status word saved at exception */
unsigned int __pad[2];
unsigned int xmm[8][4];
};
#if defined(__amd64)
#undef _fpstate
#endif
#endif /* __i386 || __amd64 */
/*
* The structure of the 80*87 status and control words, and the mxcsr
* register are given by the following structures.
*/
struct _cw87 {
unsigned
mask: 6, /* exception masks */
res1: 2, /* not used */
prec: 2, /* precision control field */
rnd: 2, /* rounding control field */
inf: 1, /* infinity control (not on 387) */
res2: 3; /* not used */
};
struct _sw87 {
unsigned
excp: 6, /* exception sticky bits */
res1: 1, /* not used */
errs: 1, /* error summary-set if unmasked excp */
c012: 3, /* condition code bits 0..2 */
stkt: 3, /* stack top pointer */
c3: 1, /* condition code bit 3 */
busy: 1; /* coprocessor busy */
};
struct _mxcsr {
unsigned
excp: 6, /* exception sticky bits */
daz: 1, /* denormals are zeroes */
mask: 6, /* exception masks */
rnd: 2, /* rounding control */
fzero: 1; /* flush to zero */
};
#endif
#ifdef __cplusplus
}
#endif
#endif /* _IEEEFP_H */