diff mbox series

[PULL,4/4] softfloat: fix floatx80 pseudo-denormal round to integer

Message ID 20200515184722.31182-5-richard.henderson@linaro.org
State Accepted
Commit 9ecaf5ccec13ff2e8fe1e72f6e0f3367d2169c1c
Headers show
Series softfloat patch queue | expand

Commit Message

Richard Henderson May 15, 2020, 6:47 p.m. UTC
From: Joseph Myers <joseph@codesourcery.com>


The softfloat function floatx80_round_to_int incorrectly handles the
case of a pseudo-denormal where only the high bit of the significand
is set, ignoring that bit (treating the number as an exact zero)
rather than treating the number as an alternative representation of
+/- 2^-16382 (which may round to +/- 1 depending on the rounding mode)
as hardware does.  Fix this check (simplifying the code in the
process).

Signed-off-by: Joseph Myers <joseph@codesourcery.com>

Message-Id: <alpine.DEB.2.21.2005042339420.22972@digraph.polyomino.org.uk>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 fpu/softfloat.c                            |  2 +-
 tests/tcg/i386/test-i386-pseudo-denormal.c | 10 ++++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

-- 
2.20.1
diff mbox series

Patch

diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index c57f72e3a6..a362bf89ca 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -5741,7 +5741,7 @@  floatx80 floatx80_round_to_int(floatx80 a, float_status *status)
     }
     if ( aExp < 0x3FFF ) {
         if (    ( aExp == 0 )
-             && ( (uint64_t) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
+             && ( (uint64_t) ( extractFloatx80Frac( a ) ) == 0 ) ) {
             return a;
         }
         status->float_exception_flags |= float_flag_inexact;
diff --git a/tests/tcg/i386/test-i386-pseudo-denormal.c b/tests/tcg/i386/test-i386-pseudo-denormal.c
index acf2b9cf03..00d510cf4a 100644
--- a/tests/tcg/i386/test-i386-pseudo-denormal.c
+++ b/tests/tcg/i386/test-i386-pseudo-denormal.c
@@ -14,6 +14,7 @@  volatile long double ld_res;
 
 int main(void)
 {
+    short cw;
     int ret = 0;
     ld_res = ld_pseudo_m16382.ld + ld_pseudo_m16382.ld;
     if (ld_res != 0x1p-16381L) {
@@ -24,5 +25,14 @@  int main(void)
         printf("FAIL: pseudo-denormal compare\n");
         ret = 1;
     }
+    /* Set round-upward.  */
+    __asm__ volatile ("fnstcw %0" : "=m" (cw));
+    cw = (cw & ~0xc00) | 0x800;
+    __asm__ volatile ("fldcw %0" : : "m" (cw));
+    __asm__ ("frndint" : "=t" (ld_res) : "0" (ld_pseudo_m16382.ld));
+    if (ld_res != 1.0L) {
+        printf("FAIL: pseudo-denormal round-to-integer\n");
+        ret = 1;
+    }
     return ret;
 }