aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--sysdeps/powerpc/fpu/fclrexcpt.c7
-rw-r--r--sysdeps/powerpc/fpu/fedisblxcpt.c14
-rw-r--r--sysdeps/powerpc/fpu/feenablxcpt.c14
-rw-r--r--sysdeps/powerpc/fpu/feholdexcpt.c3
-rw-r--r--sysdeps/powerpc/fpu/fenv_libc.h17
-rw-r--r--sysdeps/powerpc/fpu/fesetenv.c2
-rw-r--r--sysdeps/powerpc/fpu/fsetexcptflg.c7
8 files changed, 60 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 8b9cfb5..4007295 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2014-04-28 Adhemerval Zanella <azanella@linux.vnet.ibm.com>
+
+ * sysdeps/powerpc/fpu/fclrexcpt.c (__feclearexcept): Do not update
+ FPSCR if value do not change.
+ * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Likewise.
+ * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Likewise.
+ * sysdeps/powerpc/fpu/feholdexcpt.c (feholdexcept): Likewise.
+ * sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Likewise.
+ * sysdeps/powerpc/fpu/fsetexcptflg.c (__fesetexceptflag): Likewise.
+ * sysdeps/powerpc/fpu/fenv_libc.h (fenv_reg_to_exceptions): New helper
+ function.
+
2014-05-29 Carlos O'Donell <carlos@systemhalted.org>
* sysdeps/hppa: Move directory from ports/sysdeps/hppa.
diff --git a/sysdeps/powerpc/fpu/fclrexcpt.c b/sysdeps/powerpc/fpu/fclrexcpt.c
index cda2810..4607f62 100644
--- a/sysdeps/powerpc/fpu/fclrexcpt.c
+++ b/sysdeps/powerpc/fpu/fclrexcpt.c
@@ -22,17 +22,18 @@
int
__feclearexcept (int excepts)
{
- fenv_union_t u;
+ fenv_union_t u, n;
/* Get the current state. */
u.fenv = fegetenv_register ();
/* Clear the relevant bits. */
- u.l = u.l & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID)
+ n.l = u.l & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID)
| (excepts & FPSCR_STICKY_BITS));
/* Put the new state in effect. */
- fesetenv_register (u.fenv);
+ if (u.l != n.l)
+ fesetenv_register (n.fenv);
/* Success. */
return 0;
diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c
index 5883e09..94c01ab 100644
--- a/sysdeps/powerpc/fpu/fedisblxcpt.c
+++ b/sysdeps/powerpc/fpu/fedisblxcpt.c
@@ -22,15 +22,17 @@
int
fedisableexcept (int excepts)
{
- fenv_union_t fe;
- int result, new;
+ fenv_union_t fe, curr;
+ int result = 0, new;
- result = __fegetexcept ();
+ /* Get current exception mask to return. */
+ fe.fenv = curr.fenv = fegetenv_register ();
+ result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
- fe.fenv = fegetenv_register ();
+ /* Sets the new exception mask. */
if (excepts & FE_INEXACT)
fe.l &= ~(1 << (31 - FPSCR_XE));
if (excepts & FE_DIVBYZERO)
@@ -41,7 +43,9 @@ fedisableexcept (int excepts)
fe.l &= ~(1 << (31 - FPSCR_OE));
if (excepts & FE_INVALID)
fe.l &= ~(1 << (31 - FPSCR_VE));
- fesetenv_register (fe.fenv);
+
+ if (fe.l != curr.l)
+ fesetenv_register (fe.fenv);
new = __fegetexcept ();
if (new == 0 && result != 0)
diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c
index 8ad0f97..01a68cf 100644
--- a/sysdeps/powerpc/fpu/feenablxcpt.c
+++ b/sysdeps/powerpc/fpu/feenablxcpt.c
@@ -22,15 +22,17 @@
int
feenableexcept (int excepts)
{
- fenv_union_t fe;
- int result, new;
+ fenv_union_t fe, curr;
+ int result = 0, new;
- result = __fegetexcept ();
+ /* Get current exception mask to return. */
+ fe.fenv = curr.fenv = fegetenv_register ();
+ result = fenv_reg_to_exceptions (fe.l);
if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID)
excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID;
- fe.fenv = fegetenv_register ();
+ /* Sets the new exception mask. */
if (excepts & FE_INEXACT)
fe.l |= (1 << (31 - FPSCR_XE));
if (excepts & FE_DIVBYZERO)
@@ -41,7 +43,9 @@ feenableexcept (int excepts)
fe.l |= (1 << (31 - FPSCR_OE));
if (excepts & FE_INVALID)
fe.l |= (1 << (31 - FPSCR_VE));
- fesetenv_register (fe.fenv);
+
+ if (fe.l != curr.l)
+ fesetenv_register (fe.fenv);
new = __fegetexcept ();
if (new != 0 && result == 0)
diff --git a/sysdeps/powerpc/fpu/feholdexcpt.c b/sysdeps/powerpc/fpu/feholdexcpt.c
index 1375a2f..764dd38 100644
--- a/sysdeps/powerpc/fpu/feholdexcpt.c
+++ b/sysdeps/powerpc/fpu/feholdexcpt.c
@@ -32,6 +32,9 @@ feholdexcept (fenv_t *envp)
flag. */
new.l = old.l & 0xffffffff00000007LL;
+ if (new.l == old.l)
+ return 0;
+
/* If the old env had any enabled exceptions, then mask SIGFPE in the
MSR FE0/FE1 bits. This may allow the FPU to run faster because it
always takes the default action and can not generate SIGFPE. */
diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h
index 28e4d1f..c1df5ce 100644
--- a/sysdeps/powerpc/fpu/fenv_libc.h
+++ b/sysdeps/powerpc/fpu/fenv_libc.h
@@ -146,6 +146,23 @@ enum {
/* the remaining two least-significant bits keep the rounding mode */
};
+static inline int
+fenv_reg_to_exceptions (unsigned long long l)
+{
+ int result = 0;
+ if (l & (1 << (31 - FPSCR_XE)))
+ result |= FE_INEXACT;
+ if (l & (1 << (31 - FPSCR_ZE)))
+ result |= FE_DIVBYZERO;
+ if (l & (1 << (31 - FPSCR_UE)))
+ result |= FE_UNDERFLOW;
+ if (l & (1 << (31 - FPSCR_OE)))
+ result |= FE_OVERFLOW;
+ if (l & (1 << (31 - FPSCR_VE)))
+ result |= FE_INVALID;
+ return result;
+}
+
#ifdef _ARCH_PWR6
/* Not supported in ISA 2.05. Provided for source compat only. */
# define FPSCR_NI 29
diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c
index fa99ddb..138bde0 100644
--- a/sysdeps/powerpc/fpu/fesetenv.c
+++ b/sysdeps/powerpc/fpu/fesetenv.c
@@ -29,6 +29,8 @@ __fesetenv (const fenv_t *envp)
/* get the currently set exceptions. */
new.fenv = *envp;
old.fenv = fegetenv_register ();
+ if (old.l == new.l)
+ return 0;
/* If the old env has no enabled exceptions and the new env has any enabled
exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
diff --git a/sysdeps/powerpc/fpu/fsetexcptflg.c b/sysdeps/powerpc/fpu/fsetexcptflg.c
index 95193c1..cee6682 100644
--- a/sysdeps/powerpc/fpu/fsetexcptflg.c
+++ b/sysdeps/powerpc/fpu/fsetexcptflg.c
@@ -21,7 +21,7 @@
int
__fesetexceptflag (const fexcept_t *flagp, int excepts)
{
- fenv_union_t u;
+ fenv_union_t u, n;
fexcept_t flag;
/* Get the current state. */
@@ -31,7 +31,7 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts)
flag = *flagp & excepts;
/* Replace the exception status */
- u.l = ((u.l & ~(FPSCR_STICKY_BITS & excepts))
+ n.l = ((u.l & ~(FPSCR_STICKY_BITS & excepts))
| (flag & FPSCR_STICKY_BITS)
| (flag >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT))
& FE_INVALID_SOFTWARE));
@@ -39,7 +39,8 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts)
/* Store the new status word (along with the rest of the environment).
This may cause floating-point exceptions if the restored state
requests it. */
- fesetenv_register (u.fenv);
+ if (n.l != u.l)
+ fesetenv_register (u.fenv);
/* Deal with FE_INVALID_SOFTWARE not being implemented on some chips. */
if (flag & FE_INVALID)