1 /*- 2 * Copyright (c) 2004-2005 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$ 27 */ 28 29 #ifndef _FENV_H_ 30 #define _FENV_H_ 31 32 #include <sys/_types.h> 33 34 #ifndef __fenv_static 35 #define __fenv_static static 36 #endif 37 38 typedef __uint32_t fenv_t; 39 typedef __uint32_t fexcept_t; 40 41 /* Exception flags */ 42 #define FE_INVALID 0x0001 43 #define FE_DIVBYZERO 0x0002 44 #define FE_OVERFLOW 0x0004 45 #define FE_UNDERFLOW 0x0008 46 #define FE_INEXACT 0x0010 47 #ifdef __ARM_PCS_VFP 48 #define FE_DENORMAL 0x0080 49 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 50 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL) 51 #else 52 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 53 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 54 #endif 55 56 /* Rounding modes */ 57 #ifdef __ARM_PCS_VFP 58 #define FE_TONEAREST 0x00000000 59 #define FE_UPWARD 0x00400000 60 #define FE_DOWNWARD 0x00800000 61 #define FE_TOWARDZERO 0x00c00000 62 #else 63 #define FE_TONEAREST 0x0000 64 #define FE_TOWARDZERO 0x0001 65 #define FE_UPWARD 0x0002 66 #define FE_DOWNWARD 0x0003 67 #endif 68 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 69 FE_UPWARD | FE_TOWARDZERO) 70 __BEGIN_DECLS 71 72 /* Default floating-point environment */ 73 extern const fenv_t __fe_dfl_env; 74 #define FE_DFL_ENV (&__fe_dfl_env) 75 76 /* We need to be able to map status flag positions to mask flag positions */ 77 #ifndef __ARM_PCS_VFP 78 #define _FPUSW_SHIFT 16 79 #define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) 80 #endif 81 82 #ifndef __ARM_PCS_VFP 83 84 int feclearexcept(int __excepts); 85 int fegetexceptflag(fexcept_t *__flagp, int __excepts); 86 int fesetexceptflag(const fexcept_t *__flagp, int __excepts); 87 int feraiseexcept(int __excepts); 88 int fetestexcept(int __excepts); 89 int fegetround(void); 90 int fesetround(int __round); 91 int fegetenv(fenv_t *__envp); 92 int feholdexcept(fenv_t *__envp); 93 int fesetenv(const fenv_t *__envp); 94 int feupdateenv(const fenv_t *__envp); 95 96 #else /* __ARM_PCS_VFP */ 97 98 #define vmrs_fpscr(__r) __asm __volatile("vmrs %0, fpscr" : "=&r"(__r)) 99 #define vmsr_fpscr(__r) __asm __volatile("vmsr fpscr, %0" : : "r"(__r)) 100 101 #define _FPU_MASK_SHIFT 8 102 103 __fenv_static inline int 104 feclearexcept(int __excepts) 105 { 106 fexcept_t __fpsr; 107 108 vmrs_fpscr(__fpsr); 109 __fpsr &= ~__excepts; 110 vmsr_fpscr(__fpsr); 111 return (0); 112 } 113 114 __fenv_static inline int 115 fegetexceptflag(fexcept_t *__flagp, int __excepts) 116 { 117 fexcept_t __fpsr; 118 119 vmrs_fpscr(__fpsr); 120 *__flagp = __fpsr & __excepts; 121 return (0); 122 } 123 124 __fenv_static inline int 125 fesetexceptflag(const fexcept_t *__flagp, int __excepts) 126 { 127 fexcept_t __fpsr; 128 129 vmrs_fpscr(__fpsr); 130 __fpsr &= ~__excepts; 131 __fpsr |= *__flagp & __excepts; 132 vmsr_fpscr(__fpsr); 133 return (0); 134 } 135 136 __fenv_static inline int 137 feraiseexcept(int __excepts) 138 { 139 fexcept_t __ex = __excepts; 140 141 fesetexceptflag(&__ex, __excepts); /* XXX */ 142 return (0); 143 } 144 145 __fenv_static inline int 146 fetestexcept(int __excepts) 147 { 148 fexcept_t __fpsr; 149 150 vmrs_fpscr(__fpsr); 151 return (__fpsr & __excepts); 152 } 153 154 __fenv_static inline int 155 fegetround(void) 156 { 157 fenv_t __fpsr; 158 159 vmrs_fpscr(__fpsr); 160 return (__fpsr & _ROUND_MASK); 161 } 162 163 __fenv_static inline int 164 fesetround(int __round) 165 { 166 fenv_t __fpsr; 167 168 vmrs_fpscr(__fpsr); 169 __fpsr &= ~(_ROUND_MASK); 170 __fpsr |= __round; 171 vmsr_fpscr(__fpsr); 172 return (0); 173 } 174 175 __fenv_static inline int 176 fegetenv(fenv_t *__envp) 177 { 178 179 vmrs_fpscr(*__envp); 180 return (0); 181 } 182 183 __fenv_static inline int 184 feholdexcept(fenv_t *__envp) 185 { 186 fenv_t __env; 187 188 vmrs_fpscr(__env); 189 *__envp = __env; 190 __env &= ~(FE_ALL_EXCEPT); 191 vmsr_fpscr(__env); 192 return (0); 193 } 194 195 __fenv_static inline int 196 fesetenv(const fenv_t *__envp) 197 { 198 199 vmsr_fpscr(*__envp); 200 return (0); 201 } 202 203 __fenv_static inline int 204 feupdateenv(const fenv_t *__envp) 205 { 206 fexcept_t __fpsr; 207 208 vmrs_fpscr(__fpsr); 209 vmsr_fpscr(*__envp); 210 feraiseexcept(__fpsr & FE_ALL_EXCEPT); 211 return (0); 212 } 213 214 #if __BSD_VISIBLE 215 216 /* We currently provide no external definitions of the functions below. */ 217 218 __fenv_static inline int 219 feenableexcept(int __mask) 220 { 221 fenv_t __old_fpsr, __new_fpsr; 222 223 vmrs_fpscr(__old_fpsr); 224 __new_fpsr = __old_fpsr | 225 ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); 226 vmsr_fpscr(__new_fpsr); 227 return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); 228 } 229 230 __fenv_static inline int 231 fedisableexcept(int __mask) 232 { 233 fenv_t __old_fpsr, __new_fpsr; 234 235 vmrs_fpscr(__old_fpsr); 236 __new_fpsr = __old_fpsr & 237 ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); 238 vmsr_fpscr(__new_fpsr); 239 return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); 240 } 241 242 __fenv_static inline int 243 fegetexcept(void) 244 { 245 fenv_t __fpsr; 246 247 vmrs_fpscr(__fpsr); 248 return (__fpsr & FE_ALL_EXCEPT); 249 } 250 251 #endif /* __BSD_VISIBLE */ 252 253 #endif /* __ARM_PCS_VFP */ 254 255 __END_DECLS 256 257 #endif /* !_FENV_H_ */ 258