]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix powerpc round, roundf spurious "inexact" (bug 19238).
authorJoseph Myers <joseph@codesourcery.com>
Thu, 12 Nov 2015 19:00:06 +0000 (19:00 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Thu, 12 Nov 2015 19:00:06 +0000 (19:00 +0000)
The powerpc hard-float round and roundf functions, both 32-bit and
64-bit, raise spurious "inexact" exceptions for integer arguments from
adding 0.5 and rounding to integer toward zero.

Since these functions already save and restore the rounding mode, it's
natural to make them restore the full floating-point state instead to
fix this bug, which this patch does.  The save of the state is moved
after the first floating-point operation on the input so that any
"invalid" exceptions from signaling NaN inputs are properly
preserved.  As a consequence of this approach to the fix, "inexact"
for noninteger arguments (disallowed by TS 18661-1 but not by C99/C11,
see bug 15479) is also avoided for these implementations; this is
*not* a general fix for bug 15479 since plenty of other
implementations of various functions still raise spurious "inexact"
for noninteger arguments.

This issue and fix do not apply to builds using power5+ versions of
round and roundf, which use the frin instruction and avoid "inexact"
exceptions that way.

This patch should get hard-float powerpc32 and powerpc64 (default
function implementations) back to a state where test-float and
test-double will pass after ulps regeneration.

Tested for powerpc32 and powerpc64.

[BZ #15479]
[BZ #19238]
* sysdeps/powerpc/powerpc32/fpu/s_round.S (__round): Save
floating-point state after first operation on input.  Restore full
state rather than just rounding mode.
* sysdeps/powerpc/powerpc32/fpu/s_roundf.S (__roundf): Likewise.
* sysdeps/powerpc/powerpc64/fpu/s_round.S (__round): Likewise.
* sysdeps/powerpc/powerpc64/fpu/s_roundf.S (__roundf): Likewise.

ChangeLog
sysdeps/powerpc/powerpc32/fpu/s_round.S
sysdeps/powerpc/powerpc32/fpu/s_roundf.S
sysdeps/powerpc/powerpc64/fpu/s_round.S
sysdeps/powerpc/powerpc64/fpu/s_roundf.S

index e902b8125b94d97f6069f1228bb93f89fb9323cf..ff181065605eb213be6384643eb77766c575d98b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2015-11-12  Joseph Myers  <joseph@codesourcery.com>
 
+       [BZ #15479]
+       [BZ #19238]
+       * sysdeps/powerpc/powerpc32/fpu/s_round.S (__round): Save
+       floating-point state after first operation on input.  Restore full
+       state rather than just rounding mode.
+       * sysdeps/powerpc/powerpc32/fpu/s_roundf.S (__roundf): Likewise.
+       * sysdeps/powerpc/powerpc64/fpu/s_round.S (__round): Likewise.
+       * sysdeps/powerpc/powerpc64/fpu/s_roundf.S (__roundf): Likewise.
+
        [BZ #19235]
        * sysdeps/powerpc/powerpc64/fpu/s_llround.S (__llround): Do not
        add 0.5 to integer arguments.
index 061fbe2575f0e6c9b20989ced02024fd375c5b2f..18ba18a870705bdda5c1f7d54e8a3e8eb3248b3d 100644 (file)
@@ -38,7 +38,6 @@
 
        .section        ".text"
 ENTRY (__round)
-       mffs    fp11            /* Save current FPU rounding mode.  */
 #ifdef SHARED
        mflr    r11
        cfi_register(lr,r11)
@@ -55,6 +54,8 @@ ENTRY (__round)
        fabs    fp0,fp1
        fsub    fp12,fp13,fp13  /* generate 0.0  */
        fcmpu   cr7,fp0,fp13    /* if (fabs(x) > TWO52)  */
+       mffs    fp11            /* Save current FPU rounding mode and
+                                  "inexact" state.  */
        fcmpu   cr6,fp1,fp12    /* if (x > 0.0)  */
        bnllr-  cr7
        mtfsfi  7,1             /* Set rounding mode toward 0.  */
@@ -70,7 +71,8 @@ ENTRY (__round)
        fsub    fp1,fp1,fp13    /* x-= TWO52;  */
        fabs    fp1,fp1         /* if (x == 0.0)  */
                                /* x = 0.0; */
-       mtfsf   0x01,fp11       /* restore previous rounding mode.  */
+       mtfsf   0xff,fp11       /* Restore previous rounding mode and
+                                  "inexact" state.  */
        blr
 .L4:
        fsub    fp9,fp1,fp10    /* x+= 0.5;  */
@@ -80,7 +82,8 @@ ENTRY (__round)
        fnabs   fp1,fp1         /* if (x == 0.0)  */
                                /* x = -0.0; */
 .L9:
-       mtfsf   0x01,fp11       /* restore previous rounding mode.  */
+       mtfsf   0xff,fp11       /* Restore previous rounding mode and
+                                  "inexact" state.  */
        blr
        END (__round)
 
index 414bede3617c6a7f18e9616c8e08ea35b8010ffb..e69a8233e077ac06b686e314c548b9e3907aeb88 100644 (file)
@@ -37,7 +37,6 @@
 
        .section        ".text"
 ENTRY (__roundf )
-       mffs    fp11            /* Save current FPU rounding mode.  */
 #ifdef SHARED
        mflr    r11
        cfi_register(lr,r11)
@@ -54,6 +53,8 @@ ENTRY (__roundf )
        fabs    fp0,fp1
        fsubs   fp12,fp13,fp13  /* generate 0.0  */
        fcmpu   cr7,fp0,fp13    /* if (fabs(x) > TWO23)  */
+       mffs    fp11            /* Save current FPU rounding mode and
+                                  "inexact" state.  */
        fcmpu   cr6,fp1,fp12    /* if (x > 0.0)  */
        bnllr-  cr7
        mtfsfi  7,1             /* Set rounding mode toward 0.  */
@@ -68,7 +69,8 @@ ENTRY (__roundf )
        fsubs   fp1,fp1,fp13    /* x-= TWO23;  */
        fabs    fp1,fp1         /* if (x == 0.0)  */
                                /* x = 0.0; */
-       mtfsf   0x01,fp11       /* restore previous rounding mode.  */
+       mtfsf   0xff,fp11       /* Restore previous rounding mode and
+                                  "inexact" state.  */
        blr
 .L4:
        fsubs   fp9,fp1,fp10    /* x+= 0.5;  */
@@ -78,7 +80,8 @@ ENTRY (__roundf )
        fnabs   fp1,fp1         /* if (x == 0.0)  */
                                /* x = -0.0; */
 .L9:
-       mtfsf   0x01,fp11       /* restore previous rounding mode.  */
+       mtfsf   0xff,fp11       /* Restore previous rounding mode and
+                                  "inexact" state.  */
        blr
        END (__roundf)
 
index 2f99c04d1fdd39a54affdbd5b4fe01b8494822a8..31ede3953d61e79eeb4c96180e72662e772440f4 100644 (file)
 
 EALIGN (__round, 4, 0)
        CALL_MCOUNT 0
-       mffs    fp11            /* Save current FPU rounding mode.  */
        lfd     fp13,.LC0@toc(2)
        fabs    fp0,fp1
        fsub    fp12,fp13,fp13  /* generate 0.0  */
        fcmpu   cr7,fp0,fp13    /* if (fabs(x) > TWO52)  */
+       mffs    fp11            /* Save current FPU rounding mode and
+                                  "inexact" state.  */
        fcmpu   cr6,fp1,fp12    /* if (x > 0.0)  */
        bnllr-  cr7
        mtfsfi  7,1             /* Set rounding mode toward 0.  */
@@ -53,7 +54,8 @@ EALIGN (__round, 4, 0)
        fsub    fp1,fp1,fp13    /* x-= TWO52;  */
        fabs    fp1,fp1         /* if (x == 0.0)  */
                                /* x = 0.0; */
-       mtfsf   0x01,fp11       /* restore previous rounding mode.  */
+       mtfsf   0xff,fp11       /* Restore previous rounding mode and
+                                  "inexact" state.  */
        blr
 .L4:
        fsub    fp9,fp1,fp10    /* x+= 0.5;  */
@@ -63,7 +65,8 @@ EALIGN (__round, 4, 0)
        fnabs   fp1,fp1         /* if (x == 0.0)  */
                                /* x = -0.0; */
 .L9:
-       mtfsf   0x01,fp11       /* restore previous rounding mode.  */
+       mtfsf   0xff,fp11       /* Restore previous rounding mode and
+                                  "inexact" state.  */
        blr
        END (__round)
 
index babb52b0d4e58a625cd89a2de8dd239db5d22912..3ccf48c23b3c4db07b13edc789b26a3dce7f4df5 100644 (file)
 
 EALIGN (__roundf, 4, 0)
        CALL_MCOUNT 0
-       mffs    fp11            /* Save current FPU rounding mode.  */
        lfs     fp13,.LC0@toc(2)
        fabs    fp0,fp1
        fsubs   fp12,fp13,fp13  /* generate 0.0  */
        fcmpu   cr7,fp0,fp13    /* if (fabs(x) > TWO23)  */
+       mffs    fp11            /* Save current FPU rounding mode and
+                                  "inexact" state.  */
        fcmpu   cr6,fp1,fp12    /* if (x > 0.0)  */
        bnllr-  cr7
        mtfsfi  7,1             /* Set rounding mode toward 0.  */
@@ -54,7 +55,8 @@ EALIGN (__roundf, 4, 0)
        fsubs   fp1,fp1,fp13    /* x-= TWO23;  */
        fabs    fp1,fp1         /* if (x == 0.0)  */
                                /* x = 0.0; */
-       mtfsf   0x01,fp11       /* restore previous rounding mode.  */
+       mtfsf   0xff,fp11       /* Restore previous rounding mode and
+                                  "inexact" state.  */
        blr
 .L4:
        fsubs   fp9,fp1,fp10    /* x+= 0.5;  */
@@ -64,7 +66,8 @@ EALIGN (__roundf, 4, 0)
        fnabs   fp1,fp1         /* if (x == 0.0)  */
                                /* x = -0.0; */
 .L9:
-       mtfsf   0x01,fp11       /* restore previous rounding mode.  */
+       mtfsf   0xff,fp11       /* Restore previous rounding mode and
+                                  "inexact" state.  */
        blr
        END (__roundf)