arm64: simplify the fenv implementation a bit.
The macOS man page was helpful in advancing my understanding of
feupdateenv() in particular.
Test: treehugger
Change-Id: I511e8b31ac16f3fdf08b42eee5a2e6558ec3b70b
diff --git a/libm/arm64/fenv.c b/libm/arm64/fenv.c
index a99288b..369140b 100644
--- a/libm/arm64/fenv.c
+++ b/libm/arm64/fenv.c
@@ -59,7 +59,6 @@
int fesetenv(const fenv_t* envp) {
fpu_control_t fpcr;
-
__get_fpcr(fpcr);
if (envp->__control != fpcr) {
__set_fpcr(envp->__control);
@@ -70,27 +69,22 @@
int feclearexcept(int excepts) {
fpu_status_t fpsr;
-
- excepts &= FE_ALL_EXCEPT;
__get_fpsr(fpsr);
- fpsr &= ~excepts;
+ fpsr &= ~(excepts & FE_ALL_EXCEPT);
__set_fpsr(fpsr);
return 0;
}
int fegetexceptflag(fexcept_t* flagp, int excepts) {
fpu_status_t fpsr;
-
- excepts &= FE_ALL_EXCEPT;
__get_fpsr(fpsr);
- *flagp = fpsr & excepts;
+ *flagp = fpsr & (excepts & FE_ALL_EXCEPT);
return 0;
}
int fesetexceptflag(const fexcept_t* flagp, int excepts) {
- fpu_status_t fpsr;
-
excepts &= FE_ALL_EXCEPT;
+ fpu_status_t fpsr;
__get_fpsr(fpsr);
fpsr &= ~excepts;
fpsr |= *flagp & excepts;
@@ -100,32 +94,27 @@
int feraiseexcept(int excepts) {
fexcept_t ex = excepts;
-
fesetexceptflag(&ex, excepts);
return 0;
}
int fetestexcept(int excepts) {
fpu_status_t fpsr;
-
- excepts &= FE_ALL_EXCEPT;
__get_fpsr(fpsr);
- return (fpsr & excepts);
+ return (fpsr & (excepts & FE_ALL_EXCEPT));
}
int fegetround(void) {
fpu_control_t fpcr;
-
__get_fpcr(fpcr);
return ((fpcr >> FPCR_RMODE_SHIFT) & FE_TOWARDZERO);
}
int fesetround(int round) {
- fpu_control_t fpcr, new_fpcr;
-
- round &= FE_TOWARDZERO;
+ if (round < FE_TONEAREST || round > FE_UPWARD) return -1;
+ fpu_control_t fpcr;
__get_fpcr(fpcr);
- new_fpcr = fpcr & ~(FE_TOWARDZERO << FPCR_RMODE_SHIFT);
+ fpu_control_t new_fpcr = fpcr & ~(FE_TOWARDZERO << FPCR_RMODE_SHIFT);
new_fpcr |= (round << FPCR_RMODE_SHIFT);
if (new_fpcr != fpcr) {
__set_fpcr(new_fpcr);
@@ -134,33 +123,15 @@
}
int feholdexcept(fenv_t* envp) {
- fpu_status_t fpsr;
- __get_fpsr(fpsr);
- fpu_control_t fpcr;
- __get_fpcr(fpcr);
- fenv_t env = { .__status = fpsr, .__control = fpcr };
- *envp = env;
-
- // Clear all exceptions.
- fpsr &= ~FE_ALL_EXCEPT;
- __set_fpsr(fpsr);
+ fegetenv(envp);
+ feclearexcept(FE_ALL_EXCEPT);
return 0;
}
int feupdateenv(const fenv_t* envp) {
- fpu_status_t fpsr;
- fpu_control_t fpcr;
-
- // Set FPU Control register.
- __get_fpcr(fpcr);
- if (envp->__control != fpcr) {
- __set_fpcr(envp->__control);
- }
-
- // Set FPU Status register to status | currently raised exceptions.
- __get_fpsr(fpsr);
- fpsr = envp->__status | (fpsr & FE_ALL_EXCEPT);
- __set_fpsr(fpsr);
+ int excepts = fetestexcept(FE_ALL_EXCEPT);
+ fesetenv(envp);
+ feraiseexcept(excepts);
return 0;
}