From 632d8780deab9576847a51228129b782f8e8c18b Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Sun, 28 Apr 2024 06:41:29 +0300 Subject: [PATCH] rewrite code for biasing unmasked underflow for floatx80 in softfloat3e (from hack to clean code) --- bochs/cpu/softfloat3e/s_roundPackToExtF80.c | 104 ++++++++++---------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/bochs/cpu/softfloat3e/s_roundPackToExtF80.c b/bochs/cpu/softfloat3e/s_roundPackToExtF80.c index b0d4039ba..fea854024 100644 --- a/bochs/cpu/softfloat3e/s_roundPackToExtF80.c +++ b/bochs/cpu/softfloat3e/s_roundPackToExtF80.c @@ -76,25 +76,29 @@ extFloat80_t /*---------------------------------------------------------------- *----------------------------------------------------------------*/ isTiny = (exp < 0) || (sig <= (uint64_t) (sig + roundIncrement)); - sig = softfloat_shiftRightJam64(sig, 1 - exp); - sigExact = sig; - roundBits = sig & roundMask; - sig += roundIncrement; - exp = ((sig & UINT64_C(0x8000000000000000)) != 0); - roundIncrement = roundMask + 1; - if (roundNearEven && (roundBits<<1 == roundIncrement)) { - roundMask |= roundIncrement; + if (isTiny && sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 0x6000; } - sig &= ~roundMask; - if (isTiny) { - if (roundBits || (sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow))) - softfloat_raiseFlags(status, softfloat_flag_underflow); + else { + sig = softfloat_shiftRightJam64(sig, 1 - exp); + roundBits = sig & roundMask; + sigExact = sig; + sig += roundIncrement; + exp = ((sig & UINT64_C(0x8000000000000000)) != 0); + roundIncrement = roundMask + 1; + if (roundNearEven && (roundBits<<1 == roundIncrement)) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > sigExact) softfloat_setRoundingUp(status); + if (isTiny) + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + return packToExtF80(sign, exp, sig); } - if (roundBits) { - softfloat_raiseFlags(status, softfloat_flag_inexact); - if (sig > sigExact) softfloat_setRoundingUp(status); - } - return packToExtF80(sign, exp, sig); } if ((0x7FFE < exp) || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))) { goto overflow; @@ -102,9 +106,6 @@ extFloat80_t } /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ - if (roundBits) { - softfloat_raiseFlags(status, softfloat_flag_inexact); - } sigExact = sig; sig = (uint64_t) (sig + roundIncrement); if (sig < roundIncrement) { @@ -117,7 +118,10 @@ extFloat80_t roundMask |= roundIncrement; } sig &= ~roundMask; - if (sig > sigExact) softfloat_setRoundingUp(status); + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > sigExact) softfloat_setRoundingUp(status); + } return packToExtF80(sign, exp, sig); /*------------------------------------------------------------------------ *------------------------------------------------------------------------*/ @@ -134,30 +138,35 @@ extFloat80_t /*---------------------------------------------------------------- *----------------------------------------------------------------*/ isTiny = (exp < 0) || ! doIncrement || (sig < UINT64_C(0xFFFFFFFFFFFFFFFF)); - sig64Extra = softfloat_shiftRightJam64Extra(sig, sigExtra, 1 - exp); - exp = 0; - sig = sig64Extra.v; - sigExtra = sig64Extra.extra; - if (isTiny) { - if (sigExtra || (sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow))) - softfloat_raiseFlags(status, softfloat_flag_underflow); + if (isTiny && sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 0x6000; } - if (sigExtra) - softfloat_raiseFlags(status, softfloat_flag_inexact); - doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); - if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { - doIncrement = - (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; + else { + sig64Extra = softfloat_shiftRightJam64Extra(sig, sigExtra, 1 - exp); + exp = 0; + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + if (sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (isTiny) + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + doIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; + } + if (doIncrement) { + sigExact = sig; + ++sig; + sig &= ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF)) & roundNearEven); + exp = ((sig & UINT64_C(0x8000000000000000)) != 0); + if (sig > sigExact) + softfloat_setRoundingUp(status); + } + return packToExtF80(sign, exp, sig); } - if (doIncrement) { - sigExact = sig; - ++sig; - sig &= ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF)) & roundNearEven); - exp = ((sig & UINT64_C(0x8000000000000000)) != 0); - if (sig > sigExact) - softfloat_setRoundingUp(status); - } - return packToExtF80(sign, exp, sig); } if ((0x7FFE < exp) || ((exp == 0x7FFE) && (sig == UINT64_C(0xFFFFFFFFFFFFFFFF)) && doIncrement)) { /*---------------------------------------------------------------- @@ -206,18 +215,11 @@ extFloat80_t extFloat80_t softfloat_roundPackToExtF80(bool sign, int32_t exp, uint64_t sig, uint64_t sigExtra, uint8_t roundingPrecision, struct softfloat_status_t *status) { - softfloat_status_t round_status = *status; extFloat80_t result = SoftFloat_roundPackToExtF80(sign, exp, sig, sigExtra, roundingPrecision, status); - // bias unmasked underflow - if (status->softfloat_exceptionFlags & ~status->softfloat_exceptionMasks & softfloat_flag_underflow) { - softfloat_raiseFlags(&round_status, softfloat_flag_underflow); - result = SoftFloat_roundPackToExtF80(sign, exp + 0x6000, sig, sigExtra, roundingPrecision, &round_status); - *status = round_status; - } - // bias unmasked overflow if (status->softfloat_exceptionFlags & ~status->softfloat_exceptionMasks & softfloat_flag_overflow) { + softfloat_status_t round_status = *status; softfloat_raiseFlags(&round_status, softfloat_flag_overflow); result = SoftFloat_roundPackToExtF80(sign, exp - 0x6000, sig, sigExtra, roundingPrecision, &round_status); *status = round_status;