diff options
Diffstat (limited to 'sysdeps/i386/fpu/fesetenv.c')
-rw-r--r-- | sysdeps/i386/fpu/fesetenv.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/sysdeps/i386/fpu/fesetenv.c b/sysdeps/i386/fpu/fesetenv.c index 910aa0991c..f3b9cefee5 100644 --- a/sysdeps/i386/fpu/fesetenv.c +++ b/sysdeps/i386/fpu/fesetenv.c @@ -18,12 +18,18 @@ <http://www.gnu.org/licenses/>. */ #include <fenv.h> +#include <fpu_control.h> #include <assert.h> #include <unistd.h> #include <ldsodefs.h> #include <dl-procinfo.h> +/* All exceptions, including the x86-specific "denormal operand" + exception. */ +#define FE_ALL_EXCEPT_X86 (FE_ALL_EXCEPT | __FE_DENORM) + + int __fesetenv (const fenv_t *envp) { @@ -40,22 +46,30 @@ __fesetenv (const fenv_t *envp) if (envp == FE_DFL_ENV) { - temp.__control_word |= FE_ALL_EXCEPT; + temp.__control_word |= FE_ALL_EXCEPT_X86; temp.__control_word &= ~FE_TOWARDZERO; - temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__control_word |= _FPU_EXTENDED; + temp.__status_word &= ~FE_ALL_EXCEPT_X86; } else if (envp == FE_NOMASK_ENV) { temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); - temp.__status_word &= ~FE_ALL_EXCEPT; + /* Keep the "denormal operand" exception masked. */ + temp.__control_word |= __FE_DENORM; + temp.__control_word |= _FPU_EXTENDED; + temp.__status_word &= ~FE_ALL_EXCEPT_X86; } else { - temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__control_word &= ~(FE_ALL_EXCEPT_X86 + | FE_TOWARDZERO + | _FPU_EXTENDED); temp.__control_word |= (envp->__control_word - & (FE_ALL_EXCEPT | FE_TOWARDZERO)); - temp.__status_word &= ~FE_ALL_EXCEPT; - temp.__status_word |= envp->__status_word & FE_ALL_EXCEPT; + & (FE_ALL_EXCEPT_X86 + | FE_TOWARDZERO + | _FPU_EXTENDED)); + temp.__status_word &= ~FE_ALL_EXCEPT_X86; + temp.__status_word |= envp->__status_word & FE_ALL_EXCEPT_X86; } temp.__eip = 0; temp.__cs_selector = 0; @@ -73,22 +87,28 @@ __fesetenv (const fenv_t *envp) if (envp == FE_DFL_ENV) { /* Clear SSE exceptions. */ - mxcsr &= ~FE_ALL_EXCEPT; + mxcsr &= ~FE_ALL_EXCEPT_X86; /* Set mask for SSE MXCSR. */ - mxcsr |= (FE_ALL_EXCEPT << 7); + mxcsr |= (FE_ALL_EXCEPT_X86 << 7); /* Set rounding to FE_TONEAREST. */ mxcsr &= ~0x6000; mxcsr |= (FE_TONEAREST << 3); + /* Clear the FZ and DAZ bits. */ + mxcsr &= ~0x8040; } else if (envp == FE_NOMASK_ENV) { /* Clear SSE exceptions. */ - mxcsr &= ~FE_ALL_EXCEPT; + mxcsr &= ~FE_ALL_EXCEPT_X86; /* Do not mask exceptions. */ mxcsr &= ~(FE_ALL_EXCEPT << 7); + /* Keep the "denormal operand" exception masked. */ + mxcsr |= (__FE_DENORM << 7); /* Set rounding to FE_TONEAREST. */ mxcsr &= ~0x6000; mxcsr |= (FE_TONEAREST << 3); + /* Clear the FZ and DAZ bits. */ + mxcsr &= ~0x8040; } else mxcsr = envp->__eip; |