this repo has no description
at fixPythonPipStalling 311 lines 11 kB view raw
1/* 2 * fenv.c 3 * cLibm 4 * 5 * Created by Ian Ollmann on 7/15/07. 6 * Copyright 2007 Apple Inc. All rights reserved. 7 * 8 * A partial implementation for Intel is provided here for testing purposes. 9 * You'll need to provide a full implementation for your platform of choice. 10 * 11 */ 12 13#if defined(ARMLIBM_FENV_SUPPORT) 14 15#include "fenv.h" 16#include <stdint.h> 17#include "required_arithmetic.h" 18 19#define FE_ALL_RND ( FE_TONEAREST | FE_TOWARDZERO | FE_UPWARD | FE_DOWNWARD ) 20 21#if defined( __GNUC__ ) 22 #define ALWAYS_INLINE __attribute__ ((__always_inline__)) 23#else 24 #define ALWAYS_INLINE 25#endif 26 27#ifndef __arm__ 28 #error This file is for use on ARM + VFP and later 29#endif 30 31 32#define GET_FPSCR() ({ uint32_t _fpscr; __asm__ __volatile__( "fmrx %0, fpscr" : "=r" (_fpscr) ); /* return */ _fpscr; }) 33#define SET_FPSCR(_fpscr) __asm__ __volatile__( "fmxr fpscr, %0" : : "r" (_fpscr) ) 34 35 36const fenv_t _FE_DFL_ENV = {{{ 0, 0, 0, 0 }}}; 37// Worker functions for making sure that much of the work is done in a uniform way 38 39// For each bit set in excepts, change the floating point state to match the correspinding bit in *flagp 40static inline int _fesetexceptflag_private(const fexcept_t *flagp, int excepts ) ALWAYS_INLINE; 41static inline int _fesetexceptflag_private(const fexcept_t *flagp, int excepts ) 42{ 43 uint32_t fpscr = GET_FPSCR(); 44 45 excepts &= FE_ALL_EXCEPT | 0x8000; 46 47 fpscr &= ~excepts; 48 fpscr |= *flagp & excepts; 49 50 SET_FPSCR( fpscr ); 51 52 return 0; 53} 54 55// For each bit set in excepts, copy the corresponding bit from the floating point state into *flagp 56// All other bits shall be set to zero 57static inline int _fegetexceptflag_private(fexcept_t *flagp, int excepts); 58static inline int _fegetexceptflag_private(fexcept_t *flagp, int excepts) 59{ 60 uint32_t fpscr = GET_FPSCR(); 61 62 *flagp = fpscr & excepts; 63 64 return 0; 65} 66 67 68 69/******************************************************************************* 70* The function "feclearexcept" clears the supported floating point * 71* exceptions represented by its argument. * 72*******************************************************************************/ 73 74int feclearexcept(int excepts) 75{ 76 fexcept_t zero = 0; 77 return _fesetexceptflag_private( &zero, excepts ); 78} 79 80 81 82/******************************************************************************* 83* The function "feraiseexcept" raises the supported floating-point * 84* exceptions represented by its argument. The order in which these * 85* floating-point exceptions are raised is unspecified. * 86*******************************************************************************/ 87 88int feraiseexcept(int excepts) 89{ 90 int inexact_set = 0; 91 92 if( excepts & FE_OVERFLOW ) 93 { 94 required_add_float( 0x1.0p127f, 0x1.0p127f ); 95 inexact_set = 1; 96 } 97 if( excepts & FE_UNDERFLOW ) 98 { 99 required_multiply_float( 0x1.0p-126f, 0x1.0p-126f ); 100 inexact_set = 1; 101 } 102 if( excepts & FE_INVALID ) 103 required_add_float( __builtin_inff(), -__builtin_inff() ); 104 if( excepts & FE_DIVBYZERO ) 105 required_divide_float( 1.0f, 0.0f ); 106 if( 0 != (excepts & FE_INEXACT) && 0 == inexact_set ) 107 required_add_float( 0x1.0p127f, 1.0f ); 108 109 return 0; 110} 111 112 113 114 115 116 117/******************************************************************************* 118* The function "fetestexcept" determines which of the specified subset of * 119* the floating-point exception flags are currently set. The excepts * 120* argument specifies the floating-point status flags to be queried. This * 121* function returns the value of the bitwise OR of the floating-point * 122* exception macros corresponding to the currently set floating-point * 123* exceptions included in excepts. * 124* * 125*******************************************************************************/ 126 127int fetestexcept(int excepts ) 128{ 129 fexcept_t t = 0; 130 131 _fegetexceptflag_private( &t, excepts); 132 133 return t; 134} 135 136 137/******************************************************************************* 138* The following functions provide control of rounding direction modes. * 139*******************************************************************************/ 140 141/******************************************************************************* 142* The function "fegetround" returns the value of the rounding direction * 143* macro which represents the current rounding direction, or a negative * 144* if there is no such rounding direction macro or the current rounding * 145* direction is not determinable. * 146*******************************************************************************/ 147 148int fegetround(void) 149{ 150 int32_t fpscr = GET_FPSCR(); 151 152 return fpscr & FE_ALL_RND; 153} 154 155 156/******************************************************************************* 157* The function "fesetround" establishes the rounding direction represented * 158* by its argument "round". If the argument is not equal to the value of a * 159* rounding direction macro, the rounding direction is not changed. It * 160* returns zero if and only if the argument is equal to a rounding * 161* direction macro. * 162*******************************************************************************/ 163 164int fesetround(int round ) 165{ 166 if( (round & FE_ALL_RND) != round ) 167 return round; 168 169 int32_t fpscr = GET_FPSCR(); 170 171 fpscr &= ~FE_ALL_RND; 172 fpscr |= round & FE_ALL_RND; 173 174 SET_FPSCR( fpscr ); 175 176 return 0; 177} 178 179 180/******************************************************************************* 181* The following functions manage the floating-point environment, exception * 182* flags and dynamic modes, as one entity. * 183*******************************************************************************/ 184 185/******************************************************************************* 186* The fegetenv function stores the current floating-point enviornment in * 187* the object pointed to by envp. * 188*******************************************************************************/ 189int fegetenv(fenv_t *envp) 190{ 191 envp->__fpscr = GET_FPSCR(); 192 envp->__reserved0 = 0; 193 envp->__reserved1 = 0; 194 envp->__reserved2 = 0; 195 196 return 0; 197} 198 199/******************************************************************************* 200* The feholdexcept function saves the current floating-point environment in * 201* the object pointed to by envp, clears the floating-point status flags, * 202* and then installs a non-stop (continue on floating-point exceptions) * 203* mode, if available, for all floating-point exceptions. The feholdexcept * 204* function returns zero if and only if non-stop floating-point exceptions * 205* handling was successfully installed. * 206*******************************************************************************/ 207int feholdexcept(fenv_t *envp) 208{ 209 uint32_t fpscr = GET_FPSCR(); 210 211 envp->__fpscr = fpscr; 212 envp->__reserved0 = 0; 213 envp->__reserved1 = 0; 214 envp->__reserved2 = 0; 215 216 fpscr &= ~( FE_ALL_EXCEPT | (FE_ALL_EXCEPT << 8) ); 217 218 SET_FPSCR( fpscr ); 219 220 return 0; 221} 222 223 224/******************************************************************************* 225* The fesetnv function establishes the floating-point environment * 226* represented by the object pointed to by envp. The argument envp shall * 227* point to an object set by a call to fegetenv or feholdexcept, or equal to * 228* a floating-point environment macro -- we define only *FE_DFL_ENV and * 229* FE_DISABLE_SSE_DENORMS_ENV -- to be C99 standard compliant and portable * 230* to other architectures. Note that fesetnv merely installs the state of * 231* the floating-point status flags represented through its argument, and * 232* does not raise these floating-point exceptions. * 233* * 234*******************************************************************************/ 235int fesetenv(const fenv_t *envp) 236{ 237 SET_FPSCR( envp->__fpscr ); 238 239 return 0; 240} 241 242 243 244/******************************************************************************* 245* The feupdateenv function saves the currently raised floating-point * 246* exceptions in its automatic storage, installs the floating-point * 247* environment represented by the object pointed to by envp, and then raises * 248* the saved floating-point exceptions. The argument envp shall point to an * 249* object set by a call to feholdexcept or fegetenv or equal a * 250* floating-point environment macro. * 251* * 252*******************************************************************************/ 253int feupdateenv(const fenv_t *envp) 254{ 255 uint32_t oldenv = GET_FPSCR(); 256 257 SET_FPSCR( envp->__fpscr ); 258 259 int inexact_set = 0; 260 261 if( oldenv & FE_OVERFLOW ) 262 { 263 required_add_float( 0x1.0p127f, 0x1.0p127f ); 264 inexact_set = 1; 265 } 266 if( oldenv & FE_UNDERFLOW ) 267 { 268 required_multiply_float( 0x1.0p-126f, 0x1.0p-126f ); 269 inexact_set = 1; 270 } 271 if( oldenv & FE_INVALID ) 272 required_add_float( __builtin_inff(), -__builtin_inff() ); 273 if( oldenv & FE_DIVBYZERO ) 274 required_divide_float( 1.0f, 0.0f ); 275 if( 0 != (oldenv & FE_INEXACT) && 0 == inexact_set ) 276 required_add_float( 0x1.0p127f, 1.0f ); 277 278 return 0; 279} 280 281 282/******************************************************************************* 283* The function "fegetexceptflag" stores a implementation-defined * 284* representation of the states of the floating-point status flags indicated * 285* by its integer argument excepts in the object pointed to by the argument, * 286* flagp. * 287*******************************************************************************/ 288 289int fegetexceptflag(fexcept_t *flagp, int excepts) 290{ 291 return _fegetexceptflag_private( flagp, excepts ); 292} 293 294/******************************************************************************* 295* The function "fesetexceptflag" sets or clears the floating point status * 296* flags indicated by the argument excepts to the states stored in the * 297* object pointed to by flagp. The value of the *flagp shall have been set * 298* by a previous call to fegetexceptflag whose second argument represented * 299* at least those floating-point exceptions represented by the argument * 300* excepts. This function does not raise floating-point exceptions; it just * 301* sets the state of the flags. * 302*******************************************************************************/ 303 304int fesetexceptflag(const fexcept_t *flagp, int excepts ) 305{ 306 return _fesetexceptflag_private( flagp, excepts ); 307} 308 309#endif 310 311