Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/include/ieeefp.h
Show All 34 Lines | |||||
* | * | ||||
* from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93 | * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93 | ||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
#ifndef _MACHINE_IEEEFP_H_ | #ifndef _MACHINE_IEEEFP_H_ | ||||
#define _MACHINE_IEEEFP_H_ | #define _MACHINE_IEEEFP_H_ | ||||
/* | #include <x86/x86_ieeefp.h> | ||||
* Deprecated historical FPU control interface | |||||
* | |||||
* IEEE floating point type, constant and function definitions. | |||||
* XXX: {FP,SSE}*FLD and {FP,SSE}*OFF are undocumented pollution. | |||||
*/ | |||||
#ifndef _SYS_CDEFS_H_ | |||||
#error this file needs sys/cdefs.h as a prerequisite | |||||
#endif | |||||
/* | /* | ||||
* Rounding modes. | |||||
*/ | |||||
typedef enum { | |||||
FP_RN=0, /* round to nearest */ | |||||
FP_RM, /* round down towards minus infinity */ | |||||
FP_RP, /* round up towards plus infinity */ | |||||
FP_RZ /* truncate */ | |||||
} fp_rnd_t; | |||||
/* | |||||
* Precision (i.e., rounding precision) modes. | |||||
*/ | |||||
typedef enum { | |||||
FP_PS=0, /* 24 bit (single-precision) */ | |||||
FP_PRS, /* reserved */ | |||||
FP_PD, /* 53 bit (double-precision) */ | |||||
FP_PE /* 64 bit (extended-precision) */ | |||||
} fp_prec_t; | |||||
#define fp_except_t int | |||||
/* | |||||
* Exception bit masks. | |||||
*/ | |||||
#define FP_X_INV 0x01 /* invalid operation */ | |||||
#define FP_X_DNML 0x02 /* denormal */ | |||||
#define FP_X_DZ 0x04 /* zero divide */ | |||||
#define FP_X_OFL 0x08 /* overflow */ | |||||
#define FP_X_UFL 0x10 /* underflow */ | |||||
#define FP_X_IMP 0x20 /* (im)precision */ | |||||
#define FP_X_STK 0x40 /* stack fault */ | |||||
/* | |||||
* FPU control word bit-field masks. | |||||
*/ | |||||
#define FP_MSKS_FLD 0x3f /* exception masks field */ | |||||
#define FP_PRC_FLD 0x300 /* precision control field */ | |||||
#define FP_RND_FLD 0xc00 /* rounding control field */ | |||||
/* | |||||
* FPU status word bit-field masks. | |||||
*/ | |||||
#define FP_STKY_FLD 0x3f /* sticky flags field */ | |||||
/* | |||||
* SSE mxcsr register bit-field masks. | * SSE mxcsr register bit-field masks. | ||||
*/ | */ | ||||
#define SSE_STKY_FLD 0x3f /* exception flags */ | #define SSE_STKY_FLD 0x3f /* exception flags */ | ||||
#define SSE_DAZ_FLD 0x40 /* Denormals are zero */ | #define SSE_DAZ_FLD 0x40 /* Denormals are zero */ | ||||
#define SSE_MSKS_FLD 0x1f80 /* exception masks field */ | #define SSE_MSKS_FLD 0x1f80 /* exception masks field */ | ||||
#define SSE_RND_FLD 0x6000 /* rounding control */ | #define SSE_RND_FLD 0x6000 /* rounding control */ | ||||
#define SSE_FZ_FLD 0x8000 /* flush to zero on underflow */ | #define SSE_FZ_FLD 0x8000 /* flush to zero on underflow */ | ||||
/* | |||||
* FPU control word bit-field offsets (shift counts). | |||||
*/ | |||||
#define FP_MSKS_OFF 0 /* exception masks offset */ | |||||
#define FP_PRC_OFF 8 /* precision control offset */ | |||||
#define FP_RND_OFF 10 /* rounding control offset */ | |||||
/* | /* | ||||
* FPU status word bit-field offsets (shift counts). | |||||
*/ | |||||
#define FP_STKY_OFF 0 /* sticky flags offset */ | |||||
/* | |||||
* SSE mxcsr register bit-field offsets (shift counts). | * SSE mxcsr register bit-field offsets (shift counts). | ||||
*/ | */ | ||||
#define SSE_STKY_OFF 0 /* exception flags offset */ | #define SSE_STKY_OFF 0 /* exception flags offset */ | ||||
#define SSE_DAZ_OFF 6 /* DAZ exception mask offset */ | #define SSE_DAZ_OFF 6 /* DAZ exception mask offset */ | ||||
#define SSE_MSKS_OFF 7 /* other exception masks offset */ | #define SSE_MSKS_OFF 7 /* other exception masks offset */ | ||||
#define SSE_RND_OFF 13 /* rounding control offset */ | #define SSE_RND_OFF 13 /* rounding control offset */ | ||||
#define SSE_FZ_OFF 15 /* flush to zero offset */ | #define SSE_FZ_OFF 15 /* flush to zero offset */ | ||||
#ifdef __GNUCLIKE_ASM | #ifdef __GNUCLIKE_ASM | ||||
#define __fldcw(addr) __asm __volatile("fldcw %0" : : "m" (*(addr))) | |||||
#define __fldenv(addr) __asm __volatile("fldenv %0" : : "m" (*(addr))) | |||||
#define __fnclex() __asm __volatile("fnclex") | |||||
#define __fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr))) | |||||
#define __fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr))) | |||||
#define __fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr))) | |||||
#define __ldmxcsr(addr) __asm __volatile("ldmxcsr %0" : : "m" (*(addr))) | |||||
#define __stmxcsr(addr) __asm __volatile("stmxcsr %0" : "=m" (*(addr))) | |||||
/* | |||||
* Load the control word. Be careful not to trap if there is a currently | |||||
* unmasked exception (ones that will become freshly unmasked are not a | |||||
* problem). This case must be handled by a save/restore of the | |||||
* environment or even of the full x87 state. Accessing the environment | |||||
* is very inefficient, so only do it when necessary. | |||||
*/ | |||||
static __inline void | |||||
__fnldcw(unsigned short _cw, unsigned short _newcw) | |||||
{ | |||||
struct { | |||||
unsigned _cw; | |||||
unsigned _other[6]; | |||||
} _env; | |||||
unsigned short _sw; | |||||
if ((_cw & FP_MSKS_FLD) != FP_MSKS_FLD) { | |||||
__fnstsw(&_sw); | |||||
if (((_sw & ~_cw) & FP_STKY_FLD) != 0) { | |||||
__fnstenv(&_env); | |||||
_env._cw = _newcw; | |||||
__fldenv(&_env); | |||||
return; | |||||
} | |||||
} | |||||
__fldcw(&_newcw); | |||||
} | |||||
/* | /* | ||||
* General notes about conflicting SSE vs FP status bits. | * General notes about conflicting SSE vs FP status bits. | ||||
* This code assumes that software will not fiddle with the control | * This code assumes that software will not fiddle with the control | ||||
* bits of the SSE and x87 in such a way to get them out of sync and | * bits of the SSE and x87 in such a way to get them out of sync and | ||||
* still expect this to work. Break this at your peril. | * still expect this to work. Break this at your peril. | ||||
* Because I based this on the i386 port, the x87 state is used for | * Because I based this on the i386 port, the x87 state is used for | ||||
* the fpget*() functions, and is shadowed into the SSE state for | * the fpget*() functions, and is shadowed into the SSE state for | ||||
▲ Show 20 Lines • Show All 137 Lines • Show Last 20 Lines |