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 __fenv_static inline int 102 feclearexcept(int __excepts) 103 { 104 fexcept_t __fpsr; 105 106 vmrs_fpscr(__fpsr); 107 __fpsr &= ~__excepts; 108 vmsr_fpscr(__fpsr); 109 return (0); 110 } 111 112 __fenv_static inline int 113 fegetexceptflag(fexcept_t *__flagp, int __excepts) 114 { 115 fexcept_t __fpsr; 116 117 vmrs_fpscr(__fpsr); 118 *__flagp = __fpsr & __excepts; 119 return (0); 120 } 121 122 __fenv_static inline int 123 fesetexceptflag(const fexcept_t *__flagp, int __excepts) 124 { 125 fexcept_t __fpsr; 126 127 vmrs_fpscr(__fpsr); 128 __fpsr &= ~__excepts; 129 __fpsr |= *__flagp & __excepts; 130 vmsr_fpscr(__fpsr); 131 return (0); 132 } 133 134 __fenv_static inline int 135 feraiseexcept(int __excepts) 136 { 137 fexcept_t __ex = __excepts; 138 139 fesetexceptflag(&__ex, __excepts); /* XXX */ 140 return (0); 141 } 142 143 __fenv_static inline int 144 fetestexcept(int __excepts) 145 { 146 fexcept_t __fpsr; 147 148 vmrs_fpscr(__fpsr); 149 return (__fpsr & __excepts); 150 } 151 152 __fenv_static inline int 153 fegetround(void) 154 { 155 fenv_t __fpsr; 156 157 vmrs_fpscr(__fpsr); 158 return (__fpsr & _ROUND_MASK); 159 } 160 161 __fenv_static inline int 162 fesetround(int __round) 163 { 164 fenv_t __fpsr; 165 166 vmrs_fpscr(__fpsr); 167 __fpsr &= ~(_ROUND_MASK); 168 __fpsr |= __round; 169 vmsr_fpscr(__fpsr); 170 return (0); 171 } 172 173 __fenv_static inline int 174 fegetenv(fenv_t *__envp) 175 { 176 177 vmrs_fpscr(*__envp); 178 return (0); 179 } 180 181 __fenv_static inline int 182 feholdexcept(fenv_t *__envp) 183 { 184 fenv_t __env; 185 186 vmrs_fpscr(__env); 187 *__envp = __env; 188 __env &= ~(FE_ALL_EXCEPT); 189 vmsr_fpscr(__env); 190 return (0); 191 } 192 193 __fenv_static inline int 194 fesetenv(const fenv_t *__envp) 195 { 196 197 vmsr_fpscr(*__envp); 198 return (0); 199 } 200 201 __fenv_static inline int 202 feupdateenv(const fenv_t *__envp) 203 { 204 fexcept_t __fpsr; 205 206 vmrs_fpscr(__fpsr); 207 vmsr_fpscr(*__envp); 208 feraiseexcept(__fpsr & FE_ALL_EXCEPT); 209 return (0); 210 } 211 212 #if __BSD_VISIBLE 213 214 /* We currently provide no external definitions of the functions below. */ 215 216 static inline int 217 feenableexcept(int __mask) 218 { 219 fenv_t __old_fpsr, __new_fpsr; 220 221 vmrs_fpscr(__old_fpsr); 222 __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT); 223 vmsr_fpscr(__new_fpsr); 224 return (__old_fpsr & FE_ALL_EXCEPT); 225 } 226 227 static inline int 228 fedisableexcept(int __mask) 229 { 230 fenv_t __old_fpsr, __new_fpsr; 231 232 vmrs_fpscr(__old_fpsr); 233 __new_fpsr = __old_fpsr & ~(__mask & FE_ALL_EXCEPT); 234 vmsr_fpscr(__new_fpsr); 235 return (__old_fpsr & FE_ALL_EXCEPT); 236 } 237 238 static inline int 239 fegetexcept(void) 240 { 241 fenv_t __fpsr; 242 243 vmrs_fpscr(__fpsr); 244 return (__fpsr & FE_ALL_EXCEPT); 245 } 246 247 #endif /* __BSD_VISIBLE */ 248 249 #endif /* __ARM_PCS_VFP */ 250 251 __END_DECLS 252 253 #endif /* !_FENV_H_ */ 254