aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2015-11-11 00:06:09 +0000
committerJoseph Myers <joseph@codesourcery.com>2015-11-11 00:06:09 +0000
commit71d1b0166b4ace0d804af2993b3815758b852efc (patch)
tree1cfe69ef93cf1fa482ecbd57dc324cd2494895a1 /sysdeps
parentfe534fe8980fa214c410e3661a4216e781073353 (diff)
downloadglibc-71d1b0166b4ace0d804af2993b3815758b852efc.zip
glibc-71d1b0166b4ace0d804af2993b3815758b852efc.tar.gz
glibc-71d1b0166b4ace0d804af2993b3815758b852efc.tar.bz2
Fix powerpc nearbyint wrongly clearing "inexact" and leaving traps disabled (bug 19228).
Similar to bug 15491 recently fixed for x86_64 / x86, the powerpc (both powerpc32 and powerpc64) hard-float implementations of nearbyintf and nearbyint wrongly clear an "inexact" exception that was raised before the function was called; this shows up as failure of the test math/test-nearbyint-except added when that bug was fixed. They also wrongly leave traps on "inexact" disabled if they were enabled before the function was called. This patch fixes the bugs similar to how the x86 bug was fixed: saving and restoring the whole floating-point state, both to restore the original "inexact" flag state and to restore the original state of whether traps on "inexact" were enabled. Because there's a convenient point in the powerpc implementations to save state after any sNaN arguments will have raised "invalid" but before "inexact" traps need to be disabled, no special handling for "invalid" is needed as in the x86 version. Tested for powerpc64 and powerpc32, where it fixes the math/test-nearbyint-except failure as well as fixing the new test math/test-nearbyint-except-2 added by this patch. Also tested for x86_64 and x86 that the new test passes. If powerpc experts see a more efficient way of doing this (e.g. instruction positioning that's better for pipelines on typical processors) then of course followups optimizing the fix are welcome. [BZ #19228] * sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S (__nearbyint): Save and restore full floating-point state. * sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S (__nearbyintf): Likewise. * sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S (__nearbyint): Likewise. * sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S (__nearbyintf): Likewise. * math/test-nearbyint-except-2.c: New file. * math/Makefile (tests): Add test-nearbyint-except-2.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S6
-rw-r--r--sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S6
-rw-r--r--sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S6
-rw-r--r--sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S6
4 files changed, 16 insertions, 8 deletions
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S b/sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S
index cee4c7b..27673b6 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S
@@ -52,19 +52,21 @@ ENTRY (__nearbyint)
bgelr cr7
fcmpu cr7,fp1,fp12 /* if (x > 0.0 */
ble cr7,L(lessthanzero)
+ mffs fp11
mtfsb0 4*cr7+lt /* Disable FE_INEXACT exception */
fadd fp1,fp1,fp13 /* x += TWO52 */
fsub fp1,fp1,fp13 /* x -= TWO52 */
fabs fp1,fp1 /* if (x == 0.0 */
- mtfsb0 4*cr1+eq /* Clear any FE_INEXACT exception */
+ mtfsf 0xff,fp11 /* Restore FE_INEXACT state. */
blr
L(lessthanzero):
bgelr cr7
+ mffs fp11
mtfsb0 4*cr7+lt /* Disable FE_INEXACT exception */
fsub fp1,fp1,fp13 /* x -= TWO52 */
fadd fp1,fp1,fp13 /* x += TWO52 */
fnabs fp1,fp1 /* if (x == 0.0) */
- mtfsb0 4*cr1+eq /* Clear any FE_INEXACT exception */
+ mtfsf 0xff,fp11 /* Restore FE_INEXACT state. */
blr
END (__nearbyint)
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S b/sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S
index 96a39c6..a5084b2 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S
@@ -51,19 +51,21 @@ ENTRY (__nearbyintf)
bgelr cr7
fcmpu cr7,fp1,fp12 /* if (x > 0.0 */
ble cr7,L(lessthanzero)
+ mffs fp11
mtfsb0 4*cr7+lt /* Disable FE_INEXACT exception */
fadds fp1,fp1,fp13 /* x += TWO23 */
fsubs fp1,fp1,fp13 /* x -= TWO23 */
fabs fp1,fp1 /* if (x == 0.0) */
- mtfsb0 4*cr1+eq /* Clear any FE_INEXACT exception */
+ mtfsf 0xff,fp11 /* Restore FE_INEXACT state. */
blr
L(lessthanzero):
bgelr cr7
+ mffs fp11
mtfsb0 4*cr7+lt /* Disable FE_INEXACT exception */
fsubs fp1,fp1,fp13 /* x -= TWO23 */
fadds fp1,fp1,fp13 /* x += TWO23 */
fnabs fp1,fp1 /* if (x == 0.0) */
- mtfsb0 4*cr1+eq /* Clear any FE_INEXACT exception */
+ mtfsf 0xff,fp11 /* Restore FE_INEXACT state. */
blr
END (__nearbyintf)
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S b/sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S
index 6654840..9c87596 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S
@@ -40,19 +40,21 @@ EALIGN (__nearbyint, 4, 0)
fsub fp12,fp13,fp13 /* generate 0.0 */
fcmpu cr7,fp1,fp12 /* if (x > 0.0) */
ble cr7, L(lessthanzero)
+ mffs fp11
mtfsb0 4*cr7+lt /* Disable FE_INEXACT exception */
fadd fp1,fp1,fp13 /* x+= TWO52 */
fsub fp1,fp1,fp13 /* x-= TWO52 */
fabs fp1,fp1 /* if (x == 0.0) */
- mtfsb0 4*cr1+eq /* Clear any FE_INEXACT exception */
+ mtfsf 0xff,fp11 /* Restore FE_INEXACT state. */
blr /* x = 0.0; */
L(lessthanzero):
bgelr cr7 /* if (x < 0.0) */
+ mffs fp11
mtfsb0 4*cr7+lt
fsub fp1,fp1,fp13 /* x -= TWO52 */
fadd fp1,fp1,fp13 /* x += TWO52 */
fnabs fp1,fp1 /* if (x == 0.0) */
- mtfsb0 4*cr1+eq
+ mtfsf 0xff,fp11 /* Restore FE_INEXACT state. */
blr /* x = -0.0; */
END (__nearbyint)
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S b/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S
index 041dfeb..9dfbce6 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S
@@ -41,19 +41,21 @@ EALIGN (__nearbyintf, 4, 0)
fsubs fp12,fp13,fp13 /* generate 0.0 */
fcmpu cr7,fp1,fp12 /* if (x > 0.0) */
ble cr7, L(lessthanzero)
+ mffs fp11
mtfsb0 4*cr7+lt /* Disable FE_INEXACT exception */
fadds fp1,fp1,fp13 /* x += TWO23 */
fsubs fp1,fp1,fp13 /* x -= TWO23 */
fabs fp1,fp1 /* if (x == 0.0) */
- mtfsb0 4*cr1+eq /* Clear pending FE_INEXACT exception */
+ mtfsf 0xff,fp11 /* Restore FE_INEXACT state. */
blr /* x = 0.0; */
L(lessthanzero):
bgelr cr7 /* if (x < 0.0) */
+ mffs fp11
mtfsb0 4*cr7+lt /* Disable FE_INEXACT exception */
fsubs fp1,fp1,fp13 /* x -= TWO23 */
fadds fp1,fp1,fp13 /* x += TWO23 */
fnabs fp1,fp1 /* if (x == 0.0) */
- mtfsb0 4*cr1+eq /* Clear pending FE_INEXACT exception */
+ mtfsf 0xff,fp11 /* Restore FE_INEXACT state. */
blr /* x = -0.0; */
END (__nearbyintf)