+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.
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;
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)
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)
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)
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)
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. */
/* 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
/* 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
int
__fesetexceptflag (const fexcept_t *flagp, int excepts)
{
- fenv_union_t u;
+ fenv_union_t u, n;
fexcept_t flag;
/* Get the current state. */
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));
/* 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)