From patchwork Thu Mar 25 14:00:11 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Froyd X-Patchwork-Id: 48523 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 380BCB7C8E for ; Fri, 26 Mar 2010 01:25:39 +1100 (EST) Received: from localhost ([127.0.0.1]:41233 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Nunyu-0005yf-3B for incoming@patchwork.ozlabs.org; Thu, 25 Mar 2010 10:24:20 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Nunbp-0003qm-8G for qemu-devel@nongnu.org; Thu, 25 Mar 2010 10:00:29 -0400 Received: from [140.186.70.92] (port=43527 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Nunbf-0003mh-EL for qemu-devel@nongnu.org; Thu, 25 Mar 2010 10:00:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1NunbZ-0001Gn-T0 for qemu-devel@nongnu.org; Thu, 25 Mar 2010 10:00:19 -0400 Received: from mx20.gnu.org ([199.232.41.8]:49951) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1NunbZ-0001Gj-Od for qemu-devel@nongnu.org; Thu, 25 Mar 2010 10:00:13 -0400 Received: from mail.codesourcery.com ([38.113.113.100]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NunbY-0002YU-ME for qemu-devel@nongnu.org; Thu, 25 Mar 2010 10:00:13 -0400 Received: (qmail 20807 invoked from network); 25 Mar 2010 14:00:11 -0000 Received: from unknown (HELO localhost) (froydnj@127.0.0.2) by mail.codesourcery.com with ESMTPA; 25 Mar 2010 14:00:11 -0000 Date: Thu, 25 Mar 2010 07:00:11 -0700 From: Nathan Froyd To: Juha.Riihimaki@nokia.com Subject: WIP flush-to-zero patch [was: Re: [Qemu-devel] QEMU state of ARM NEON support.] Message-ID: <20100325140011.GT16726@codesourcery.com> References: <4BA7741F.60209@ispras.ru> <372ED49D-DF43-4E6C-AA3D-F4DA95746981@nokia.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <372ED49D-DF43-4E6C-AA3D-F4DA95746981@nokia.com> User-Agent: Mutt/1.5.17+20080114 (2008-01-14) X-detected-operating-system: by mx20.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: qemu-devel@nongnu.org, zhur@ispras.ru X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org On Thu, Mar 25, 2010 at 08:52:39AM +0100, Juha.Riihimaki@nokia.com wrote: > - Using subnormal floating point input values yields wrong results > (this is visible in your vceq/vcgt/vcle tests against zero), I guess > this would need to be corrected in the softfloat library which QEMU > uses. FWIW, below is a WIP progress patch to implement flush-to-zero better. The motivating observation is that many chips feature separate flush-input and flush-output flags and QEMU's fpu/ library only implements flush-output. So the bulk of the patch is: - replacing the ad-hoc unpacking of float values into (sign, exponent, significand) with a centralized routine that will apply flush-to-zero on input values; - splitting float_status.flush_to_zero into separate input/output flags; - modifying targets to set input/output flags appropriately. The float_flag_input_denormal is entirely optional; I thought it might make sense for chips that may raise exceptions on denormal inputs (e.g. many MIPS chips). Perhaps it makes more sense to provide floatZZ_is_denormal and let chip emulation handle those cases themselves. The patch is untested, and likely won't work for NEON as-is, since NEON uses a separate float_status control. But extending the patch to work with NEON should be straightforward. -Nathan diff --git a/fpu/softfloat.c b/fpu/softfloat.c index e6065b4..f10db48 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -204,6 +204,25 @@ INLINE flag extractFloat32Sign( float32 a ) } /*---------------------------------------------------------------------------- +| Unpacks the fractional, exponent, and sign bits of the single-precision +| floating-point value `a' into the locations pointed to by `aSigPtr', +| `aExpPtr', and `aSignPtr', respectively. +-----------------------------------------------------------------------------*/ + +INLINE void + unpackFloat32( float32 a, bits32 *aSigPtr, int16 *aExpPtr, flag *aSignPtr STATUS_PARAM ) +{ + *aSigPtr = extractFloat32Frac( a ); + *aExpPtr = extractFloat32Exp( a ); + *aSignPtr = extractFloat32Sign( a ); + + if ( STATUS(flush_inputs_to_zero) && *aExpPtr == 0 ) { + *aSigPtr = 0; + float_raise( float_flag_input_denormal STATUS_VAR); + } +} + +/*---------------------------------------------------------------------------- | Normalizes the subnormal single-precision floating-point value represented | by the denormalized significand `aSig'. The normalized exponent and | significand are stored at the locations pointed to by `zExpPtr' and @@ -296,7 +315,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_P return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 )); } if ( zExp < 0 ) { - if ( STATUS(flush_to_zero) ) return packFloat32( zSign, 0, 0 ); + if ( STATUS(flush_outputs_to_zero) ) return packFloat32( zSign, 0, 0 ); isTiny = ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) || ( zExp < -1 ) @@ -368,6 +387,25 @@ INLINE flag extractFloat64Sign( float64 a ) } /*---------------------------------------------------------------------------- +| Unpacks the fractional, exponent, and sign bits of the double-precision +| floating-point value `a' into the locations pointed to by `aSigPtr', +| `aExpPtr', and `aSignPtr', respectively. +-----------------------------------------------------------------------------*/ + +INLINE void + unpackFloat64( float64 a, bits64 *aSigPtr, int16 *aExpPtr, flag *aSignPtr STATUS_PARAM ) +{ + *aSigPtr = extractFloat64Frac( a ); + *aExpPtr = extractFloat64Exp( a ); + *aSignPtr = extractFloat64Sign( a ); + + if ( STATUS(flush_inputs_to_zero) && *aExpPtr == 0 ) { + *aSigPtr = 0; + float_raise( float_flag_input_denormal STATUS_VAR); + } +} + +/*---------------------------------------------------------------------------- | Normalizes the subnormal double-precision floating-point value represented | by the denormalized significand `aSig'. The normalized exponent and | significand are stored at the locations pointed to by `zExpPtr' and @@ -460,7 +498,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_P return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 )); } if ( zExp < 0 ) { - if ( STATUS(flush_to_zero) ) return packFloat64( zSign, 0, 0 ); + if ( STATUS(flush_outputs_to_zero) ) return packFloat64( zSign, 0, 0 ); isTiny = ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) || ( zExp < -1 ) @@ -537,6 +575,25 @@ INLINE flag extractFloatx80Sign( floatx80 a ) } /*---------------------------------------------------------------------------- +| Unpacks the fractional, exponent, and sign bits of the extended +| double-precision floating-point value `a' into the locations pointed to by +| `aSigPtr', `aExpPtr', and `aSignPtr', respectively. +-----------------------------------------------------------------------------*/ + +INLINE void + unpackFloatx80( floatx80 a, bits64 *aSigPtr, int32 *aExpPtr, flag *aSignPtr STATUS_PARAM ) +{ + *aSigPtr = extractFloatx80Frac( a ); + *aExpPtr = extractFloatx80Exp( a ); + *aSignPtr = extractFloatx80Sign( a ); + + if ( STATUS(flush_inputs_to_zero) && *aExpPtr == 0 ) { + *aSigPtr = 0; + float_raise( float_flag_input_denormal STATUS_VAR); + } +} + +/*---------------------------------------------------------------------------- | Normalizes the subnormal extended double-precision floating-point value | represented by the denormalized significand `aSig'. The normalized exponent | and significand are stored at the locations pointed to by `zExpPtr' and @@ -639,7 +696,7 @@ static floatx80 goto overflow; } if ( zExp <= 0 ) { - if ( STATUS(flush_to_zero) ) return packFloatx80( zSign, 0, 0 ); + if ( STATUS(flush_outputs_to_zero) ) return packFloatx80( zSign, 0, 0 ); isTiny = ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) || ( zExp < 0 ) @@ -834,6 +891,30 @@ INLINE flag extractFloat128Sign( float128 a ) } /*---------------------------------------------------------------------------- +| Unpacks the least-significant 64 fraction, the most-significant 48 fraction, +| exponent, and sign bits of the quadruple-precision floating-point value `a' +| into the locations pointed to by `aSig1Ptr', `aSig0Ptr', `aExpPtr', and +| `aSignPtr', respectively. +-----------------------------------------------------------------------------*/ + +INLINE void + unpackFloat128( + float128 a, bits64 *aSig1Ptr, bits64 *aSig0Ptr, + int32 *aExpPtr, flag *aSignPtr STATUS_PARAM ) +{ + *aSig1Ptr = extractFloat128Frac1( a ); + *aSig0Ptr = extractFloat128Frac0( a ); + *aExpPtr = extractFloat128Exp( a ); + *aSignPtr = extractFloat128Sign( a ); + + if ( STATUS(flush_inputs_to_zero) && *aExpPtr == 0 ) { + *aSig1Ptr = 0; + *aSig0Ptr = 0; + float_raise( float_flag_input_denormal STATUS_VAR); + } +} + +/*---------------------------------------------------------------------------- | Normalizes the subnormal quadruple-precision floating-point value | represented by the denormalized significand formed by the concatenation of | `aSig0' and `aSig1'. The normalized exponent is stored at the location @@ -970,7 +1051,7 @@ static float128 return packFloat128( zSign, 0x7FFF, 0, 0 ); } if ( zExp < 0 ) { - if ( STATUS(flush_to_zero) ) return packFloat128( zSign, 0, 0, 0 ); + if ( STATUS(flush_outputs_to_zero) ) return packFloat128( zSign, 0, 0, 0 ); isTiny = ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) || ( zExp < -1 ) @@ -1298,9 +1379,7 @@ int32 float32_to_int32( float32 a STATUS_PARAM ) bits32 aSig; bits64 aSig64; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); if ( ( aExp == 0xFF ) && aSig ) aSign = 0; if ( aExp ) aSig |= 0x00800000; shiftCount = 0xAF - aExp; @@ -1328,9 +1407,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM ) bits32 aSig; int32 z; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); shiftCount = aExp - 0x9E; if ( 0 <= shiftCount ) { if ( float32_val(a) != 0xCF000000 ) { @@ -1370,9 +1447,7 @@ int64 float32_to_int64( float32 a STATUS_PARAM ) bits32 aSig; bits64 aSig64, aSigExtra; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); shiftCount = 0xBE - aExp; if ( shiftCount < 0 ) { float_raise( float_flag_invalid STATUS_VAR); @@ -1407,9 +1482,7 @@ int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM ) bits64 aSig64; int64 z; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); shiftCount = aExp - 0xBE; if ( 0 <= shiftCount ) { if ( float32_val(a) != 0xDF000000 ) { @@ -1448,9 +1521,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM ) int16 aExp; bits32 aSig; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); if ( aExp == 0xFF ) { if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR )); return packFloat64( aSign, 0x7FF, 0 ); @@ -1479,9 +1550,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM ) int16 aExp; bits32 aSig; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); if ( aExp == 0xFF ) { if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) ); return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); @@ -1512,9 +1581,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM ) int16 aExp; bits32 aSig; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); if ( aExp == 0xFF ) { if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) ); return packFloat128( aSign, 0x7FFF, 0, 0 ); @@ -1602,11 +1669,10 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM) int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; int16 expDiff; + flag dummySign; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); + unpackFloat32( a, &aSig, &aExp, &dummySign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &dummySign STATUS_VAR); expDiff = aExp - bExp; aSig <<= 6; bSig <<= 6; @@ -1644,7 +1710,7 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM) return a; } if ( aExp == 0 ) { - if ( STATUS(flush_to_zero) ) return packFloat32( zSign, 0, 0 ); + if ( STATUS(flush_outputs_to_zero) ) return packFloat32( zSign, 0, 0 ); return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); } zSig = 0x40000000 + aSig + bSig; @@ -1676,11 +1742,10 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM) int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; int16 expDiff; + flag dummySign; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); + unpackFloat32( a, &aSig, &aExp, &dummySign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &dummySign STATUS_VAR); expDiff = aExp - bExp; aSig <<= 7; bSig <<= 7; @@ -1794,12 +1859,8 @@ float32 float32_mul( float32 a, float32 b STATUS_PARAM ) bits64 zSig64; bits32 zSig; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &bSign STATUS_VAR); zSign = aSign ^ bSign; if ( aExp == 0xFF ) { if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { @@ -1852,12 +1913,8 @@ float32 float32_div( float32 a, float32 b STATUS_PARAM ) int16 aExp, bExp, zExp; bits32 aSig, bSig, zSig; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &bSign STATUS_VAR); zSign = aSign ^ bSign; if ( aExp == 0xFF ) { if ( aSig ) return propagateFloat32NaN( a, b STATUS_VAR ); @@ -1918,11 +1975,8 @@ float32 float32_rem( float32 a, float32 b STATUS_PARAM ) bits32 alternateASig; sbits32 sigMean; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &zSign STATUS_VAR); if ( aExp == 0xFF ) { if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { return propagateFloat32NaN( a, b STATUS_VAR ); @@ -2014,9 +2068,7 @@ float32 float32_sqrt( float32 a STATUS_PARAM ) bits32 aSig, zSig; bits64 rem, term; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); if ( aExp == 0xFF ) { if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR ); if ( ! aSign ) return a; @@ -2066,9 +2118,7 @@ float32 float32_log2( float32 a STATUS_PARAM ) int16 aExp; bits32 aSig, zSig, i; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); if ( aExp == 0 ) { if ( aSig == 0 ) return packFloat32( 1, 0xFF, 0 ); @@ -2110,9 +2160,14 @@ float32 float32_log2( float32 a STATUS_PARAM ) int float32_eq( float32 a, float32 b STATUS_PARAM ) { + flag aSign, bSign; + int16 aExp, bExp; + bits32 aSig, bSig; - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &bSign STATUS_VAR); + if ( ( ( aExp == 0xFF ) && aSig ) + || ( ( bExp == 0xFF ) && bSig ) ) { if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { float_raise( float_flag_invalid STATUS_VAR); @@ -2134,16 +2189,18 @@ int float32_eq( float32 a, float32 b STATUS_PARAM ) int float32_le( float32 a, float32 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits32 aSig, bSig; bits32 av, bv; - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &bSign STATUS_VAR); + if ( ( ( aExp == 0xFF ) && aSig ) + || ( ( bExp == 0xFF ) && bSig ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); av = float32_val(a); bv = float32_val(b); if ( aSign != bSign ) return aSign || ( (bits32) ( ( av | bv )<<1 ) == 0 ); @@ -2160,16 +2217,18 @@ int float32_le( float32 a, float32 b STATUS_PARAM ) int float32_lt( float32 a, float32 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits32 aSig, bSig; bits32 av, bv; - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &bSign STATUS_VAR); + if ( ( ( aExp == 0xFF ) && aSig ) + || ( ( bExp == 0xFF ) && bSig ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); av = float32_val(a); bv = float32_val(b); if ( aSign != bSign ) return aSign && ( (bits32) ( ( av | bv )<<1 ) != 0 ); @@ -2186,10 +2245,15 @@ int float32_lt( float32 a, float32 b STATUS_PARAM ) int float32_eq_signaling( float32 a, float32 b STATUS_PARAM ) { + flag aSign, bSign; + int16 aExp, bExp; + bits32 aSig, bSig; bits32 av, bv; - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &bSign STATUS_VAR); + if ( ( ( aExp == 0xFF ) && aSig ) + || ( ( bExp == 0xFF ) && bSig ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; @@ -2210,18 +2274,20 @@ int float32_eq_signaling( float32 a, float32 b STATUS_PARAM ) int float32_le_quiet( float32 a, float32 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits32 aSig, bSig; bits32 av, bv; - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &bSign STATUS_VAR); + if ( ( ( aExp == 0xFF ) && aSig ) + || ( ( bExp == 0xFF ) && bSig ) ) { if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { float_raise( float_flag_invalid STATUS_VAR); } return 0; } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); av = float32_val(a); bv = float32_val(b); if ( aSign != bSign ) return aSign || ( (bits32) ( ( av | bv )<<1 ) == 0 ); @@ -2239,18 +2305,20 @@ int float32_le_quiet( float32 a, float32 b STATUS_PARAM ) int float32_lt_quiet( float32 a, float32 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits32 aSig, bSig; bits32 av, bv; - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); + unpackFloat32( b, &bSig, &bExp, &bSign STATUS_VAR); + if ( ( ( aExp == 0xFF ) && aSig ) + || ( ( bExp == 0xFF ) && bSig ) ) { if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { float_raise( float_flag_invalid STATUS_VAR); } return 0; } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); av = float32_val(a); bv = float32_val(b); if ( aSign != bSign ) return aSign && ( (bits32) ( ( av | bv )<<1 ) != 0 ); @@ -2274,9 +2342,7 @@ int32 float64_to_int32( float64 a STATUS_PARAM ) int16 aExp, shiftCount; bits64 aSig; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); shiftCount = 0x42C - aExp; @@ -2302,9 +2368,7 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM ) bits64 aSig, savedASig; int32 z; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( 0x41E < aExp ) { if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; goto invalid; @@ -2347,9 +2411,7 @@ int64 float64_to_int64( float64 a STATUS_PARAM ) int16 aExp, shiftCount; bits64 aSig, aSigExtra; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); shiftCount = 0x433 - aExp; if ( shiftCount <= 0 ) { @@ -2390,9 +2452,7 @@ int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM ) bits64 aSig; int64 z; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); shiftCount = aExp - 0x433; if ( 0 <= shiftCount ) { @@ -2439,9 +2499,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM ) bits64 aSig; bits32 zSig; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FF ) { if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) ); return packFloat32( aSign, 0xFF, 0 ); @@ -2516,9 +2574,7 @@ bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM) bits32 increment; int8 roundingMode; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); if ( aExp == 0xFF ) { if (aSig) { /* Make sure correct exceptions are raised. */ @@ -2609,9 +2665,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM ) int16 aExp; bits64 aSig; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FF ) { if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) ); return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); @@ -2643,9 +2697,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM ) int16 aExp; bits64 aSig, zSig0, zSig1; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FF ) { if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) ); return packFloat128( aSign, 0x7FFF, 0, 0 ); @@ -2747,11 +2799,10 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM ) int16 aExp, bExp, zExp; bits64 aSig, bSig, zSig; int16 expDiff; + flag dummySign; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); + unpackFloat64( a, &aSig, &aExp, &dummySign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &dummySign STATUS_VAR ); expDiff = aExp - bExp; aSig <<= 9; bSig <<= 9; @@ -2789,7 +2840,7 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM ) return a; } if ( aExp == 0 ) { - if ( STATUS(flush_to_zero) ) return packFloat64( zSign, 0, 0 ); + if ( STATUS(flush_outputs_to_zero) ) return packFloat64( zSign, 0, 0 ); return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); } zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; @@ -2821,11 +2872,10 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM ) int16 aExp, bExp, zExp; bits64 aSig, bSig, zSig; int16 expDiff; + flag dummySign; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); + unpackFloat64( a, &aSig, &aExp, &dummySign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &dummySign STATUS_VAR ); expDiff = aExp - bExp; aSig <<= 10; bSig <<= 10; @@ -2937,12 +2987,8 @@ float64 float64_mul( float64 a, float64 b STATUS_PARAM ) int16 aExp, bExp, zExp; bits64 aSig, bSig, zSig0, zSig1; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &bSign STATUS_VAR ); zSign = aSign ^ bSign; if ( aExp == 0x7FF ) { if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { @@ -2997,12 +3043,8 @@ float64 float64_div( float64 a, float64 b STATUS_PARAM ) bits64 rem0, rem1; bits64 term0, term1; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &bSign STATUS_VAR ); zSign = aSign ^ bSign; if ( aExp == 0x7FF ) { if ( aSig ) return propagateFloat64NaN( a, b STATUS_VAR ); @@ -3067,11 +3109,8 @@ float64 float64_rem( float64 a, float64 b STATUS_PARAM ) bits64 q, alternateASig; sbits64 sigMean; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &zSign STATUS_VAR ); if ( aExp == 0x7FF ) { if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { return propagateFloat64NaN( a, b STATUS_VAR ); @@ -3150,9 +3189,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM ) bits64 aSig, zSig, doubleZSig; bits64 rem0, rem1, term0, term1; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FF ) { if ( aSig ) return propagateFloat64NaN( a, a STATUS_VAR ); if ( ! aSign ) return a; @@ -3199,9 +3236,7 @@ float64 float64_log2( float64 a STATUS_PARAM ) int16 aExp; bits64 aSig, aSig0, aSig1, zSig, i; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp == 0 ) { if ( aSig == 0 ) return packFloat64( 1, 0x7FF, 0 ); @@ -3242,10 +3277,15 @@ float64 float64_log2( float64 a STATUS_PARAM ) int float64_eq( float64 a, float64 b STATUS_PARAM ) { + flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; bits64 av, bv; - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FF ) && aSig ) + || ( ( bExp == 0x7FF ) && bSig ) ) { if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { float_raise( float_flag_invalid STATUS_VAR); @@ -3268,16 +3308,18 @@ int float64_eq( float64 a, float64 b STATUS_PARAM ) int float64_le( float64 a, float64 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; bits64 av, bv; - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FF ) && aSig ) + || ( ( bExp == 0x7FF ) && bSig ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); av = float64_val(a); bv = float64_val(b); if ( aSign != bSign ) return aSign || ( (bits64) ( ( av | bv )<<1 ) == 0 ); @@ -3294,16 +3336,18 @@ int float64_le( float64 a, float64 b STATUS_PARAM ) int float64_lt( float64 a, float64 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; bits64 av, bv; - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FF ) && aSig ) + || ( ( bExp == 0x7FF ) && bSig ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); av = float64_val(a); bv = float64_val(b); if ( aSign != bSign ) return aSign && ( (bits64) ( ( av | bv )<<1 ) != 0 ); @@ -3320,10 +3364,15 @@ int float64_lt( float64 a, float64 b STATUS_PARAM ) int float64_eq_signaling( float64 a, float64 b STATUS_PARAM ) { + flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; bits64 av, bv; - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FF ) && aSig ) + || ( ( bExp == 0x7FF ) && bSig ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; @@ -3344,18 +3393,20 @@ int float64_eq_signaling( float64 a, float64 b STATUS_PARAM ) int float64_le_quiet( float64 a, float64 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; bits64 av, bv; - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FF ) && aSig ) + || ( ( bExp == 0x7FF ) && bSig ) ) { if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { float_raise( float_flag_invalid STATUS_VAR); } return 0; } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); av = float64_val(a); bv = float64_val(b); if ( aSign != bSign ) return aSign || ( (bits64) ( ( av | bv )<<1 ) == 0 ); @@ -3373,18 +3424,20 @@ int float64_le_quiet( float64 a, float64 b STATUS_PARAM ) int float64_lt_quiet( float64 a, float64 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; bits64 av, bv; - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloat64( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FF ) && aSig ) + || ( ( bExp == 0x7FF ) && bSig ) ) { if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { float_raise( float_flag_invalid STATUS_VAR); } return 0; } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); av = float64_val(a); bv = float64_val(b); if ( aSign != bSign ) return aSign && ( (bits64) ( ( av | bv )<<1 ) != 0 ); @@ -3410,9 +3463,7 @@ int32 floatx80_to_int32( floatx80 a STATUS_PARAM ) int32 aExp, shiftCount; bits64 aSig; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; shiftCount = 0x4037 - aExp; if ( shiftCount <= 0 ) shiftCount = 1; @@ -3438,9 +3489,7 @@ int32 floatx80_to_int32_round_to_zero( floatx80 a STATUS_PARAM ) bits64 aSig, savedASig; int32 z; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( 0x401E < aExp ) { if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; goto invalid; @@ -3482,9 +3531,7 @@ int64 floatx80_to_int64( floatx80 a STATUS_PARAM ) int32 aExp, shiftCount; bits64 aSig, aSigExtra; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); shiftCount = 0x403E - aExp; if ( shiftCount <= 0 ) { if ( shiftCount ) { @@ -3523,9 +3570,7 @@ int64 floatx80_to_int64_round_to_zero( floatx80 a STATUS_PARAM ) bits64 aSig; int64 z; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); shiftCount = aExp - 0x403E; if ( 0 <= shiftCount ) { aSig &= LIT64( 0x7FFFFFFFFFFFFFFF ); @@ -3563,9 +3608,7 @@ float32 floatx80_to_float32( floatx80 a STATUS_PARAM ) int32 aExp; bits64 aSig; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FFF ) { if ( (bits64) ( aSig<<1 ) ) { return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) ); @@ -3591,9 +3634,7 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM ) int32 aExp; bits64 aSig, zSig; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FFF ) { if ( (bits64) ( aSig<<1 ) ) { return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) ); @@ -3621,9 +3662,7 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM ) int16 aExp; bits64 aSig, zSig0, zSig1; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) ); } @@ -3720,11 +3759,10 @@ static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM int32 aExp, bExp, zExp; bits64 aSig, bSig, zSig0, zSig1; int32 expDiff; + flag dummySign; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); + unpackFloatx80( a, &aSig, &aExp, &dummySign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &dummySign STATUS_VAR ); expDiff = aExp - bExp; if ( 0 < expDiff ) { if ( aExp == 0x7FFF ) { @@ -3787,11 +3825,10 @@ static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign STATUS_PARAM bits64 aSig, bSig, zSig0, zSig1; int32 expDiff; floatx80 z; + flag dummySign; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); + unpackFloatx80( a, &aSig, &aExp, &dummySign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &dummySign STATUS_VAR ); expDiff = aExp - bExp; if ( 0 < expDiff ) goto aExpBigger; if ( expDiff < 0 ) goto bExpBigger; @@ -3896,12 +3933,8 @@ floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM ) bits64 aSig, bSig, zSig0, zSig1; floatx80 z; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &bSign STATUS_VAR ); zSign = aSign ^ bSign; if ( aExp == 0x7FFF ) { if ( (bits64) ( aSig<<1 ) @@ -3956,12 +3989,8 @@ floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM ) bits64 rem0, rem1, rem2, term0, term1, term2; floatx80 z; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &bSign STATUS_VAR ); zSign = aSign ^ bSign; if ( aExp == 0x7FFF ) { if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b STATUS_VAR ); @@ -4036,11 +4065,8 @@ floatx80 floatx80_rem( floatx80 a, floatx80 b STATUS_PARAM ) bits64 q, term0, term1, alternateASig0, alternateASig1; floatx80 z; - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); + unpackFloatx80( a, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &zSign STATUS_VAR ); if ( aExp == 0x7FFF ) { if ( (bits64) ( aSig0<<1 ) || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { @@ -4132,9 +4158,7 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM ) bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; floatx80 z; - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); + unpackFloatx80( a, &aSig0, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FFF ) { if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a STATUS_VAR ); if ( ! aSign ) return a; @@ -4197,11 +4221,16 @@ floatx80 floatx80_sqrt( floatx80 a STATUS_PARAM ) int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM ) { + flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && (bits64) ( aSig<<1 ) ) + || ( ( bExp == 0x7FFF ) + && (bits64) ( bSig<<1 ) ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { @@ -4228,17 +4257,19 @@ int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM ) int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && (bits64) ( aSig<<1 ) ) + || ( ( bExp == 0x7FFF ) + && (bits64) ( bSig<<1 ) ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); if ( aSign != bSign ) { return aSign @@ -4261,17 +4292,19 @@ int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM ) int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && (bits64) ( aSig<<1 ) ) + || ( ( bExp == 0x7FFF ) + && (bits64) ( bSig<<1 ) ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); if ( aSign != bSign ) { return aSign @@ -4293,11 +4326,16 @@ int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM ) int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM ) { + flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && (bits64) ( aSig<<1 ) ) + || ( ( bExp == 0x7FFF ) + && (bits64) ( bSig<<1 ) ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; @@ -4321,11 +4359,15 @@ int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM ) int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && (bits64) ( aSig<<1 ) ) + || ( ( bExp == 0x7FFF ) + && (bits64) ( bSig<<1 ) ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { @@ -4333,8 +4375,6 @@ int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM ) } return 0; } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); if ( aSign != bSign ) { return aSign @@ -4357,11 +4397,15 @@ int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM ) int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM ) { flag aSign, bSign; + int16 aExp, bExp; + bits64 aSig, bSig; - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); + unpackFloatx80( b, &bSig, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && (bits64) ( aSig<<1 ) ) + || ( ( bExp == 0x7FFF ) + && (bits64) ( bSig<<1 ) ) ) { if ( floatx80_is_signaling_nan( a ) || floatx80_is_signaling_nan( b ) ) { @@ -4369,8 +4413,6 @@ int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM ) } return 0; } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); if ( aSign != bSign ) { return aSign @@ -4403,10 +4445,7 @@ int32 float128_to_int32( float128 a STATUS_PARAM ) int32 aExp, shiftCount; bits64 aSig0, aSig1; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); aSig0 |= ( aSig1 != 0 ); @@ -4433,10 +4472,7 @@ int32 float128_to_int32_round_to_zero( float128 a STATUS_PARAM ) bits64 aSig0, aSig1, savedASig; int32 z; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); aSig0 |= ( aSig1 != 0 ); if ( 0x401E < aExp ) { if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; @@ -4480,10 +4516,7 @@ int64 float128_to_int64( float128 a STATUS_PARAM ) int32 aExp, shiftCount; bits64 aSig0, aSig1; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); shiftCount = 0x402F - aExp; if ( shiftCount <= 0 ) { @@ -4524,10 +4557,7 @@ int64 float128_to_int64_round_to_zero( float128 a STATUS_PARAM ) bits64 aSig0, aSig1; int64 z; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); shiftCount = aExp - 0x402F; if ( 0 < shiftCount ) { @@ -4582,10 +4612,7 @@ float32 float128_to_float32( float128 a STATUS_PARAM ) bits64 aSig0, aSig1; bits32 zSig; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) { return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) ); @@ -4616,10 +4643,7 @@ float64 float128_to_float64( float128 a STATUS_PARAM ) int32 aExp; bits64 aSig0, aSig1; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) { return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) ); @@ -4651,10 +4675,7 @@ floatx80 float128_to_floatx80( float128 a STATUS_PARAM ) int32 aExp; bits64 aSig0, aSig1; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) { return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) ); @@ -4791,13 +4812,10 @@ static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM int32 aExp, bExp, zExp; bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; int32 expDiff; + flag dummySign; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &dummySign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &dummySign STATUS_VAR ); expDiff = aExp - bExp; if ( 0 < expDiff ) { if ( aExp == 0x7FFF ) { @@ -4838,7 +4856,7 @@ static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM } add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); if ( aExp == 0 ) { - if ( STATUS(flush_to_zero) ) return packFloat128( zSign, 0, 0, 0 ); + if ( STATUS(flush_outputs_to_zero) ) return packFloat128( zSign, 0, 0, 0 ); return packFloat128( zSign, 0, zSig0, zSig1 ); } zSig2 = 0; @@ -4873,13 +4891,10 @@ static float128 subFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; int32 expDiff; float128 z; + flag dummySign; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &dummySign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &dummySign STATUS_VAR ); expDiff = aExp - bExp; shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); @@ -4998,14 +5013,8 @@ float128 float128_mul( float128 a, float128 b STATUS_PARAM ) bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; float128 z; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &bSign STATUS_VAR ); zSign = aSign ^ bSign; if ( aExp == 0x7FFF ) { if ( ( aSig0 | aSig1 ) @@ -5063,14 +5072,8 @@ float128 float128_div( float128 a, float128 b STATUS_PARAM ) bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; float128 z; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &bSign STATUS_VAR ); zSign = aSign ^ bSign; if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b STATUS_VAR ); @@ -5148,13 +5151,8 @@ float128 float128_rem( float128 a, float128 b STATUS_PARAM ) sbits64 sigMean0; float128 z; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &zSign STATUS_VAR ); if ( aExp == 0x7FFF ) { if ( ( aSig0 | aSig1 ) || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { @@ -5256,10 +5254,7 @@ float128 float128_sqrt( float128 a STATUS_PARAM ) bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; float128 z; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FFF ) { if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a STATUS_VAR ); if ( ! aSign ) return a; @@ -5319,11 +5314,16 @@ float128 float128_sqrt( float128 a STATUS_PARAM ) int float128_eq( float128 a, float128 b STATUS_PARAM ) { - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + flag aSign, bSign; + int32 aExp, bExp; + bits64 aSig0, aSig1, bSig0, bSig1; + + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && ( aSig0 | aSig1 ) ) + || ( ( bExp == 0x7FFF ) + && ( bSig0 | bSig1 ) ) ) { if ( float128_is_signaling_nan( a ) || float128_is_signaling_nan( b ) ) { @@ -5350,17 +5350,19 @@ int float128_eq( float128 a, float128 b STATUS_PARAM ) int float128_le( float128 a, float128 b STATUS_PARAM ) { flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + int32 aExp, bExp; + bits64 aSig0, aSig1, bSig0, bSig1; + + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && ( aSig0 | aSig1 ) ) + || ( ( bExp == 0x7FFF ) + && ( bSig0 | bSig1 ) ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); if ( aSign != bSign ) { return aSign @@ -5382,17 +5384,19 @@ int float128_le( float128 a, float128 b STATUS_PARAM ) int float128_lt( float128 a, float128 b STATUS_PARAM ) { flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + int32 aExp, bExp; + bits64 aSig0, aSig1, bSig0, bSig1; + + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && ( aSig0 | aSig1 ) ) + || ( ( bExp == 0x7FFF ) + && ( bSig0 | bSig1 ) ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); if ( aSign != bSign ) { return aSign @@ -5414,11 +5418,16 @@ int float128_lt( float128 a, float128 b STATUS_PARAM ) int float128_eq_signaling( float128 a, float128 b STATUS_PARAM ) { - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + flag aSign, bSign; + int32 aExp, bExp; + bits64 aSig0, aSig1, bSig0, bSig1; + + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && ( aSig0 | aSig1 ) ) + || ( ( bExp == 0x7FFF ) + && ( bSig0 | bSig1 ) ) ) { float_raise( float_flag_invalid STATUS_VAR); return 0; @@ -5442,11 +5451,15 @@ int float128_eq_signaling( float128 a, float128 b STATUS_PARAM ) int float128_le_quiet( float128 a, float128 b STATUS_PARAM ) { flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + int32 aExp, bExp; + bits64 aSig0, aSig1, bSig0, bSig1; + + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && ( aSig0 | aSig1 ) ) + || ( ( bExp == 0x7FFF ) + && ( bSig0 | bSig1 ) ) ) { if ( float128_is_signaling_nan( a ) || float128_is_signaling_nan( b ) ) { @@ -5454,8 +5467,6 @@ int float128_le_quiet( float128 a, float128 b STATUS_PARAM ) } return 0; } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); if ( aSign != bSign ) { return aSign @@ -5478,11 +5489,15 @@ int float128_le_quiet( float128 a, float128 b STATUS_PARAM ) int float128_lt_quiet( float128 a, float128 b STATUS_PARAM ) { flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) + int32 aExp, bExp; + bits64 aSig0, aSig1, bSig0, bSig1; + + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && ( aSig0 | aSig1 ) ) + || ( ( bExp == 0x7FFF ) + && ( bSig0 | bSig1 ) ) ) { if ( float128_is_signaling_nan( a ) || float128_is_signaling_nan( b ) ) { @@ -5490,8 +5505,6 @@ int float128_lt_quiet( float128 a, float128 b STATUS_PARAM ) } return 0; } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); if ( aSign != bSign ) { return aSign @@ -5617,12 +5630,14 @@ INLINE int float ## s ## _compare_internal( float ## s a, float ## s b, \ int is_quiet STATUS_PARAM ) \ { \ flag aSign, bSign; \ + int16 aExp, bExp; \ + bits ## s aSig, bSig; \ bits ## s av, bv; \ \ - if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \ - extractFloat ## s ## Frac( a ) ) || \ - ( ( extractFloat ## s ## Exp( b ) == nan_exp ) && \ - extractFloat ## s ## Frac( b ) )) { \ + unpackFloat ## s ( a, &aSig, &aExp, &aSign ); \ + unpackFloat ## s ( b, &bSig, &bExp, &bSign ); \ + if (( ( aExp == nan_exp ) && aSig ) || \ + ( ( bExp == nan_exp ) && bSig )) { \ if (!is_quiet || \ float ## s ## _is_signaling_nan( a ) || \ float ## s ## _is_signaling_nan( b ) ) { \ @@ -5630,8 +5645,6 @@ INLINE int float ## s ## _compare_internal( float ## s a, float ## s b, \ } \ return float_relation_unordered; \ } \ - aSign = extractFloat ## s ## Sign( a ); \ - bSign = extractFloat ## s ## Sign( b ); \ av = float ## s ## _val(a); \ bv = float ## s ## _val(b); \ if ( aSign != bSign ) { \ @@ -5667,11 +5680,16 @@ INLINE int float128_compare_internal( float128 a, float128 b, int is_quiet STATUS_PARAM ) { flag aSign, bSign; - - if (( ( extractFloat128Exp( a ) == 0x7fff ) && - ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) || - ( ( extractFloat128Exp( b ) == 0x7fff ) && - ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )) { + int32 aExp, bExp; + bits64 aSig0, aSig1, bSig0, bSig1; + + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); + unpackFloat128( b, &bSig1, &bSig0, &bExp, &bSign STATUS_VAR ); + if ( ( ( aExp == 0x7FFF ) + && ( aSig0 | aSig1 ) ) + || ( ( bExp == 0x7FFF ) + && ( bSig0 | bSig1 ) ) + ) { if (!is_quiet || float128_is_signaling_nan( a ) || float128_is_signaling_nan( b ) ) { @@ -5679,8 +5697,6 @@ INLINE int float128_compare_internal( float128 a, float128 b, } return float_relation_unordered; } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); if ( aSign != bSign ) { if ( ( ( ( a.high | b.high )<<1 ) | a.low | b.low ) == 0 ) { /* zero case */ @@ -5714,9 +5730,7 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM ) int16 aExp; bits32 aSig; - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); + unpackFloat32( a, &aSig, &aExp, &aSign STATUS_VAR); if ( aExp == 0xFF ) { return a; @@ -5737,9 +5751,7 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM ) int16 aExp; bits64 aSig; - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); + unpackFloat64( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FF ) { return a; @@ -5761,9 +5773,7 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM ) int16 aExp; bits64 aSig; - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); + unpackFloatx80( a, &aSig, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FF ) { return a; @@ -5784,10 +5794,7 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM ) int32 aExp; bits64 aSig0, aSig1; - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); + unpackFloat128( a, &aSig1, &aSig0, &aExp, &aSign STATUS_VAR ); if ( aExp == 0x7FFF ) { return a; } diff --git a/fpu/softfloat.h b/fpu/softfloat.h index 636591b..eb0d53b 100644 --- a/fpu/softfloat.h +++ b/fpu/softfloat.h @@ -180,7 +180,9 @@ enum { float_flag_divbyzero = 4, float_flag_overflow = 8, float_flag_underflow = 16, - float_flag_inexact = 32 + float_flag_inexact = 32, + /* Not strictly an IEEE flag, but implemented on several architectures. */ + float_flag_input_denormal = 64 }; typedef struct float_status { @@ -190,15 +192,20 @@ typedef struct float_status { #ifdef FLOATX80 signed char floatx80_rounding_precision; #endif - flag flush_to_zero; + flag flush_inputs_to_zero; + flag flush_outputs_to_zero; flag default_nan_mode; } float_status; void set_float_rounding_mode(int val STATUS_PARAM); void set_float_exception_flags(int val STATUS_PARAM); -INLINE void set_flush_to_zero(flag val STATUS_PARAM) +INLINE void set_flush_inputs_to_zero(flag val STATUS_PARAM) { - STATUS(flush_to_zero) = val; + STATUS(flush_inputs_to_zero) = val; +} +INLINE void set_flush_outputs_to_zero(flag val STATUS_PARAM) +{ + STATUS(flush_outputs_to_zero) = val; } INLINE void set_default_nan_mode(flag val STATUS_PARAM) { diff --git a/target-arm/helper.c b/target-arm/helper.c index 18e22b1..723b368 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2209,6 +2209,8 @@ static inline int vfp_exceptbits_from_host(int host_bits) target_bits |= 8; if (host_bits & float_flag_inexact) target_bits |= 0x10; + if (host_bits & float_flag_input_denormal) + target_bits |= 0x80; return target_bits; } @@ -2240,6 +2242,8 @@ static inline int vfp_exceptbits_to_host(int target_bits) host_bits |= float_flag_underflow; if (target_bits & 0x10) host_bits |= float_flag_inexact; + if (target_bits & 0x80) + host_bits |= float_flag_input_denormal; return host_bits; } @@ -2272,8 +2276,11 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val) } set_float_rounding_mode(i, &env->vfp.fp_status); } - if (changed & (1 << 24)) - set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status); + if (changed & (1 << 24)) { + i = (val & (1 << 24)) != 0; + set_flush_inputs_to_zero(i, &env->vfp.fp_status); + set_flush_outputs_to_zero(i, &env->vfp.fp_status); + } if (changed & (1 << 25)) set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status); diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 2bfdd50..a46caf7 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1897,8 +1897,14 @@ static unsigned int ieee_rm[] = { #define RESTORE_ROUNDING_MODE \ set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status) +/* FIXME: On most MIPS Technologies chips, there are other flags that interact with + FS in interesting ways. */ #define RESTORE_FLUSH_MODE \ - set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status); + do { \ + int flag = (env->active_fpu.fcr31 & (1 << 24)) != 0; \ + set_flush_inputs_to_zero(flag, &env->active_fpu.fp_status); \ + set_flush_outputs_to_zero(flag, &env->active_fpu.fp_status); \ + } while (0); target_ulong helper_cfc1 (uint32_t reg) { diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 8f2ee98..95c22fb 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -2060,7 +2060,7 @@ void helper_mtvscr (ppc_avr_t *r) #else env->vscr = r->u32[0]; #endif - set_flush_to_zero(vscr_nj, &env->vec_status); + set_flush_outputs_to_zero(vscr_nj, &env->vec_status); } void helper_vaddcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index db4dc17..9b78ea7 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -507,7 +507,7 @@ static inline void vscr_init (CPUPPCState *env, uint32_t val) env->vscr = val; /* Altivec always uses round-to-nearest */ set_float_rounding_mode(float_round_nearest_even, &env->vec_status); - set_flush_to_zero(vscr_nj, &env->vec_status); + set_flush_outputs_to_zero(vscr_nj, &env->vec_status); } #if defined(CONFIG_USER_ONLY)