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.
This commit is contained in:
Carlos O'Donell 2015-03-11 02:42:27 -04:00
parent fae1aa8d22
commit e4363cfb57
5 changed files with 44 additions and 11 deletions

View File

@ -1,3 +1,12 @@
2015-03-11 Carlos O'Donell <carlos@redhat.com>
[BZ #18111]
* sysdeps/hppa/fpu/fpu_control.h (_FPU_HPPA_SHIFT_FLAGS): Define.
(_FPU_SETCW): Initialize cw from fpsr before storing.
* sysdeps/hppa/fpu/fsetexcptflg.c: Include fpu_control.h
(fesetexceptflag): Rewrite using fpu_control.h.
* sysdeps/hppa/fpu/feupdateenv.c: Handle FE_DFL_ENV, and FE_NOMASK_ENV.
2015-03-11 John David Anglin <danglin@gcc.gnu.org>
[BZ #18110]

2
NEWS
View File

@ -14,7 +14,7 @@ Version 2.22
17792, 17836, 17912, 17916, 17932, 17944, 17949, 17964, 17965, 17967,
17969, 17978, 17987, 17991, 17996, 17998, 17999, 18019, 18020, 18029,
18030, 18032, 18036, 18038, 18039, 18042, 18043, 18046, 18047, 18104,
18110.
18110, 18111.
* Character encoding and ctype tables were updated to Unicode 7.0.0, using
new generator scripts contributed by Pravin Satpute and Mike FABIAN (Red

View File

@ -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. */

View File

@ -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" ); \

View File

@ -18,19 +18,25 @@
<http://www.gnu.org/licenses/>. */
#include <fenv.h>
#include <math.h>
#include <fpu_control.h>
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;