1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #ifndef _FENV_H_ 32 #define _FENV_H_ 33 34 #include <sys/_types.h> 35 36 #ifndef __fenv_static 37 #define __fenv_static static 38 #endif 39 40 typedef __uint32_t fenv_t; 41 typedef __uint32_t fexcept_t; 42 43 /* Exception flags */ 44 #define FE_INVALID 0x0001 45 #define FE_DIVBYZERO 0x0002 46 #define FE_OVERFLOW 0x0004 47 #define FE_UNDERFLOW 0x0008 48 #define FE_INEXACT 0x0010 49 #ifdef __ARM_PCS_VFP 50 #define FE_DENORMAL 0x0080 51 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 52 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL) 53 #else 54 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ 55 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) 56 #endif 57 58 /* Rounding modes */ 59 #define VFP_FE_TONEAREST 0x00000000 60 #define VFP_FE_UPWARD 0x00400000 61 #define VFP_FE_DOWNWARD 0x00800000 62 #define VFP_FE_TOWARDZERO 0x00c00000 63 64 #ifdef __ARM_PCS_VFP 65 #define FE_TONEAREST VFP_FE_TONEAREST 66 #define FE_UPWARD VFP_FE_UPWARD 67 #define FE_DOWNWARD VFP_FE_DOWNWARD 68 #define FE_TOWARDZERO VFP_FE_TOWARDZERO 69 #else 70 #define FE_TONEAREST 0x0000 71 #define FE_TOWARDZERO 0x0001 72 #define FE_UPWARD 0x0002 73 #define FE_DOWNWARD 0x0003 74 #endif 75 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ 76 FE_UPWARD | FE_TOWARDZERO) 77 __BEGIN_DECLS 78 79 /* Default floating-point environment */ 80 extern const fenv_t __fe_dfl_env; 81 #define FE_DFL_ENV (&__fe_dfl_env) 82 83 /* We need to be able to map status flag positions to mask flag positions */ 84 #ifndef __ARM_PCS_VFP 85 #define _FPUSW_SHIFT 16 86 #define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) 87 #endif 88 89 #ifndef __ARM_PCS_VFP 90 91 int feclearexcept(int __excepts); 92 int fegetexceptflag(fexcept_t *__flagp, int __excepts); 93 int fesetexceptflag(const fexcept_t *__flagp, int __excepts); 94 int feraiseexcept(int __excepts); 95 int fetestexcept(int __excepts); 96 int fegetround(void); 97 int fesetround(int __round); 98 int fegetenv(fenv_t *__envp); 99 int feholdexcept(fenv_t *__envp); 100 int fesetenv(const fenv_t *__envp); 101 int feupdateenv(const fenv_t *__envp); 102 #if __BSD_VISIBLE 103 int feenableexcept(int __mask); 104 int fedisableexcept(int __mask); 105 int fegetexcept(void); 106 #endif 107 108 #else /* __ARM_PCS_VFP */ 109 110 #define vmrs_fpscr(__r) __asm __volatile("vmrs %0, fpscr" : "=&r"(__r)) 111 #define vmsr_fpscr(__r) __asm __volatile("vmsr fpscr, %0" : : "r"(__r)) 112 113 #define _FPU_MASK_SHIFT 8 114 115 __fenv_static inline int 116 feclearexcept(int __excepts) 117 { 118 fexcept_t __fpsr; 119 120 vmrs_fpscr(__fpsr); 121 __fpsr &= ~__excepts; 122 vmsr_fpscr(__fpsr); 123 return (0); 124 } 125 126 __fenv_static inline int 127 fegetexceptflag(fexcept_t *__flagp, int __excepts) 128 { 129 fexcept_t __fpsr; 130 131 vmrs_fpscr(__fpsr); 132 *__flagp = __fpsr & __excepts; 133 return (0); 134 } 135 136 __fenv_static inline int 137 fesetexceptflag(const fexcept_t *__flagp, int __excepts) 138 { 139 fexcept_t __fpsr; 140 141 vmrs_fpscr(__fpsr); 142 __fpsr &= ~__excepts; 143 __fpsr |= *__flagp & __excepts; 144 vmsr_fpscr(__fpsr); 145 return (0); 146 } 147 148 __fenv_static inline int 149 feraiseexcept(int __excepts) 150 { 151 fexcept_t __ex = __excepts; 152 153 fesetexceptflag(&__ex, __excepts); /* XXX */ 154 return (0); 155 } 156 157 __fenv_static inline int 158 fetestexcept(int __excepts) 159 { 160 fexcept_t __fpsr; 161 162 vmrs_fpscr(__fpsr); 163 return (__fpsr & __excepts); 164 } 165 166 __fenv_static inline int 167 fegetround(void) 168 { 169 fenv_t __fpsr; 170 171 vmrs_fpscr(__fpsr); 172 return (__fpsr & _ROUND_MASK); 173 } 174 175 __fenv_static inline int 176 fesetround(int __round) 177 { 178 fenv_t __fpsr; 179 180 vmrs_fpscr(__fpsr); 181 __fpsr &= ~(_ROUND_MASK); 182 __fpsr |= __round; 183 vmsr_fpscr(__fpsr); 184 return (0); 185 } 186 187 __fenv_static inline int 188 fegetenv(fenv_t *__envp) 189 { 190 191 vmrs_fpscr(*__envp); 192 return (0); 193 } 194 195 __fenv_static inline int 196 feholdexcept(fenv_t *__envp) 197 { 198 fenv_t __env; 199 200 vmrs_fpscr(__env); 201 *__envp = __env; 202 __env &= ~(FE_ALL_EXCEPT); 203 vmsr_fpscr(__env); 204 return (0); 205 } 206 207 __fenv_static inline int 208 fesetenv(const fenv_t *__envp) 209 { 210 211 vmsr_fpscr(*__envp); 212 return (0); 213 } 214 215 __fenv_static inline int 216 feupdateenv(const fenv_t *__envp) 217 { 218 fexcept_t __fpsr; 219 220 vmrs_fpscr(__fpsr); 221 vmsr_fpscr(*__envp); 222 feraiseexcept(__fpsr & FE_ALL_EXCEPT); 223 return (0); 224 } 225 226 #if __BSD_VISIBLE 227 228 /* We currently provide no external definitions of the functions below. */ 229 230 __fenv_static inline int 231 feenableexcept(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 fedisableexcept(int __mask) 244 { 245 fenv_t __old_fpsr, __new_fpsr; 246 247 vmrs_fpscr(__old_fpsr); 248 __new_fpsr = __old_fpsr & 249 ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT); 250 vmsr_fpscr(__new_fpsr); 251 return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT); 252 } 253 254 __fenv_static inline int 255 fegetexcept(void) 256 { 257 fenv_t __fpsr; 258 259 vmrs_fpscr(__fpsr); 260 return (__fpsr & FE_ALL_EXCEPT); 261 } 262 263 #endif /* __BSD_VISIBLE */ 264 265 #endif /* __ARM_PCS_VFP */ 266 267 __END_DECLS 268 269 #endif /* !_FENV_H_ */ 270