]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix powerpc fmax, fmin sNaN handling (bug 20947).
authorJoseph Myers <joseph@codesourcery.com>
Thu, 15 Dec 2016 00:43:16 +0000 (00:43 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Thu, 15 Dec 2016 00:43:16 +0000 (00:43 +0000)
Various fmax and fmin function implementations mishandle sNaN
arguments:

(a) When both arguments are NaNs, the return value should be a qNaN,
but sometimes it is an sNaN if at least one argument is an sNaN.

(b) Under TS 18661-1 semantics, if either argument is an sNaN then the
result should be a qNaN (whereas if one argument is a qNaN and the
other is not a NaN, the result should be the non-NaN argument).
Various implementations treat sNaNs like qNaNs here.

This patch fixes the powerpc versions of these functions (shared by
float and double, 32-bit and 64-bit).  The structure of those versions
is that all ordered cases are already handled before anything dealing
with the case where the arguments are unordered; thus, this patch
causes no change to the code executed in the common case (neither
argument a NaN).

Tested for powerpc (32-bit and 64-bit), together with tests to be
added along with the x86_64 / x86 fixes.

[BZ #20947]
* sysdeps/powerpc/fpu/s_fmax.S (__fmax): Add the arguments when
either is a signaling NaN.
* sysdeps/powerpc/fpu/s_fmin.S (__fmin): Likewise.

ChangeLog
sysdeps/powerpc/fpu/s_fmax.S
sysdeps/powerpc/fpu/s_fmin.S

index c08b711d7a67676ec0f43628949cf241ec70f53b..cf798fb84f0cf01558e2ddfad25bf4345c94646b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2016-12-15  Joseph Myers  <joseph@codesourcery.com>
+
+       [BZ #20947]
+       * sysdeps/powerpc/fpu/s_fmax.S (__fmax): Add the arguments when
+       either is a signaling NaN.
+       * sysdeps/powerpc/fpu/s_fmin.S (__fmin): Likewise.
+
 2016-12-14  Joseph Myers  <joseph@codesourcery.com>
 
        [BZ #20947]
index 75ee74c316164b47cd4ed1672f44b13bce2976c3..e6405c02dd6b9f3e630ea8c970b48be2db2a9d32 100644 (file)
@@ -25,7 +25,42 @@ ENTRY(__fmax)
        bnulr+  cr0
 /* x and y are unordered, so one of x or y must be a NaN... */
        fcmpu   cr1,fp2,fp2
-       bunlr   cr1
+       bun     cr1,1f
+/* x is a NaN; y is not.  Test if x is signaling.  */
+#ifdef __powerpc64__
+       stfd    fp1,-8(r1)
+       lwz     r3,-8+HIWORD(r1)
+#else
+       stwu    r1,-16(r1)
+       cfi_adjust_cfa_offset (16)
+       stfd    fp1,8(r1)
+       lwz     r3,8+HIWORD(r1)
+       addi    r1,r1,16
+       cfi_adjust_cfa_offset (-16)
+#endif
+       andis.  r3,r3,8
+       bne     cr0,0f
+       b       2f
+1:     /* y is a NaN; x may or may not be.  */
+       fcmpu   cr1,fp1,fp1
+       bun     cr1,2f
+/* y is a NaN; x is not.  Test if y is signaling.  */
+#ifdef __powerpc64__
+       stfd    fp2,-8(r1)
+       lwz     r3,-8+HIWORD(r1)
+#else
+       stwu    r1,-16(r1)
+       cfi_adjust_cfa_offset (16)
+       stfd    fp2,8(r1)
+       lwz     r3,8+HIWORD(r1)
+       addi    r1,r1,16
+       cfi_adjust_cfa_offset (-16)
+#endif
+       andis.  r3,r3,8
+       bnelr   cr0
+2:     /* x and y are NaNs, or one is a signaling NaN.  */
+       fadd    fp1,fp1,fp2
+       blr
 0:     fmr     fp1,fp2
        blr
 END(__fmax)
index 4d7c3b4fbc5dfd21ac6a783e9db4a623ef1d0685..9ae77feb36de8f432fab9033ca7b1db74700cfab 100644 (file)
@@ -25,7 +25,42 @@ ENTRY(__fmin)
        bnulr+  cr0
 /* x and y are unordered, so one of x or y must be a NaN... */
        fcmpu   cr1,fp2,fp2
-       bunlr   cr1
+       bun     cr1,1f
+/* x is a NaN; y is not.  Test if x is signaling.  */
+#ifdef __powerpc64__
+       stfd    fp1,-8(r1)
+       lwz     r3,-8+HIWORD(r1)
+#else
+       stwu    r1,-16(r1)
+       cfi_adjust_cfa_offset (16)
+       stfd    fp1,8(r1)
+       lwz     r3,8+HIWORD(r1)
+       addi    r1,r1,16
+       cfi_adjust_cfa_offset (-16)
+#endif
+       andis.  r3,r3,8
+       bne     cr0,0f
+       b       2f
+1:     /* y is a NaN; x may or may not be.  */
+       fcmpu   cr1,fp1,fp1
+       bun     cr1,2f
+/* y is a NaN; x is not.  Test if y is signaling.  */
+#ifdef __powerpc64__
+       stfd    fp2,-8(r1)
+       lwz     r3,-8+HIWORD(r1)
+#else
+       stwu    r1,-16(r1)
+       cfi_adjust_cfa_offset (16)
+       stfd    fp2,8(r1)
+       lwz     r3,8+HIWORD(r1)
+       addi    r1,r1,16
+       cfi_adjust_cfa_offset (-16)
+#endif
+       andis.  r3,r3,8
+       bnelr   cr0
+2:     /* x and y are NaNs, or one is a signaling NaN.  */
+       fadd    fp1,fp1,fp2
+       blr
 0:     fmr     fp1,fp2
        blr
 END(__fmin)