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