| Commit | Line | Data |
|---|---|---|
| 984263bc | 1 | /*- |
| 410233b2 | 2 | * Copyright (c) 2003 Peter Wemm. |
| 984263bc MD |
3 | * Copyright (c) 1990 Andrew Moore, Talke Studio |
| 4 | * All rights reserved. | |
| 5 | * | |
| 6 | * Redistribution and use in source and binary forms, with or without | |
| 7 | * modification, are permitted provided that the following conditions | |
| 8 | * are met: | |
| 9 | * 1. Redistributions of source code must retain the above copyright | |
| 10 | * notice, this list of conditions and the following disclaimer. | |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 12 | * notice, this list of conditions and the following disclaimer in the | |
| 13 | * documentation and/or other materials provided with the distribution. | |
| 14 | * 3. All advertising materials mentioning features or use of this software | |
| 15 | * must display the following acknowledgement: | |
| 16 | * This product includes software developed by the University of | |
| 17 | * California, Berkeley and its contributors. | |
| 18 | * 4. Neither the name of the University nor the names of its contributors | |
| 19 | * may be used to endorse or promote products derived from this software | |
| 20 | * without specific prior written permission. | |
| 21 | * | |
| 22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
| 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
| 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 32 | * SUCH DAMAGE. | |
| 33 | * | |
| 34 | * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93 | |
| 410233b2 | 35 | * $FreeBSD: src/sys/i386/include/ieeefp.h,v 1.14 2008/01/11 18:59:35 bde Exp $ |
| 984263bc MD |
36 | */ |
| 37 | ||
| 88181b08 MD |
38 | #ifndef _CPU_IEEEFP_H_ |
| 39 | #define _CPU_IEEEFP_H_ | |
| 984263bc MD |
40 | |
| 41 | /* | |
| 410233b2 PA |
42 | * IEEE floating point type, constant and function definitions. |
| 43 | * XXX: FP*FLD and FP*OFF are undocumented pollution. | |
| 44 | */ | |
| 45 | ||
| 46 | /* | |
| 47 | * Rounding modes. | |
| 984263bc MD |
48 | */ |
| 49 | typedef enum { | |
| 50 | FP_RN=0, /* round to nearest */ | |
| 410233b2 PA |
51 | FP_RM, /* round down towards minus infinity */ |
| 52 | FP_RP, /* round up towards plus infinity */ | |
| 984263bc MD |
53 | FP_RZ /* truncate */ |
| 54 | } fp_rnd_t; | |
| 55 | ||
| 56 | /* | |
| 410233b2 | 57 | * Precision (i.e., rounding precision) modes. |
| 984263bc MD |
58 | */ |
| 59 | typedef enum { | |
| 60 | FP_PS=0, /* 24 bit (single-precision) */ | |
| 61 | FP_PRS, /* reserved */ | |
| 62 | FP_PD, /* 53 bit (double-precision) */ | |
| 63 | FP_PE /* 64 bit (extended-precision) */ | |
| 64 | } fp_prec_t; | |
| 65 | ||
| 66 | #define fp_except_t int | |
| 67 | ||
| 68 | /* | |
| 410233b2 | 69 | * Exception bit masks. |
| 984263bc MD |
70 | */ |
| 71 | #define FP_X_INV 0x01 /* invalid operation */ | |
| 72 | #define FP_X_DNML 0x02 /* denormal */ | |
| 73 | #define FP_X_DZ 0x04 /* zero divide */ | |
| 74 | #define FP_X_OFL 0x08 /* overflow */ | |
| 75 | #define FP_X_UFL 0x10 /* underflow */ | |
| 76 | #define FP_X_IMP 0x20 /* (im)precision */ | |
| 77 | #define FP_X_STK 0x40 /* stack fault */ | |
| 78 | ||
| 79 | /* | |
| 410233b2 | 80 | * FPU control word bit-field masks. |
| 984263bc | 81 | */ |
| 410233b2 PA |
82 | #define FP_MSKS_FLD 0x3f /* exception masks field */ |
| 83 | #define FP_PRC_FLD 0x300 /* precision control field */ | |
| 84 | #define FP_RND_FLD 0xc00 /* rounding control field */ | |
| 984263bc MD |
85 | |
| 86 | /* | |
| 410233b2 | 87 | * FPU status word bit-field masks. |
| 984263bc | 88 | */ |
| 984263bc MD |
89 | #define FP_STKY_FLD 0x3f /* sticky flags field */ |
| 90 | ||
| 91 | /* | |
| 410233b2 | 92 | * FPU control word bit-field offsets (shift counts). |
| 984263bc MD |
93 | */ |
| 94 | #define FP_MSKS_OFF 0 /* exception masks offset */ | |
| 95 | #define FP_PRC_OFF 8 /* precision control offset */ | |
| 410233b2 PA |
96 | #define FP_RND_OFF 10 /* rounding control offset */ |
| 97 | ||
| 98 | /* | |
| 99 | * FPU status word bit-field offsets (shift counts). | |
| 100 | */ | |
| 984263bc MD |
101 | #define FP_STKY_OFF 0 /* sticky flags offset */ |
| 102 | ||
| fe667cd2 PA |
103 | #ifdef __GNUC__ |
| 104 | ||
| 5a8d63ad PA |
105 | #define _fldcw(addr) __asm __volatile("fldcw %0" : : "m" (*(addr))) |
| 106 | #define _fldenv(addr) __asm __volatile("fldenv %0" : : "m" (*(addr))) | |
| 107 | #define _fnclex() __asm __volatile("fnclex") | |
| 108 | #define _fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr))) | |
| 109 | #define _fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr))) | |
| 110 | #define _fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr))) | |
| fe667cd2 PA |
111 | |
| 112 | /* | |
| 410233b2 PA |
113 | * Load the control word. Be careful not to trap if there is a currently |
| 114 | * unmasked exception (ones that will become freshly unmasked are not a | |
| 115 | * problem). This case must be handled by a save/restore of the | |
| 116 | * environment or even of the full x87 state. Accessing the environment | |
| 117 | * is very inefficient, so only do it when necessary. | |
| fe667cd2 | 118 | */ |
| 410233b2 | 119 | static __inline void |
| 5a8d63ad | 120 | _fnldcw(unsigned short _cw, unsigned short _newcw) |
| fe667cd2 | 121 | { |
| 410233b2 PA |
122 | struct { |
| 123 | unsigned _cw; | |
| 124 | unsigned _other[6]; | |
| 125 | } _env; | |
| 126 | unsigned short _sw; | |
| 127 | ||
| 128 | if ((_cw & FP_MSKS_FLD) != FP_MSKS_FLD) { | |
| 5a8d63ad | 129 | _fnstsw(&_sw); |
| 410233b2 | 130 | if (((_sw & ~_cw) & FP_STKY_FLD) != 0) { |
| 5a8d63ad | 131 | _fnstenv(&_env); |
| 410233b2 | 132 | _env._cw = _newcw; |
| 5a8d63ad | 133 | _fldenv(&_env); |
| 410233b2 PA |
134 | return; |
| 135 | } | |
| fe667cd2 | 136 | } |
| 5a8d63ad | 137 | _fldcw(&_newcw); |
| fe667cd2 PA |
138 | } |
| 139 | ||
| 410233b2 PA |
140 | static __inline fp_rnd_t |
| 141 | fpgetround(void) | |
| fe667cd2 | 142 | { |
| 410233b2 PA |
143 | unsigned short _cw; |
| 144 | ||
| 5a8d63ad | 145 | _fnstcw(&_cw); |
| 410233b2 | 146 | return ((fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF)); |
| fe667cd2 PA |
147 | } |
| 148 | ||
| 410233b2 PA |
149 | static __inline fp_rnd_t |
| 150 | fpsetround(fp_rnd_t _m) | |
| 151 | { | |
| 152 | fp_rnd_t _p; | |
| 153 | unsigned short _cw, _newcw; | |
| 154 | ||
| 5a8d63ad | 155 | _fnstcw(&_cw); |
| 410233b2 PA |
156 | _p = (fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF); |
| 157 | _newcw = _cw & ~FP_RND_FLD; | |
| 158 | _newcw |= (_m << FP_RND_OFF) & FP_RND_FLD; | |
| 5a8d63ad | 159 | _fnldcw(_cw, _newcw); |
| 410233b2 PA |
160 | return (_p); |
| 161 | } | |
| 162 | ||
| 163 | static __inline fp_prec_t | |
| 164 | fpgetprec(void) | |
| 165 | { | |
| 166 | unsigned short _cw; | |
| 167 | ||
| 5a8d63ad | 168 | _fnstcw(&_cw); |
| 410233b2 PA |
169 | return ((fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF)); |
| 170 | } | |
| 171 | ||
| 172 | static __inline fp_prec_t | |
| 173 | fpsetprec(fp_prec_t _m) | |
| 174 | { | |
| 175 | fp_prec_t _p; | |
| 176 | unsigned short _cw, _newcw; | |
| 177 | ||
| 5a8d63ad | 178 | _fnstcw(&_cw); |
| 410233b2 PA |
179 | _p = (fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF); |
| 180 | _newcw = _cw & ~FP_PRC_FLD; | |
| 181 | _newcw |= (_m << FP_PRC_OFF) & FP_PRC_FLD; | |
| 5a8d63ad | 182 | _fnldcw(_cw, _newcw); |
| 410233b2 PA |
183 | return (_p); |
| 184 | } | |
| fe667cd2 PA |
185 | |
| 186 | /* | |
| 410233b2 PA |
187 | * Get or set the exception mask. |
| 188 | * Note that the x87 mask bits are inverted by the API -- a mask bit of 1 | |
| 189 | * means disable for x87 and SSE, but for fp*mask() it means enable. | |
| fe667cd2 | 190 | */ |
| 410233b2 PA |
191 | |
| 192 | static __inline fp_except_t | |
| 193 | fpgetmask(void) | |
| 194 | { | |
| 195 | unsigned short _cw; | |
| 196 | ||
| 5a8d63ad | 197 | _fnstcw(&_cw); |
| 410233b2 PA |
198 | return ((~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF); |
| 199 | } | |
| 200 | ||
| 201 | static __inline fp_except_t | |
| 202 | fpsetmask(fp_except_t _m) | |
| 203 | { | |
| 204 | fp_except_t _p; | |
| 205 | unsigned short _cw, _newcw; | |
| 206 | ||
| 5a8d63ad | 207 | _fnstcw(&_cw); |
| 410233b2 PA |
208 | _p = (~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF; |
| 209 | _newcw = _cw & ~FP_MSKS_FLD; | |
| 210 | _newcw |= (~_m << FP_MSKS_OFF) & FP_MSKS_FLD; | |
| 5a8d63ad | 211 | _fnldcw(_cw, _newcw); |
| 410233b2 PA |
212 | return (_p); |
| 213 | } | |
| 214 | ||
| 215 | static __inline fp_except_t | |
| 216 | fpgetsticky(void) | |
| 217 | { | |
| 218 | unsigned _ex; | |
| 219 | unsigned short _sw; | |
| 220 | ||
| 5a8d63ad | 221 | _fnstsw(&_sw); |
| 410233b2 PA |
222 | _ex = (_sw & FP_STKY_FLD) >> FP_STKY_OFF; |
| 223 | return ((fp_except_t)_ex); | |
| 224 | } | |
| 225 | ||
| 226 | static __inline fp_except_t | |
| 227 | fpresetsticky(fp_except_t _m) | |
| 228 | { | |
| 229 | struct { | |
| 230 | unsigned _cw; | |
| 231 | unsigned _sw; | |
| 232 | unsigned _other[5]; | |
| 233 | } _env; | |
| 234 | fp_except_t _p; | |
| 235 | ||
| 236 | _m &= FP_STKY_FLD >> FP_STKY_OFF; | |
| 237 | _p = fpgetsticky(); | |
| 238 | if ((_p & ~_m) == _p) | |
| 239 | return (_p); | |
| 240 | if ((_p & ~_m) == 0) { | |
| 5a8d63ad | 241 | _fnclex(); |
| 410233b2 PA |
242 | return (_p); |
| 243 | } | |
| 5a8d63ad | 244 | _fnstenv(&_env); |
| 410233b2 | 245 | _env._sw &= ~_m; |
| 5a8d63ad | 246 | _fldenv(&_env); |
| 410233b2 PA |
247 | return (_p); |
| 248 | } | |
| 249 | ||
| 250 | #endif /* __GNUC__ */ | |
| fe667cd2 PA |
251 | |
| 252 | /* Suppress prototypes in the MI header. */ | |
| 253 | #define _IEEEFP_INLINED_ 1 | |
| 254 | ||
| 88181b08 | 255 | #endif /* !_CPU_IEEEFP_H_ */ |