aboutsummaryrefslogtreecommitdiffstats
path: root/libm/mips/fenv.c
diff options
context:
space:
mode:
authorCalin Juravle <calin@google.com>2014-02-25 14:49:41 +0000
committerCalin Juravle <calin@google.com>2014-02-26 12:30:44 +0000
commit2d367905a2e1b950f79b408141eea07c222b590b (patch)
tree8f5d47b3513c213114549acaef2d8f3e6adecd09 /libm/mips/fenv.c
parenta92b57c7f8230661d911f2fd6dd67a81e9a90cef (diff)
downloadandroid_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.c115
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);
+}