ieeefp.h revision 334771
128328Ssos/*- 2229784Suqs * Copyright (c) 2003 Peter Wemm. 328328Ssos * Copyright (c) 1990 Andrew Moore, Talke Studio 428328Ssos * All rights reserved. 528328Ssos * 628328Ssos * Redistribution and use in source and binary forms, with or without 728328Ssos * modification, are permitted provided that the following conditions 828328Ssos * are met: 928328Ssos * 1. Redistributions of source code must retain the above copyright 1028328Ssos * notice, this list of conditions and the following disclaimer. 1128328Ssos * 2. Redistributions in binary form must reproduce the above copyright 1228328Ssos * notice, this list of conditions and the following disclaimer in the 1328328Ssos * documentation and/or other materials provided with the distribution. 1428328Ssos * 3. All advertising materials mentioning features or use of this software 1597748Sschweikh * must display the following acknowledgement: 1628328Ssos * This product includes software developed by the University of 1728328Ssos * California, Berkeley and its contributors. 1828328Ssos * 4. Neither the name of the University nor the names of its contributors 1928328Ssos * may be used to endorse or promote products derived from this software 2028328Ssos * without specific prior written permission. 2128328Ssos * 2228328Ssos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2328328Ssos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2428328Ssos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2528328Ssos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2628328Ssos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2728328Ssos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2828328Ssos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2983551Sdillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3083551Sdillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3183551Sdillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3228328Ssos * SUCH DAMAGE. 3328328Ssos * 3428328Ssos * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93 3528328Ssos * $FreeBSD: stable/11/sys/i386/include/ieeefp.h 334771 2018-06-07 09:03:42Z dim $ 3628328Ssos */ 3728328Ssos 3866834Sphk#ifndef _MACHINE_IEEEFP_H_ 3966834Sphk#define _MACHINE_IEEEFP_H_ 4066834Sphk 4128328Ssos/* 4228328Ssos * Deprecated historical FPU control interface 4370991Snsouch * 4470991Snsouch * IEEE floating point type, constant and function definitions. 4553013Syokota * XXX: FP*FLD and FP*OFF are undocumented pollution. 4653013Syokota */ 4753013Syokota 4828328Ssos#ifndef _SYS_CDEFS_H_ 4953013Syokota#error this file needs sys/cdefs.h as a prerequisite 5053013Syokota#endif 5153013Syokota 5228328Ssos/* 5328328Ssos * Rounding modes. 5428328Ssos */ 5553013Syokotatypedef enum { 5653013Syokota FP_RN=0, /* round to nearest */ 5728328Ssos FP_RM, /* round down towards minus infinity */ 5880270Syokota FP_RP, /* round up towards plus infinity */ 5928328Ssos FP_RZ /* truncate */ 6053013Syokota} fp_rnd_t; 6130044Ssos 6276852Ssobomax/* 6328328Ssos * Precision (i.e., rounding precision) modes. 6428328Ssos */ 6528328Ssostypedef enum { 6628328Ssos FP_PS=0, /* 24 bit (single-precision) */ 6728328Ssos FP_PRS, /* reserved */ 6828328Ssos FP_PD, /* 53 bit (double-precision) */ 6930044Ssos FP_PE /* 64 bit (extended-precision) */ 7030044Ssos} fp_prec_t; 7153013Syokota 7280270Syokota#define fp_except_t int 7380270Syokota 7453013Syokota/* 7553013Syokota * Exception bit masks. 7653013Syokota */ 7753013Syokota#define FP_X_INV 0x01 /* invalid operation */ 7853013Syokota#define FP_X_DNML 0x02 /* denormal */ 7953013Syokota#define FP_X_DZ 0x04 /* zero divide */ 8050483Syokota#define FP_X_OFL 0x08 /* overflow */ 8153013Syokota#define FP_X_UFL 0x10 /* underflow */ 8250141Syokota#define FP_X_IMP 0x20 /* (im)precision */ 8350141Syokota#define FP_X_STK 0x40 /* stack fault */ 8450141Syokota 8550141Syokota/* 8650141Syokota * FPU control word bit-field masks. 8776852Ssobomax */ 8876852Ssobomax#define FP_MSKS_FLD 0x3f /* exception masks field */ 8950141Syokota#define FP_PRC_FLD 0x300 /* precision control field */ 9050141Syokota#define FP_RND_FLD 0xc00 /* rounding control field */ 9150141Syokota 9250141Syokota/* 9350141Syokota * FPU status word bit-field masks. 9450141Syokota */ 9528328Ssos#define FP_STKY_FLD 0x3f /* sticky flags field */ 9628328Ssos 9728328Ssos/* 9828328Ssos * FPU control word bit-field offsets (shift counts). 9953013Syokota */ 10053013Syokota#define FP_MSKS_OFF 0 /* exception masks offset */ 10153013Syokota#define FP_PRC_OFF 8 /* precision control offset */ 10228328Ssos#define FP_RND_OFF 10 /* rounding control offset */ 10353013Syokota 10430044Ssos/* 10528328Ssos * FPU status word bit-field offsets (shift counts). 10628328Ssos */ 10728328Ssos#define FP_STKY_OFF 0 /* sticky flags offset */ 108130245Sstefanf 10928328Ssos#ifdef __GNUCLIKE_ASM 11080270Syokota 11180270Syokota#define __fldcw(addr) __asm __volatile("fldcw %0" : : "m" (*(addr))) 11280270Syokota#define __fldenv(addr) __asm __volatile("fldenv %0" : : "m" (*(addr))) 11380270Syokota#define __fnclex() __asm __volatile("fnclex") 11480270Syokota#define __fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr))) 11580270Syokota#define __fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr))) 11628328Ssos#define __fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr))) 11728328Ssos#define __ldmxcsr(addr) __asm __volatile("ldmxcsr %0" : : "m" (*(addr))) 11828328Ssos#define __stmxcsr(addr) __asm __volatile("stmxcsr %0" : "=m" (*(addr))) 119130245Sstefanf 12028328Ssos/* 12128328Ssos * Load the control word. Be careful not to trap if there is a currently 12228328Ssos * unmasked exception (ones that will become freshly unmasked are not a 12328328Ssos * problem). This case must be handled by a save/restore of the 12428328Ssos * environment or even of the full x87 state. Accessing the environment 12528328Ssos * is very inefficient, so only do it when necessary. 12628328Ssos */ 12728328Ssosstatic __inline void 12828328Ssos__fnldcw(unsigned short _cw, unsigned short _newcw) 12928328Ssos{ 13028328Ssos struct { 13128328Ssos unsigned _cw; 13228328Ssos unsigned _other[6]; 13353013Syokota } _env; 13428328Ssos unsigned short _sw; 13553013Syokota 13653013Syokota if ((_cw & FP_MSKS_FLD) != FP_MSKS_FLD) { 13753013Syokota __fnstsw(&_sw); 13828328Ssos if (((_sw & ~_cw) & FP_STKY_FLD) != 0) { 13928328Ssos __fnstenv(&_env); 14050483Syokota _env._cw = _newcw; 14128328Ssos __fldenv(&_env); 14228328Ssos return; 14380270Syokota } 14428328Ssos } 14528328Ssos __fldcw(&_newcw); 14628328Ssos} 14780270Syokota 14828328Ssosstatic __inline fp_rnd_t 14953013Syokotafpgetround(void) 15053013Syokota{ 15153013Syokota unsigned short _cw; 15253013Syokota 15353013Syokota __fnstcw(&_cw); 15453013Syokota return ((fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF)); 15553013Syokota} 15653013Syokota 15728328Ssosstatic __inline fp_rnd_t 15871643Ssobomaxfpsetround(fp_rnd_t _m) 15976852Ssobomax{ 16076852Ssobomax fp_rnd_t _p; 16176852Ssobomax unsigned short _cw, _newcw; 16271643Ssobomax 16376852Ssobomax __fnstcw(&_cw); 16471643Ssobomax _p = (fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF); 16553013Syokota _newcw = _cw & ~FP_RND_FLD; 16653013Syokota _newcw |= (_m << FP_RND_OFF) & FP_RND_FLD; 16753013Syokota __fnldcw(_cw, _newcw); 16828328Ssos return (_p); 16953013Syokota} 17053013Syokota 17153013Syokotastatic __inline fp_prec_t 17228328Ssosfpgetprec(void) 17328328Ssos{ 17453013Syokota unsigned short _cw; 17553013Syokota 17653013Syokota __fnstcw(&_cw); 17753013Syokota return ((fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF)); 17853013Syokota} 17953013Syokota 18053013Syokotastatic __inline fp_prec_t 18153013Syokotafpsetprec(fp_prec_t _m) 18253013Syokota{ 18353013Syokota fp_prec_t _p; 18453013Syokota unsigned short _cw, _newcw; 18553013Syokota 18653013Syokota __fnstcw(&_cw); 18753013Syokota _p = (fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF); 18828328Ssos _newcw = _cw & ~FP_PRC_FLD; 18928328Ssos _newcw |= (_m << FP_PRC_OFF) & FP_PRC_FLD; 19053013Syokota __fnldcw(_cw, _newcw); 19153013Syokota return (_p); 19253013Syokota} 19353013Syokota 19453013Syokota/* 19553013Syokota * Get or set the exception mask. 19628328Ssos * Note that the x87 mask bits are inverted by the API -- a mask bit of 1 19771623Snsouch * means disable for x87 and SSE, but for fp*mask() it means enable. 19828328Ssos */ 19953013Syokota 20028328Ssosstatic __inline fp_except_t 20171623Snsouchfpgetmask(void) 20228328Ssos{ 20370991Snsouch unsigned short _cw; 20470991Snsouch 20570991Snsouch __fnstcw(&_cw); 20670991Snsouch return ((~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF); 20770991Snsouch} 20870991Snsouch 20970991Snsouchstatic __inline fp_except_t 21070991Snsouchfpsetmask(fp_except_t _m) 21170991Snsouch{ 21270991Snsouch fp_except_t _p; 21370991Snsouch unsigned short _cw, _newcw; 21470991Snsouch 21570991Snsouch __fnstcw(&_cw); 21670991Snsouch _p = (~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF; 21770991Snsouch _newcw = _cw & ~FP_MSKS_FLD; 21870991Snsouch _newcw |= (~_m << FP_MSKS_OFF) & FP_MSKS_FLD; 21970991Snsouch __fnldcw(_cw, _newcw); 22070991Snsouch return (_p); 22170991Snsouch} 22228328Ssos 22328328Ssosstatic __inline fp_except_t 22453013Syokotafpgetsticky(void) 22528328Ssos{ 22628328Ssos unsigned _ex; 22728328Ssos unsigned short _sw; 22828328Ssos 22953013Syokota __fnstsw(&_sw); 23053013Syokota _ex = (_sw & FP_STKY_FLD) >> FP_STKY_OFF; 23153013Syokota return ((fp_except_t)_ex); 23228328Ssos} 23353013Syokota 23453013Syokotastatic __inline fp_except_t 23553013Syokotafpresetsticky(fp_except_t _m) 23653013Syokota{ 23728328Ssos struct { 23853013Syokota unsigned _cw; 23953013Syokota unsigned _sw; 24053013Syokota unsigned _other[5]; 24153013Syokota } _env; 24253013Syokota fp_except_t _p; 24353013Syokota 24453013Syokota _m &= FP_STKY_FLD >> FP_STKY_OFF; 24553013Syokota _p = fpgetsticky(); 24653013Syokota if ((_p & ~_m) == _p) 24753013Syokota return (_p); 24853013Syokota if ((_p & ~_m) == 0) { 24953013Syokota __fnclex(); 25053013Syokota return (_p); 25153013Syokota } 25253013Syokota __fnstenv(&_env); 25353013Syokota _env._sw &= ~_m; 25453013Syokota __fldenv(&_env); 25553013Syokota return (_p); 25653013Syokota} 25753013Syokota 25853013Syokota#endif /* __GNUCLIKE_ASM */ 25953013Syokota 26053013Syokota#endif /* !_MACHINE_IEEEFP_H_ */ 26153013Syokota