--- sysdeps/arm/fesetenv.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/sysdeps/arm/fesetenv.c b/sysdeps/arm/fesetenv.c index 62031d5..66b248a 100644 --- a/sysdeps/arm/fesetenv.c +++ b/sysdeps/arm/fesetenv.c @@ -17,14 +17,13 @@ . */ #include -#include #include 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; -- 1.7.9.5