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