aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/powerpc/powerpc32/fpu
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2016-05-27 15:29:31 +0000
committerJoseph Myers <joseph@codesourcery.com>2016-05-27 15:29:31 +0000
commit24e9ae1bc22796990ab70475b233beaf109d1cfb (patch)
tree5b999ca930279336d16acd2e3bd4b23a235fba08 /sysdeps/powerpc/powerpc32/fpu
parentd8728df4306c07ed3dc64e825dec9f2e97cb826d (diff)
downloadglibc-24e9ae1bc22796990ab70475b233beaf109d1cfb.tar
glibc-24e9ae1bc22796990ab70475b233beaf109d1cfb.tar.gz
glibc-24e9ae1bc22796990ab70475b233beaf109d1cfb.tar.bz2
glibc-24e9ae1bc22796990ab70475b233beaf109d1cfb.zip
Avoid "invalid" exceptions from powerpc fabsl (sNaN) (bug 20157).
The powerpc implementations of fabsl for ldbl-128ibm (both powerpc32 and powerpc64) wrongly raise the "invalid" exception for sNaN arguments. fabs functions should be quiet for all inputs including signaling NaNs. The problem is the use of a comparison instruction fcmpu to determine if the high part of the argument is negative and so the low part needs to be negated; such instructions raise "invalid" for sNaNs. There is a pure integer implementation of fabsl in sysdeps/ieee754/ldbl-128ibm/s_fabsl.c. However, it's not necessary to use it to avoid such exceptions. The fsel instruction does not raise exceptions for sNaNs, and can be used in place of the original comparison. (Note that if the high part is zero or a NaN, it does not matter whether the low part is negated; the choice of whether the low part of a zero is +0 or -0 does not affect the value, and the low part of a NaN does not affect the value / payload either.) The condition in GCC for fsel to be available is TARGET_PPC_GFXOPT, corresponding to the _ARCH_PPCGR predefined macro. fsel is available on all 64-bit processors supported by GCC. A few 32-bit processors supported by GCC do not have TARGET_PPC_GFXOPT despite having hard float support. To support those processors, integer code (similar to that in copysignl) is included for the !_ARCH_PPCGR case for powerpc32. Tested for powerpc32 (configurations with and without _ARCH_PPCGR) and powerpc64. [BZ #20157] * sysdeps/powerpc/powerpc32/fpu/s_fabsl.S (__fabsl): Use fsel to determine whether to negate low half if [_ARCH_PPCGR], and integer comparison otherwise. * sysdeps/powerpc/powerpc64/fpu/s_fabsl.S (__fabsl): Use fsel to determine whether to negate low half.
Diffstat (limited to 'sysdeps/powerpc/powerpc32/fpu')
-rw-r--r--sysdeps/powerpc/powerpc32/fpu/s_fabsl.S21
1 files changed, 19 insertions, 2 deletions
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_fabsl.S b/sysdeps/powerpc/powerpc32/fpu/s_fabsl.S
index 0462d20630..866e817008 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_fabsl.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_fabsl.S
@@ -24,11 +24,28 @@ ENTRY(__fabsl)
/* long double [f1,f2] fabs (long double [f1,f2] x);
fabs(x,y) returns a value with the magnitude of x and
with the sign bit of y. */
+#ifdef _ARCH_PPCGR
+ /* fsel available. */
fmr fp0,fp1
+#else
+ /* Use integer operations to test sign of high part to avoid
+ exceptions on sNaNs. */
+ stwu r1,-16(r1)
+ cfi_adjust_cfa_offset (16)
+ stfd fp1,8(r1)
+#endif
fabs fp1,fp1
- fcmpu cr1,fp0,fp1
- beqlr cr1
+#ifdef _ARCH_PPCGR
+ fneg fp3,fp2
+ fsel fp2,fp0,fp2,fp3
+#else
+ lwz r3,8+HIWORD(r1)
+ cmpwi cr6,r3,0
+ addi r1,r1,16
+ cfi_adjust_cfa_offset (-16)
+ bgelr cr6
fneg fp2,fp2
+#endif
blr
END (__fabsl)