1 /*- 2 * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG> 3 * Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG> 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 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 #define __fenv_static 31 #include "fenv.h" 32 33 /* When SOFTFP_ABI is defined we are using the softfp ABI. */ 34 #if defined(__VFP_FP__) && !defined(__ARM_PCS_VFP) 35 #define SOFTFP_ABI 36 #endif 37 38 39 #ifndef FENV_MANGLE 40 /* 41 * Hopefully the system ID byte is immutable, so it's valid to use 42 * this as a default environment. 43 */ 44 const fenv_t __fe_dfl_env = 0; 45 #endif 46 47 48 /* If this is a non-mangled softfp version special processing is required */ 49 #if defined(FENV_MANGLE) || !defined(SOFTFP_ABI) 50 51 /* 52 * The following macros map between the softfloat emulator's flags and 53 * the hardware's FPSR. The hardware this file was written for doesn't 54 * have rounding control bits, so we stick those in the system ID byte. 55 */ 56 #ifndef __ARM_PCS_VFP 57 #define __set_env(env, flags, mask, rnd) env = ((flags) \ 58 | (mask)<<_FPUSW_SHIFT \ 59 | (rnd) << 24) 60 #define __env_flags(env) ((env) & FE_ALL_EXCEPT) 61 #define __env_mask(env) (((env) >> _FPUSW_SHIFT) \ 62 & FE_ALL_EXCEPT) 63 #define __env_round(env) (((env) >> 24) & _ROUND_MASK) 64 #include "fenv-softfloat.h" 65 #endif 66 67 #ifdef __GNUC_GNU_INLINE__ 68 #error "This file must be compiled with C99 'inline' semantics" 69 #endif 70 71 extern inline int feclearexcept(int __excepts); 72 extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts); 73 extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts); 74 extern inline int feraiseexcept(int __excepts); 75 extern inline int fetestexcept(int __excepts); 76 extern inline int fegetround(void); 77 extern inline int fesetround(int __round); 78 extern inline int fegetenv(fenv_t *__envp); 79 extern inline int feholdexcept(fenv_t *__envp); 80 extern inline int fesetenv(const fenv_t *__envp); 81 extern inline int feupdateenv(const fenv_t *__envp); 82 extern inline int feenableexcept(int __mask); 83 extern inline int fedisableexcept(int __mask); 84 extern inline int fegetexcept(void); 85 86 #else /* !FENV_MANGLE && SOFTFP_ABI */ 87 /* Set by libc when the VFP unit is enabled */ 88 extern int _libc_arm_fpu_present; 89 90 int __softfp_feclearexcept(int __excepts); 91 int __softfp_fegetexceptflag(fexcept_t *__flagp, int __excepts); 92 int __softfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts); 93 int __softfp_feraiseexcept(int __excepts); 94 int __softfp_fetestexcept(int __excepts); 95 int __softfp_fegetround(void); 96 int __softfp_fesetround(int __round); 97 int __softfp_fegetenv(fenv_t *__envp); 98 int __softfp_feholdexcept(fenv_t *__envp); 99 int __softfp_fesetenv(const fenv_t *__envp); 100 int __softfp_feupdateenv(const fenv_t *__envp); 101 int __softfp_feenableexcept(int __mask); 102 int __softfp_fedisableexcept(int __mask); 103 int __softfp_fegetexcept(void); 104 105 int __vfp_feclearexcept(int __excepts); 106 int __vfp_fegetexceptflag(fexcept_t *__flagp, int __excepts); 107 int __vfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts); 108 int __vfp_feraiseexcept(int __excepts); 109 int __vfp_fetestexcept(int __excepts); 110 int __vfp_fegetround(void); 111 int __vfp_fesetround(int __round); 112 int __vfp_fegetenv(fenv_t *__envp); 113 int __vfp_feholdexcept(fenv_t *__envp); 114 int __vfp_fesetenv(const fenv_t *__envp); 115 int __vfp_feupdateenv(const fenv_t *__envp); 116 int __vfp_feenableexcept(int __mask); 117 int __vfp_fedisableexcept(int __mask); 118 int __vfp_fegetexcept(void); 119 120 static int 121 __softfp_round_to_vfp(int round) 122 { 123 124 switch (round) { 125 case FE_TONEAREST: 126 default: 127 return VFP_FE_TONEAREST; 128 case FE_TOWARDZERO: 129 return VFP_FE_TOWARDZERO; 130 case FE_UPWARD: 131 return VFP_FE_UPWARD; 132 case FE_DOWNWARD: 133 return VFP_FE_DOWNWARD; 134 } 135 } 136 137 static int 138 __softfp_round_from_vfp(int round) 139 { 140 141 switch (round) { 142 case VFP_FE_TONEAREST: 143 default: 144 return FE_TONEAREST; 145 case VFP_FE_TOWARDZERO: 146 return FE_TOWARDZERO; 147 case VFP_FE_UPWARD: 148 return FE_UPWARD; 149 case VFP_FE_DOWNWARD: 150 return FE_DOWNWARD; 151 } 152 } 153 154 int feclearexcept(int __excepts) 155 { 156 157 if (_libc_arm_fpu_present) 158 __vfp_feclearexcept(__excepts); 159 __softfp_feclearexcept(__excepts); 160 161 return (0); 162 } 163 164 int fegetexceptflag(fexcept_t *__flagp, int __excepts) 165 { 166 fexcept_t __vfp_flagp; 167 168 __vfp_flagp = 0; 169 if (_libc_arm_fpu_present) 170 __vfp_fegetexceptflag(&__vfp_flagp, __excepts); 171 __softfp_fegetexceptflag(__flagp, __excepts); 172 173 *__flagp |= __vfp_flagp; 174 175 return (0); 176 } 177 178 int fesetexceptflag(const fexcept_t *__flagp, int __excepts) 179 { 180 181 if (_libc_arm_fpu_present) 182 __vfp_fesetexceptflag(__flagp, __excepts); 183 __softfp_fesetexceptflag(__flagp, __excepts); 184 185 return (0); 186 } 187 188 int feraiseexcept(int __excepts) 189 { 190 191 if (_libc_arm_fpu_present) 192 __vfp_feraiseexcept(__excepts); 193 __softfp_feraiseexcept(__excepts); 194 195 return (0); 196 } 197 198 int fetestexcept(int __excepts) 199 { 200 int __got_excepts; 201 202 __got_excepts = 0; 203 if (_libc_arm_fpu_present) 204 __got_excepts = __vfp_fetestexcept(__excepts); 205 __got_excepts |= __softfp_fetestexcept(__excepts); 206 207 return (__got_excepts); 208 } 209 210 int fegetround(void) 211 { 212 213 if (_libc_arm_fpu_present) 214 return __softfp_round_from_vfp(__vfp_fegetround()); 215 return __softfp_fegetround(); 216 } 217 218 int fesetround(int __round) 219 { 220 221 if (_libc_arm_fpu_present) 222 __vfp_fesetround(__softfp_round_to_vfp(__round)); 223 __softfp_fesetround(__round); 224 225 return (0); 226 } 227 228 int fegetenv(fenv_t *__envp) 229 { 230 fenv_t __vfp_envp; 231 232 __vfp_envp = 0; 233 if (_libc_arm_fpu_present) 234 __vfp_fegetenv(&__vfp_envp); 235 __softfp_fegetenv(__envp); 236 *__envp |= __vfp_envp; 237 238 return (0); 239 } 240 241 int feholdexcept(fenv_t *__envp) 242 { 243 fenv_t __vfp_envp; 244 245 __vfp_envp = 0; 246 if (_libc_arm_fpu_present) 247 __vfp_feholdexcept(&__vfp_envp); 248 __softfp_feholdexcept(__envp); 249 *__envp |= __vfp_envp; 250 251 return (0); 252 } 253 254 int fesetenv(const fenv_t *__envp) 255 { 256 257 if (_libc_arm_fpu_present) 258 __vfp_fesetenv(__envp); 259 __softfp_fesetenv(__envp); 260 261 return (0); 262 } 263 264 int feupdateenv(const fenv_t *__envp) 265 { 266 267 if (_libc_arm_fpu_present) 268 __vfp_feupdateenv(__envp); 269 __softfp_feupdateenv(__envp); 270 271 return (0); 272 } 273 274 int feenableexcept(int __mask) 275 { 276 int __unmasked; 277 278 __unmasked = 0; 279 if (_libc_arm_fpu_present) 280 __unmasked = __vfp_feenableexcept(__mask); 281 __unmasked |= __softfp_feenableexcept(__mask); 282 283 return (__unmasked); 284 } 285 286 int fedisableexcept(int __mask) 287 { 288 int __unmasked; 289 290 __unmasked = 0; 291 if (_libc_arm_fpu_present) 292 __unmasked = __vfp_fedisableexcept(__mask); 293 __unmasked |= __softfp_fedisableexcept(__mask); 294 295 return (__unmasked); 296 } 297 298 int fegetexcept(void) 299 { 300 int __unmasked; 301 302 __unmasked = 0; 303 if (_libc_arm_fpu_present) 304 __unmasked = __vfp_fegetexcept(); 305 __unmasked |= __softfp_fegetexcept(); 306 307 return (__unmasked); 308 } 309 310 #endif 311 312