Commit 9ecaf5cc authored by Joseph Myers's avatar Joseph Myers Committed by Richard Henderson
Browse files

softfloat: fix floatx80 pseudo-denormal round to integer



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: default avatarJoseph Myers <joseph@codesourcery.com>
Message-Id: <alpine.DEB.2.21.2005042339420.22972@digraph.polyomino.org.uk>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
parent be53fa78
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+10 −0
Original line number Diff line number Diff line
@@ -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;
}