1 #define _GNU_SOURCE 2 #include <fenv.h> 3 #include <features.h> 4 get_fpscr_f(void)5static inline double get_fpscr_f(void) 6 { 7 double d; 8 __asm__ __volatile__("mffs %0" : "=d"(d)); 9 return d; 10 } 11 get_fpscr(void)12static inline long get_fpscr(void) 13 { 14 return (union {double f; long i;}) {get_fpscr_f()}.i; 15 } 16 set_fpscr_f(double fpscr)17static inline void set_fpscr_f(double fpscr) 18 { 19 __asm__ __volatile__("mtfsf 255, %0" : : "d"(fpscr)); 20 } 21 set_fpscr(long fpscr)22static void set_fpscr(long fpscr) 23 { 24 set_fpscr_f((union {long i; double f;}) {fpscr}.f); 25 } 26 feclearexcept(int mask)27int feclearexcept(int mask) 28 { 29 mask &= FE_ALL_EXCEPT; 30 if (mask & FE_INVALID) mask |= FE_ALL_INVALID; 31 set_fpscr(get_fpscr() & ~mask); 32 return 0; 33 } 34 feraiseexcept(int mask)35int feraiseexcept(int mask) 36 { 37 mask &= FE_ALL_EXCEPT; 38 if (mask & FE_INVALID) mask |= FE_INVALID_SOFTWARE; 39 set_fpscr(get_fpscr() | mask); 40 return 0; 41 } 42 fetestexcept(int mask)43int fetestexcept(int mask) 44 { 45 return get_fpscr() & mask & FE_ALL_EXCEPT; 46 } 47 fegetround(void)48int fegetround(void) 49 { 50 return get_fpscr() & 3; 51 } 52 __fesetround(int r)53hidden int __fesetround(int r) 54 { 55 set_fpscr(get_fpscr() & ~3L | r); 56 return 0; 57 } 58 fegetenv(fenv_t * envp)59int fegetenv(fenv_t *envp) 60 { 61 *envp = get_fpscr_f(); 62 return 0; 63 } 64 fesetenv(const fenv_t * envp)65int fesetenv(const fenv_t *envp) 66 { 67 set_fpscr_f(envp != FE_DFL_ENV ? *envp : 0); 68 return 0; 69 } 70