From e4363cfb5760d88a9f353c69383b15d5c2705070 Mon Sep 17 00:00:00 2001 From: Carlos O'Donell Date: Wed, 11 Mar 2015 02:42:27 -0400 Subject: hppa: Fix feupdateenv and fesetexceptflag (Bug 18111). The function feupdateenv has been fixed to correctly handle FE_DFL_ENV and FE_NOMASK_ENV. The fesetexceptflag function has been fixed to correctly handle setting the new flags instead of just OR-ing the existing flags. This fixes the test-fenv-return and test-fenvinline failures on hppa. --- sysdeps/hppa/fpu/feupdateenv.c | 19 ++++++++++++++++--- sysdeps/hppa/fpu/fpu_control.h | 7 ++++++- sysdeps/hppa/fpu/fsetexcptflg.c | 18 ++++++++++++------ 3 files changed, 34 insertions(+), 10 deletions(-) (limited to 'sysdeps/hppa') diff --git a/sysdeps/hppa/fpu/feupdateenv.c b/sysdeps/hppa/fpu/feupdateenv.c index 931f7e6..345559e 100644 --- a/sysdeps/hppa/fpu/feupdateenv.c +++ b/sysdeps/hppa/fpu/feupdateenv.c @@ -29,9 +29,22 @@ __feupdateenv (const fenv_t *envp) __asm__ ("fstd %%fr0,0(%1) \n\t" "fldd 0(%1),%%fr0 \n\t" : "=m" (s.l) : "r" (&s.l)); - memcpy(&temp, envp, sizeof(fenv_t)); - /* Currently raised exceptions not cleared */ - temp.__status_word |= s.sw[0] & (FE_ALL_EXCEPT << 27); + + /* Given environment with exception flags not cleared. */ + if ((envp != FE_DFL_ENV) && (envp != FE_NOMASK_ENV)) + { + memcpy(&temp, envp, sizeof(fenv_t)); + temp.__status_word |= s.sw[0] & (FE_ALL_EXCEPT << 27); + } + + /* Default environment with exception flags not cleared. */ + if (envp == FE_DFL_ENV) + temp.__status_word = s.sw[0] & (FE_ALL_EXCEPT << 27); + + /* All traps enabled and current exception flags not cleared. */ + if (envp == FE_NOMASK_ENV) + temp.__status_word = (s.sw[0] & (FE_ALL_EXCEPT << 27)) | FE_ALL_EXCEPT; + /* Install new environment. */ __fesetenv (&temp); /* Success. */ diff --git a/sysdeps/hppa/fpu/fpu_control.h b/sysdeps/hppa/fpu/fpu_control.h index ba9692f..2087928 100644 --- a/sysdeps/hppa/fpu/fpu_control.h +++ b/sysdeps/hppa/fpu/fpu_control.h @@ -19,7 +19,7 @@ #ifndef _FPU_CONTROL_H #define _FPU_CONTROL_H -/* Masking of interrupts */ +/* Masking of interrupts. */ #define _FPU_MASK_PM 0x00000001 /* Inexact (I) */ #define _FPU_MASK_UM 0x00000002 /* Underflow (U) */ #define _FPU_MASK_OM 0x00000004 /* Overflow (O) */ @@ -30,6 +30,8 @@ #define _FPU_HPPA_MASK_RM 0x00000600 /* Rounding mode mask */ /* Masking of interrupt enable bits. */ #define _FPU_HPPA_MASK_INT 0x0000001f /* Interrupt mask */ +/* Shift by 27 to install flag bits. */ +#define _FPU_HPPA_SHIFT_FLAGS 27 /* There are no reserved bits in the PA fpsr (though some are undefined). */ #define _FPU_RESERVED 0x00000000 @@ -55,6 +57,9 @@ typedef unsigned int fpu_control_t; #define _FPU_SETCW(cw) \ ({ \ union { __extension__ unsigned long long __fpreg; unsigned int __halfreg[2]; } __fullfp; \ + /* Get the current status word and set the control word. */ \ + __asm__ ("fstd %%fr0,0(%1)\n\t" \ + : "=m" (__fullfp.__fpreg) : "r" (&__fullfp.__fpreg) : "%r0"); \ __fullfp.__halfreg[0] = cw; \ __asm__ ("fldd 0(%1),%%fr0\n\t" \ : : "m" (__fullfp.__fpreg), "r" (&__fullfp.__fpreg) : "%r0" ); \ diff --git a/sysdeps/hppa/fpu/fsetexcptflg.c b/sysdeps/hppa/fpu/fsetexcptflg.c index 2c34a1e..c31de8b 100644 --- a/sysdeps/hppa/fpu/fsetexcptflg.c +++ b/sysdeps/hppa/fpu/fsetexcptflg.c @@ -18,19 +18,25 @@ . */ #include -#include +#include int fesetexceptflag (const fexcept_t *flagp, int excepts) { - union { unsigned long long l; unsigned int sw[2]; } s; + fpu_control_t fpsr; + fpu_control_t fpsr_new; /* Get the current status word. */ - __asm__ ("fstd %%fr0,0(%1)" : "=m" (s.l) : "r" (&s.l) : "%r0"); - /* Install new raised trap bits */ - s.sw[0] |= (*flagp & excepts & FE_ALL_EXCEPT) << 27; + _FPU_GETCW (fpsr); + excepts &= FE_ALL_EXCEPT; + + /* Install new raised flags. */ + fpsr_new = fpsr & ~(excepts << _FPU_HPPA_SHIFT_FLAGS); + fpsr_new |= (*flagp & excepts) << _FPU_HPPA_SHIFT_FLAGS; + /* Store the new status word. */ - __asm__ ("fldd 0(%0),%%fr0" : : "r" (&s.l), "m" (s.l) : "%r0"); + if (fpsr != fpsr_new) + _FPU_SETCW (fpsr_new); /* Success. */ return 0; -- cgit v1.1