From: Nathan Froyd <froydnj@codesourcery.com>
To: Juha.Riihimaki@nokia.com
Cc: qemu-devel@nongnu.org, zhur@ispras.ru
Subject: WIP flush-to-zero patch [was: Re: [Qemu-devel] QEMU state of ARM NEON support.]
Date: Thu, 25 Mar 2010 07:00:11 -0700 [thread overview]
Message-ID: <20100325140011.GT16726@codesourcery.com> (raw)
In-Reply-To: <372ED49D-DF43-4E6C-AA3D-F4DA95746981@nokia.com>
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)
next prev parent reply other threads:[~2010-03-25 14:00 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-03-22 13:43 [Qemu-devel] QEMU state of ARM NEON support Dmitry Zhurikhin
2010-03-25 7:52 ` Juha.Riihimaki
2010-03-25 10:27 ` Dmitry Zhurikhin
2010-03-25 11:04 ` Juha.Riihimaki
2010-03-25 14:00 ` Nathan Froyd [this message]
2010-03-25 16:11 ` WIP flush-to-zero patch [was: Re: [Qemu-devel] QEMU state of ARM NEON support.] Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100325140011.GT16726@codesourcery.com \
--to=froydnj@codesourcery.com \
--cc=Juha.Riihimaki@nokia.com \
--cc=qemu-devel@nongnu.org \
--cc=zhur@ispras.ru \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.