diff options
author | Calin Juravle <calin@google.com> | 2014-02-25 14:49:41 +0000 |
---|---|---|
committer | Calin Juravle <calin@google.com> | 2014-02-26 12:30:44 +0000 |
commit | 2d367905a2e1b950f79b408141eea07c222b590b (patch) | |
tree | 8f5d47b3513c213114549acaef2d8f3e6adecd09 /libm/mips/fenv.c | |
parent | a92b57c7f8230661d911f2fd6dd67a81e9a90cef (diff) | |
download | android_bionic-2d367905a2e1b950f79b408141eea07c222b590b.tar.gz android_bionic-2d367905a2e1b950f79b408141eea07c222b590b.tar.bz2 android_bionic-2d367905a2e1b950f79b408141eea07c222b590b.zip |
Moved to a more openbsd-like fenv.h
Factored out common declarations to include/fenv.h and pushed
the implementation to .c files.
Bug: 11050744
Change-Id: I446b13cc4bc599d328343a8d392b07de280f6304
Diffstat (limited to 'libm/mips/fenv.c')
-rw-r--r-- | libm/mips/fenv.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/libm/mips/fenv.c b/libm/mips/fenv.c index b5f52dad7..893bc3009 100644 --- a/libm/mips/fenv.c +++ b/libm/mips/fenv.c @@ -33,3 +33,118 @@ * this as a default environment. */ const fenv_t __fe_dfl_env = 0; + +int fegetenv(fenv_t* __envp) { + fenv_t _fcsr = 0; +#ifdef __mips_hard_float + __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr)); +#endif + *__envp = _fcsr; + return 0; +} + +int fesetenv(const fenv_t* __envp) { + fenv_t _fcsr = *__envp; +#ifdef __mips_hard_float + __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr)); +#endif + return 0; +} + +int feclearexcept(int __excepts) { + fexcept_t __fcsr; + fegetenv(&__fcsr); + __excepts &= FE_ALL_EXCEPT; + __fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT)); + fesetenv(&__fcsr); + return 0; +} + +int fegetexceptflag(fexcept_t* __flagp, int __excepts) { + fexcept_t __fcsr; + fegetenv(&__fcsr); + *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT; + return 0; +} + +int fesetexceptflag(const fexcept_t* __flagp, int __excepts) { + fexcept_t __fcsr; + fegetenv(&__fcsr); + /* Ensure that flags are all legal */ + __excepts &= FE_ALL_EXCEPT; + __fcsr &= ~__excepts; + __fcsr |= *__flagp & __excepts; + fesetenv(&__fcsr); + return 0; +} + +int feraiseexcept(int __excepts) { + fexcept_t __fcsr; + fegetenv(&__fcsr); + /* Ensure that flags are all legal */ + __excepts &= FE_ALL_EXCEPT; + /* Cause bit needs to be set as well for generating the exception*/ + __fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT); + fesetenv(&__fcsr); + return 0; +} + +int fetestexcept(int __excepts) { + fexcept_t __FCSR; + fegetenv(&__FCSR); + return (__FCSR & __excepts & FE_ALL_EXCEPT); +} + +int fegetround(void) { + fenv_t _fcsr; + fegetenv(&_fcsr); + return (_fcsr & _FCSR_RMASK); +} + +int fesetround(int __round) { + fenv_t _fcsr; + fegetenv(&_fcsr); + _fcsr &= ~_FCSR_RMASK; + _fcsr |= (__round & _FCSR_RMASK ) ; + fesetenv(&_fcsr); + return 0; +} + +int feholdexcept(fenv_t* __envp) { + fenv_t __env; + fegetenv(&__env); + *__envp = __env; + __env &= ~(FE_ALL_EXCEPT | _FCSR_ENABLE_MASK); + fesetenv(&__env); + return 0; +} + +int feupdateenv(const fenv_t* __envp) { + fexcept_t __fcsr; + fegetenv(&__fcsr); + fesetenv(__envp); + feraiseexcept(__fcsr & FE_ALL_EXCEPT); + return 0; +} + +int feenableexcept(int __mask) { + fenv_t __old_fcsr, __new_fcsr; + fegetenv(&__old_fcsr); + __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT; + fesetenv(&__new_fcsr); + return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT); +} + +int fedisableexcept(int __mask) { + fenv_t __old_fcsr, __new_fcsr; + fegetenv(&__old_fcsr); + __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT); + fesetenv(&__new_fcsr); + return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT); +} + +int fegetexcept(void) { + fenv_t __fcsr; + fegetenv(&__fcsr); + return ((__fcsr & _FCSR_ENABLE_MASK) >> _ENABLE_SHIFT); +} |