aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--sysdeps/powerpc/fpu/fedisblxcpt.c14
-rw-r--r--sysdeps/powerpc/fpu/feenablxcpt.c15
-rw-r--r--sysdeps/powerpc/fpu/fenv_libc.h10
-rw-r--r--sysdeps/powerpc/fpu/fesetmode.c15
5 files changed, 41 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index c2d70717ec..1609d16e00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2019-08-28 Paul A. Clarke <pc@us.ibm.com>
+ * sysdeps/powerpc/fpu/fenv_libc.h (fesetenv_mode): New.
+ (FPSCR_FPRF_MASK): New. (FPSCR_STATUS_MASK): New.
+ * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Use lighter-
+ weight access to FPSCR; remove unnecessary second FPSCR read and
+ validate.
+ * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Likewise.
+ * sysdeps/powerpc/fpu/fesetmode.c (fesetmode): Use lighter-weight
+ access to FPSCR; Use macros in fenv_libc.h in favor of local.
+
+2019-08-28 Paul A. Clarke <pc@us.ibm.com>
+
* sysdeps/powerpc/fpu/fenv_libc.h: Define FPSCR bitmasks.
(fenv_reg_to_exceptions): Replace bitwise operations with mask-shift.
(fenv_exceptions_to_reg): New.
diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c
index 5cc87992f0..a2b7addf20 100644
--- a/sysdeps/powerpc/fpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/fpu/fedisblxcpt.c
@@ -26,23 +26,25 @@ fedisableexcept (int excepts)
int result, new;
/* Get current exception mask to return. */
- fe.fenv = curr.fenv = fegetenv_register ();
+ fe.fenv = curr.fenv = fegetenv_status ();
result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
+ new = fenv_exceptions_to_reg (excepts);
+
+ if (fenv_reg_to_exceptions (new) != excepts)
+ return -1;
+
/* Sets the new exception mask. */
- fe.l &= ~ fenv_exceptions_to_reg (excepts);
+ fe.l &= ~new;
if (fe.l != curr.l)
- fesetenv_register (fe.fenv);
+ fesetenv_mode (fe.fenv);
- new = __fegetexcept ();
if (new == 0 && result != 0)
(void)__fe_mask_env ();
- if ((new & excepts) != 0)
- result = -1;
return result;
}
diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c
index 3b64398ff1..c06a7fdb72 100644
--- a/sysdeps/powerpc/fpu/feenablxcpt.c
+++ b/sysdeps/powerpc/fpu/feenablxcpt.c
@@ -26,24 +26,25 @@ feenableexcept (int excepts)
int result, new;
/* Get current exception mask to return. */
- fe.fenv = curr.fenv = fegetenv_register ();
+ fe.fenv = curr.fenv = fegetenv_status ();
result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
+ new = fenv_exceptions_to_reg (excepts);
+
+ if (fenv_reg_to_exceptions (new) != excepts)
+ return -1;
+
/* Sets the new exception mask. */
- fe.l |= fenv_exceptions_to_reg (excepts);
+ fe.l |= new;
if (fe.l != curr.l)
- fesetenv_register (fe.fenv);
+ fesetenv_mode (fe.fenv);
- new = __fegetexcept ();
if (new != 0 && result == 0)
(void) __fe_nomask_env_priv ();
- if ((new & excepts) != excepts)
- result = -1;
-
return result;
}
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index 9956136a13..4144d413a2 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -70,6 +70,11 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden;
__builtin_mtfsf (0xff, d); \
} while(0)
+/* Set the last 2 nibbles of the FPSCR, which contain the
+ exception enables and the rounding mode.
+ 'fegetenv_status' retrieves these bits by reading the FPSCR. */
+#define fesetenv_mode(env) __builtin_mtfsf (0b00000011, (env));
+
/* This very handy macro:
- Sets the rounding mode to 'round to nearest';
- Sets the processor into IEEE mode; and
@@ -208,8 +213,11 @@ enum {
(FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK)
#define FPSCR_BASIC_EXCEPTIONS_MASK \
(FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK)
-
+#define FPSCR_FPRF_MASK \
+ (FPSCR_FPRF_C_MASK|FPSCR_FPRF_FL_MASK|FPSCR_FPRF_FG_MASK| \
+ FPSCR_FPRF_FE_MASK|FPSCR_FPRF_FU_MASK)
#define FPSCR_CONTROL_MASK (FPSCR_ENABLES_MASK|FPSCR_NI_MASK|FPSCR_RN_MASK)
+#define FPSCR_STATUS_MASK (FPSCR_FR_MASK|FPSCR_FI_MASK|FPSCR_FPRF_MASK)
/* The bits in the FENV(1) ABI for exceptions correspond one-to-one with bits
in the FPSCR, albeit shifted to different but corresponding locations.
diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c
index 4f4f71a3ba..e92559b6d5 100644
--- a/sysdeps/powerpc/fpu/fesetmode.c
+++ b/sysdeps/powerpc/fpu/fesetmode.c
@@ -19,11 +19,6 @@
#include <fenv_libc.h>
#include <fpu_control.h>
-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM \
- | _FPU_MASK_XM | _FPU_MASK_IM)
-
-#define FPU_STATUS 0xbffff700ULL
-
int
fesetmode (const femode_t *modep)
{
@@ -32,18 +27,18 @@ fesetmode (const femode_t *modep)
/* Logic regarding enabled exceptions as in fesetenv. */
new.fenv = *modep;
- old.fenv = fegetenv_register ();
- new.l = (new.l & ~FPU_STATUS) | (old.l & FPU_STATUS);
+ old.fenv = fegetenv_status ();
+ new.l = (new.l & ~FPSCR_STATUS_MASK) | (old.l & FPSCR_STATUS_MASK);
if (old.l == new.l)
return 0;
- if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0)
+ if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0)
(void) __fe_nomask_env_priv ();
- if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0)
+ if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0)
(void) __fe_mask_env ();
- fesetenv_register (new.fenv);
+ fesetenv_mode (new.fenv);
return 0;
}