diff options
Diffstat (limited to 'sysdeps/arm')
-rw-r--r-- | sysdeps/arm/fesetenv.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/sysdeps/arm/fesetenv.c b/sysdeps/arm/fesetenv.c index b2ed1d3911..ac47ae2d49 100644 --- a/sysdeps/arm/fesetenv.c +++ b/sysdeps/arm/fesetenv.c @@ -17,14 +17,13 @@ <http://www.gnu.org/licenses/>. */ #include <fenv.h> -#include <fpu_control.h> #include <arm-features.h> int fesetenv (const fenv_t *envp) { - fpu_control_t fpscr; + fpu_control_t fpscr, new_fpscr, updated_fpscr; /* Fail if a VFP unit isn't present. */ if (!ARM_HAVE_VFP) @@ -32,25 +31,31 @@ fesetenv (const fenv_t *envp) _FPU_GETCW (fpscr); - /* Preserve the reserved FPSCR flags. */ - fpscr &= _FPU_RESERVED; + if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV)) + { + /* The new FPSCR is valid, so don't merge the reserved flags. */ + new_fpscr = envp->__cw; - if (envp == FE_DFL_ENV) - fpscr |= _FPU_DEFAULT; - else if (envp == FE_NOMASK_ENV) - fpscr |= _FPU_IEEE; - else - fpscr |= envp->__cw & ~_FPU_RESERVED; + /* Write new FPSCR if different (ignoring NZCV flags). */ + if (((fpscr ^ new_fpscr) & ~_FPU_MASK_NZCV) != 0) + _FPU_SETCW (new_fpscr); - _FPU_SETCW (fpscr); + return 0; + } - if (envp == FE_NOMASK_ENV) + /* Preserve the reserved FPSCR flags. */ + new_fpscr = fpscr & _FPU_RESERVED; + new_fpscr |= (envp == FE_DFL_ENV) ? _FPU_DEFAULT : _FPU_IEEE; + + if (((new_fpscr ^ fpscr) & ~_FPU_MASK_NZCV) != 0) { + _FPU_SETCW (new_fpscr); + /* Not all VFP architectures support trapping exceptions, so test whether the relevant bits were set and fail if not. */ - _FPU_GETCW (fpscr); - if ((fpscr & _FPU_IEEE) != _FPU_IEEE) - return 1; + _FPU_GETCW (updated_fpscr); + + return new_fpscr & ~updated_fpscr; } return 0; |