1 /* 2 * Copyright (c) 2005-2019 Rich Felker, et al. 3 * 4 * Part of MUSL, released under the MIT license. 5 */ 6 7 8 #include <fenv.h> 9 #include <features.h> 10 11 #define hidden __attribute__((__visibility__("hidden"))) 12 13 #if __HAVE_68881__ || __mcffpu__ 14 15 static unsigned getsr() 16 { 17 unsigned v; 18 __asm__ __volatile__ ("fmove.l %%fpsr,%0" : "=dm"(v)); 19 return v; 20 } 21 22 static void setsr(unsigned v) 23 { 24 __asm__ __volatile__ ("fmove.l %0,%%fpsr" : : "dm"(v)); 25 } 26 27 static unsigned getcr() 28 { 29 unsigned v; 30 __asm__ __volatile__ ("fmove.l %%fpcr,%0" : "=dm"(v)); 31 return v; 32 } 33 34 static void setcr(unsigned v) 35 { 36 __asm__ __volatile__ ("fmove.l %0,%%fpcr" : : "dm"(v)); 37 } 38 39 int feclearexcept(int mask) 40 { 41 if (mask & ~FE_ALL_EXCEPT) return -1; 42 setsr(getsr() & ~mask); 43 return 0; 44 } 45 46 int feraiseexcept(int mask) 47 { 48 if (mask & ~FE_ALL_EXCEPT) return -1; 49 setsr(getsr() | mask); 50 return 0; 51 } 52 53 int fetestexcept(int mask) 54 { 55 return getsr() & mask; 56 } 57 58 int fegetround(void) 59 { 60 return getcr() & FE_UPWARD; 61 } 62 63 hidden int __fesetround(int r) 64 { 65 setcr((getcr() & ~FE_UPWARD) | r); 66 return 0; 67 } 68 69 int fegetenv(fenv_t *envp) 70 { 71 envp->__control_register = getcr(); 72 envp->__status_register = getsr(); 73 __asm__ __volatile__ ("fmove.l %%fpiar,%0" 74 : "=dm"(envp->__instruction_address)); 75 return 0; 76 } 77 78 int fesetenv(const fenv_t *envp) 79 { 80 static const fenv_t default_env = { 0 }; 81 if (envp == FE_DFL_ENV) 82 envp = &default_env; 83 setcr(envp->__control_register); 84 setsr(envp->__status_register); 85 __asm__ __volatile__ ("fmove.l %0,%%fpiar" 86 : : "dm"(envp->__instruction_address)); 87 return 0; 88 } 89 90 #else 91 92 #include "fenv-generic.c" 93 94 #endif 95