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 #include "fenv.h" 31 32 #include <machine/acle-compat.h> 33 34 /* When SOFTFP_ABI is defined we are using the softfp ABI. */ 35 #if defined(__VFP_FP__) && !defined(__ARM_PCS_VFP) 36 #define SOFTFP_ABI 37 #endif 38 39 40 #ifndef FENV_MANGLE 41 /* 42 * Hopefully the system ID byte is immutable, so it's valid to use 43 * this as a default environment. 44 */ 45 const fenv_t __fe_dfl_env = 0; 46 const femode_t __fe_dfl_mode = 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 int 70 (feclearexcept)(int excepts) 71 { 72 return (__feclearexcept_int(excepts)); 73 } 74 75 int 76 (fegetexceptflag)(fexcept_t *flagp, int excepts) 77 { 78 return (__fegetexceptflag_int(flagp, excepts)); 79 } 80 81 int 82 (fesetexceptflag)(const fexcept_t *flagp, int excepts) 83 { 84 return (__fesetexceptflag_int(flagp, excepts)); 85 } 86 87 int 88 (feraiseexcept)(int excepts) 89 { 90 return (__feraiseexcept_int(excepts)); 91 } 92 93 int 94 (fetestexcept)(int excepts) 95 { 96 return (__fetestexcept_int(excepts)); 97 } 98 99 int 100 (fegetround)(void) 101 { 102 return (__fegetround_int()); 103 } 104 105 int 106 (fesetround)(int round) 107 { 108 return (__fesetround_int(round)); 109 } 110 111 int 112 (fegetmode)(femode_t *modep) 113 { 114 return (__fegetmode_int(modep)); 115 } 116 117 int 118 (fesetmode)(const femode_t *modep) 119 { 120 return (__fesetmode_int(modep)); 121 } 122 123 int 124 (fegetenv)(fenv_t *envp) 125 { 126 return (__fegetenv_int(envp)); 127 } 128 129 int 130 (feholdexcept)(fenv_t *envp) 131 { 132 return (__feholdexcept_int(envp)); 133 } 134 135 int 136 (fesetenv)(const fenv_t *envp) 137 { 138 return (__fesetenv_int(envp)); 139 } 140 141 int 142 (feupdateenv)(const fenv_t *envp) 143 { 144 return (__feupdateenv_int(envp)); 145 } 146 147 int 148 (feenableexcept)(int mask) 149 { 150 return (__feenableexcept_int(mask)); 151 } 152 153 int 154 (fedisableexcept)(int mask) 155 { 156 return (__fedisableexcept_int(mask)); 157 } 158 159 int 160 (fegetexcept)(void) 161 { 162 return (__fegetexcept_int()); 163 } 164 165 #else /* !FENV_MANGLE && SOFTFP_ABI */ 166 /* Set by libc when the VFP unit is enabled */ 167 extern int _libc_arm_fpu_present; 168 169 int __softfp_feclearexcept(int __excepts); 170 int __softfp_fegetexceptflag(fexcept_t *__flagp, int __excepts); 171 int __softfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts); 172 int __softfp_feraiseexcept(int __excepts); 173 int __softfp_fetestexcept(int __excepts); 174 int __softfp_fegetround(void); 175 int __softfp_fesetround(int __round); 176 int __softfp_fegetmode(femode_t *__modep); 177 int __softfp_fesetmode(const femode_t *__modep); 178 int __softfp_fegetenv(fenv_t *__envp); 179 int __softfp_feholdexcept(fenv_t *__envp); 180 int __softfp_fesetenv(const fenv_t *__envp); 181 int __softfp_feupdateenv(const fenv_t *__envp); 182 int __softfp_feenableexcept(int __mask); 183 int __softfp_fedisableexcept(int __mask); 184 int __softfp_fegetexcept(void); 185 186 int __vfp_feclearexcept(int __excepts); 187 int __vfp_fegetexceptflag(fexcept_t *__flagp, int __excepts); 188 int __vfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts); 189 int __vfp_feraiseexcept(int __excepts); 190 int __vfp_fetestexcept(int __excepts); 191 int __vfp_fegetround(void); 192 int __vfp_fesetround(int __round); 193 int __vfp_fegetmode(femode_t *__modep); 194 int __vfp_fesetmode(const femode_t *__modep); 195 int __vfp_fegetenv(fenv_t *__envp); 196 int __vfp_feholdexcept(fenv_t *__envp); 197 int __vfp_fesetenv(const fenv_t *__envp); 198 int __vfp_feupdateenv(const fenv_t *__envp); 199 int __vfp_feenableexcept(int __mask); 200 int __vfp_fedisableexcept(int __mask); 201 int __vfp_fegetexcept(void); 202 203 static int 204 __softfp_round_to_vfp(int round) 205 { 206 207 switch (round) { 208 case FE_TONEAREST: 209 default: 210 return VFP_FE_TONEAREST; 211 case FE_TOWARDZERO: 212 return VFP_FE_TOWARDZERO; 213 case FE_UPWARD: 214 return VFP_FE_UPWARD; 215 case FE_DOWNWARD: 216 return VFP_FE_DOWNWARD; 217 } 218 } 219 220 static int 221 __softfp_round_from_vfp(int round) 222 { 223 224 switch (round) { 225 case VFP_FE_TONEAREST: 226 default: 227 return FE_TONEAREST; 228 case VFP_FE_TOWARDZERO: 229 return FE_TOWARDZERO; 230 case VFP_FE_UPWARD: 231 return FE_UPWARD; 232 case VFP_FE_DOWNWARD: 233 return FE_DOWNWARD; 234 } 235 } 236 237 int 238 (feclearexcept)(int __excepts) 239 { 240 241 if (_libc_arm_fpu_present) 242 __vfp_feclearexcept(__excepts); 243 __softfp_feclearexcept(__excepts); 244 245 return (0); 246 } 247 248 int 249 (fegetexceptflag)(fexcept_t *__flagp, int __excepts) 250 { 251 fexcept_t __vfp_flagp; 252 253 __vfp_flagp = 0; 254 if (_libc_arm_fpu_present) 255 __vfp_fegetexceptflag(&__vfp_flagp, __excepts); 256 __softfp_fegetexceptflag(__flagp, __excepts); 257 258 *__flagp |= __vfp_flagp; 259 260 return (0); 261 } 262 263 int 264 (fesetexceptflag)(const fexcept_t *__flagp, int __excepts) 265 { 266 267 if (_libc_arm_fpu_present) 268 __vfp_fesetexceptflag(__flagp, __excepts); 269 __softfp_fesetexceptflag(__flagp, __excepts); 270 271 return (0); 272 } 273 274 int 275 (feraiseexcept)(int __excepts) 276 { 277 278 if (_libc_arm_fpu_present) 279 __vfp_feraiseexcept(__excepts); 280 __softfp_feraiseexcept(__excepts); 281 282 return (0); 283 } 284 285 int 286 (fetestexcept)(int __excepts) 287 { 288 int __got_excepts; 289 290 __got_excepts = 0; 291 if (_libc_arm_fpu_present) 292 __got_excepts = __vfp_fetestexcept(__excepts); 293 __got_excepts |= __softfp_fetestexcept(__excepts); 294 295 return (__got_excepts); 296 } 297 298 int 299 (fegetround)(void) 300 { 301 302 if (_libc_arm_fpu_present) 303 return __softfp_round_from_vfp(__vfp_fegetround()); 304 return __softfp_fegetround(); 305 } 306 307 int 308 (fesetround)(int __round) 309 { 310 311 if (_libc_arm_fpu_present) 312 __vfp_fesetround(__softfp_round_to_vfp(__round)); 313 __softfp_fesetround(__round); 314 315 return (0); 316 } 317 318 int 319 (fegetmode)(femode_t *__modep) 320 { 321 femode_t __vfp_modep; 322 323 __vfp_modep = 0; 324 if (_libc_arm_fpu_present) 325 __vfp_fegetmode(&__vfp_modep); 326 __softfp_fegetmode(__modep); 327 *__modep |= __vfp_modep; 328 329 return (0); 330 } 331 332 int 333 (fesetmode)(const femode_t *__modep) 334 { 335 336 if (_libc_arm_fpu_present) 337 __vfp_fesetmode(__modep); 338 __softfp_fesetmode(__modep); 339 340 return (0); 341 } 342 343 int 344 (fegetenv)(fenv_t *__envp) 345 { 346 fenv_t __vfp_envp; 347 348 __vfp_envp = 0; 349 if (_libc_arm_fpu_present) 350 __vfp_fegetenv(&__vfp_envp); 351 __softfp_fegetenv(__envp); 352 *__envp |= __vfp_envp; 353 354 return (0); 355 } 356 357 int 358 (feholdexcept)(fenv_t *__envp) 359 { 360 fenv_t __vfp_envp; 361 362 __vfp_envp = 0; 363 if (_libc_arm_fpu_present) 364 __vfp_feholdexcept(&__vfp_envp); 365 __softfp_feholdexcept(__envp); 366 *__envp |= __vfp_envp; 367 368 return (0); 369 } 370 371 int 372 (fesetenv)(const fenv_t *__envp) 373 { 374 375 if (_libc_arm_fpu_present) 376 __vfp_fesetenv(__envp); 377 __softfp_fesetenv(__envp); 378 379 return (0); 380 } 381 382 int 383 (feupdateenv)(const fenv_t *__envp) 384 { 385 386 if (_libc_arm_fpu_present) 387 __vfp_feupdateenv(__envp); 388 __softfp_feupdateenv(__envp); 389 390 return (0); 391 } 392 393 int 394 (feenableexcept)(int __mask) 395 { 396 int __unmasked; 397 398 __unmasked = 0; 399 if (_libc_arm_fpu_present) 400 __unmasked = __vfp_feenableexcept(__mask); 401 __unmasked |= __softfp_feenableexcept(__mask); 402 403 return (__unmasked); 404 } 405 406 int 407 (fedisableexcept)(int __mask) 408 { 409 int __unmasked; 410 411 __unmasked = 0; 412 if (_libc_arm_fpu_present) 413 __unmasked = __vfp_fedisableexcept(__mask); 414 __unmasked |= __softfp_fedisableexcept(__mask); 415 416 return (__unmasked); 417 } 418 419 int 420 (fegetexcept)(void) 421 { 422 int __unmasked; 423 424 __unmasked = 0; 425 if (_libc_arm_fpu_present) 426 __unmasked = __vfp_fegetexcept(); 427 __unmasked |= __softfp_fegetexcept(); 428 429 return (__unmasked); 430 } 431 432 #endif 433