From 2d50384633f7946e8a5a8d3016f5e501c387aed8 Mon Sep 17 00:00:00 2001 From: Joseph Myers <joseph@codesourcery.com> Date: Thu, 25 Feb 2021 13:36:40 -0500 Subject: [PATCH] softfloat: do not return pseudo-denormal from floatx80 remainder The floatx80 remainder implementation sometimes returns the numerator unchanged when the denominator is sufficiently larger than the numerator. But if the value to be returned unchanged is a pseudo-denormal, that is incorrect. Fix it to normalize the numerator in that case. Backports commit b662495dca0a2a36008cf8def91e2566519ed3f2 from qemu --- qemu/fpu/softfloat.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/qemu/fpu/softfloat.c b/qemu/fpu/softfloat.c index 8e223a61..b5c80035 100644 --- a/qemu/fpu/softfloat.c +++ b/qemu/fpu/softfloat.c @@ -5668,7 +5668,7 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, float_status *status) { bool aSign, zSign; - int32_t aExp, bExp, expDiff; + int32_t aExp, bExp, expDiff, aExpOrig; uint64_t aSig0, aSig1, bSig; uint64_t q, term0, term1, alternateASig0, alternateASig1; @@ -5677,7 +5677,7 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, return floatx80_default_nan(status); } aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); + aExpOrig = aExp = extractFloatx80Exp( a ); aSign = extractFloatx80Sign( a ); bSig = extractFloatx80Frac( b ); bExp = extractFloatx80Exp( b ); @@ -5692,6 +5692,13 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, if ((uint64_t)(bSig << 1)) { return propagateFloatx80NaN(a, b, status); } + if (aExp == 0 && aSig0 >> 63) { + /* + * Pseudo-denormal argument must be returned in normalized + * form. + */ + return packFloatx80(aSign, 1, aSig0); + } return a; } if ( bExp == 0 ) { @@ -5711,7 +5718,16 @@ floatx80 floatx80_modrem(floatx80 a, floatx80 b, bool mod, expDiff = aExp - bExp; aSig1 = 0; if ( expDiff < 0 ) { - if ( mod || expDiff < -1 ) return a; + if ( mod || expDiff < -1 ) { + if (aExp == 1 && aExpOrig == 0) { + /* + * Pseudo-denormal argument must be returned in + * normalized form. + */ + return packFloatx80(aSign, aExp, aSig0); + } + return a; + } shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); expDiff = 0; }