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