summaryrefslogtreecommitdiffstats
path: root/libm/arm64/fenv.c
diff options
context:
space:
mode:
Diffstat (limited to 'libm/arm64/fenv.c')
-rw-r--r--libm/arm64/fenv.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/libm/arm64/fenv.c b/libm/arm64/fenv.c
index 27c405f..9db21ef 100644
--- a/libm/arm64/fenv.c
+++ b/libm/arm64/fenv.c
@@ -33,3 +33,109 @@
* this as a default environment.
*/
const fenv_t __fe_dfl_env = 0;
+
+int fegetenv(fenv_t* __envp) {
+ fenv_t _fpcr, _fpsr;
+ __asm__ __volatile__("mrs %0,fpcr" : "=r" (_fpcr));
+ __asm__ __volatile__("mrs %0,fpsr" : "=r" (_fpsr));
+ *__envp = (_fpcr | _fpsr);
+ return 0;
+}
+
+int fesetenv(const fenv_t* __envp) {
+ fenv_t _fpcr = (*__envp & FPCR_MASK);
+ fenv_t _fpsr = (*__envp & FPSR_MASK);
+ __asm__ __volatile__("msr fpcr,%0" : :"ri" (_fpcr));
+ __asm__ __volatile__("msr fpsr,%0" : :"ri" (_fpsr));
+ return 0;
+}
+
+int feclearexcept(int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ __fpscr &= ~__excepts;
+ fesetenv(&__fpscr);
+ return 0;
+}
+
+int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ *__flagp = __fpscr & __excepts;
+ return 0;
+}
+
+int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ __fpscr &= ~__excepts;
+ __fpscr |= *__flagp & __excepts;
+ fesetenv(&__fpscr);
+ return 0;
+}
+
+int feraiseexcept(int __excepts) {
+ fexcept_t __ex = __excepts;
+ fesetexceptflag(&__ex, __excepts);
+ return 0;
+}
+
+int fetestexcept(int __excepts) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ return (__fpscr & __excepts);
+}
+
+int fegetround(void) {
+ fenv_t _fpscr;
+ fegetenv(&_fpscr);
+ return ((_fpscr >> _FPSCR_RMODE_SHIFT) & 0x3);
+}
+
+int fesetround(int __round) {
+ fenv_t _fpscr;
+ fegetenv(&_fpscr);
+ _fpscr &= ~(0x3 << _FPSCR_RMODE_SHIFT);
+ _fpscr |= (__round << _FPSCR_RMODE_SHIFT);
+ fesetenv(&_fpscr);
+ return 0;
+}
+
+int feholdexcept(fenv_t* __envp) {
+ fenv_t __env;
+ fegetenv(&__env);
+ *__envp = __env;
+ __env &= ~(FE_ALL_EXCEPT | _FPSCR_ENABLE_MASK);
+ fesetenv(&__env);
+ return 0;
+}
+
+int feupdateenv(const fenv_t* __envp) {
+ fexcept_t __fpscr;
+ fegetenv(&__fpscr);
+ fesetenv(__envp);
+ feraiseexcept(__fpscr & FE_ALL_EXCEPT);
+ return 0;
+}
+
+int feenableexcept(int __mask) {
+ fenv_t __old_fpscr, __new_fpscr;
+ fegetenv(&__old_fpscr);
+ __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT;
+ fesetenv(&__new_fpscr);
+ return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+int fedisableexcept(int __mask) {
+ fenv_t __old_fpscr, __new_fpscr;
+ fegetenv(&__old_fpscr);
+ __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT);
+ fesetenv(&__new_fpscr);
+ return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+}
+
+int fegetexcept(void) {
+ fenv_t __fpscr;
+ fegetenv(&__fpscr);
+ return ((__fpscr & _FPSCR_ENABLE_MASK) >> _FPSCR_ENABLE_SHIFT);
+}