fenv.h revision 140219
1/*- 2 * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/lib/msun/i387/fenv.h 140219 2005-01-14 07:09:23Z das $ 27 */ 28 29#ifndef _FENV_H_ 30#define _FENV_H_ 31 32#include <sys/cdefs.h> 33#include <sys/_types.h> 34 35typedef struct { 36 __uint32_t __control; 37 __uint32_t __status; 38 __uint32_t __tag; 39 char __other[16]; 40} fenv_t; 41 42typedef __uint16_t fexcept_t; 43 44/* Exception flags */ 45#define FE_INVALID 0x01 46#define FE_DENORMAL 0x02 47#define FE_DIVBYZERO 0x04 48#define FE_OVERFLOW 0x08 49#define FE_UNDERFLOW 0x10 50#define FE_INEXACT 0x20 51#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \ 52 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 53 54/* Rounding modes */ 55#define FE_TONEAREST 0x0000 56#define FE_DOWNWARD 0x0400 57#define FE_UPWARD 0x0800 58#define FE_TOWARDZERO 0x0c00 59#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 60 FE_UPWARD | FE_TOWARDZERO) 61 62__BEGIN_DECLS 63 64/* Default floating-point environment */ 65extern const fenv_t __fe_dfl_env; 66#define FE_DFL_ENV (&__fe_dfl_env) 67 68#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw)) 69#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env)) 70#define __fnclex() __asm __volatile("fnclex") 71#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env))) 72#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw))) 73#define __fnstsw(__sw) __asm __volatile("fnstsw %0" : "=am" (*(__sw))) 74#define __fwait() __asm __volatile("fwait") 75 76static __inline int 77feclearexcept(int __excepts) 78{ 79 fenv_t __env; 80 81 if (__excepts == FE_ALL_EXCEPT) { 82 __fnclex(); 83 } else { 84 __fnstenv(&__env); 85 __env.__status &= ~__excepts; 86 __fldenv(__env); 87 } 88 return (0); 89} 90 91static __inline int 92fegetexceptflag(fexcept_t *__flagp, int __excepts) 93{ 94 int __status; 95 96 __fnstsw(&__status); 97 *__flagp = __status & __excepts; 98 return (0); 99} 100 101static __inline int 102fesetexceptflag(const fexcept_t *__flagp, int __excepts) 103{ 104 fenv_t __env; 105 106 __fnstenv(&__env); 107 __env.__status &= ~__excepts; 108 __env.__status |= *__flagp & __excepts; 109 __fldenv(__env); 110 return (0); 111} 112 113static __inline int 114feraiseexcept(int __excepts) 115{ 116 fexcept_t __ex = __excepts; 117 118 fesetexceptflag(&__ex, __excepts); 119 __fwait(); 120 return (0); 121} 122 123static __inline int 124fetestexcept(int __excepts) 125{ 126 int __status; 127 128 __fnstsw(&__status); 129 return (__status & __excepts); 130} 131 132static __inline int 133fegetround(void) 134{ 135 int __control; 136 137 __fnstcw(&__control); 138 return (__control & _ROUND_MASK); 139} 140 141static __inline int 142fesetround(int __round) 143{ 144 int __control; 145 146 if (__round & ~_ROUND_MASK) 147 return (-1); 148 __fnstcw(&__control); 149 __control &= ~_ROUND_MASK; 150 __control |= __round; 151 __fldcw(__control); 152 return (0); 153} 154 155static __inline int 156fegetenv(fenv_t *__envp) 157{ 158 int __control; 159 160 /* 161 * fnstenv masks all exceptions, so we need to save and 162 * restore the control word to avoid this side effect. 163 */ 164 __fnstcw(&__control); 165 __fnstenv(__envp); 166 __fldcw(__control); 167 return (0); 168} 169 170static __inline int 171feholdexcept(fenv_t *__envp) 172{ 173 174 __fnstenv(__envp); 175 __fnclex(); 176 return (0); 177} 178 179static __inline int 180fesetenv(const fenv_t *__envp) 181{ 182 183 __fldenv(*__envp); 184 return (0); 185} 186 187static __inline int 188feupdateenv(const fenv_t *__envp) 189{ 190 int __status; 191 192 __fnstsw(&__status); 193 __fldenv(*__envp); 194 feraiseexcept(__status & FE_ALL_EXCEPT); 195 return (0); 196} 197 198#if __BSD_VISIBLE 199 200static __inline int 201fesetmask(int __mask) 202{ 203 int __control; 204 205 __fnstcw(&__control); 206 __mask = (__control | FE_ALL_EXCEPT) & ~__mask; 207 __fldcw(__mask); 208 return (~__control & FE_ALL_EXCEPT); 209} 210 211static __inline int 212fegetmask(void) 213{ 214 int __control; 215 216 __fnstcw(&__control); 217 return (~__control & FE_ALL_EXCEPT); 218} 219 220#endif /* __BSD_VISIBLE */ 221 222__END_DECLS 223 224#endif /* !_FENV_H_ */ 225