diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2011-01-14 20:39:17 +0100 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2011-01-14 20:39:17 +0100 |
commit | 102016020bb0f368958ae91d293e13c61b3923a1 (patch) | |
tree | 0c6d0006ce608f597bc169951b4658d3d710c635 | |
parent | e90877507ea8864e32692cb79da1685f5ada8c78 (diff) | |
download | hqemu-102016020bb0f368958ae91d293e13c61b3923a1.zip hqemu-102016020bb0f368958ae91d293e13c61b3923a1.tar.gz |
softfloat: fix default-NaN mode
When the default-NaN mode is enabled, it should return the default NaN
value, but it should anyway raise the invalid operation flag if one of
the operand is an sNaN.
I have checked that this behavior matches the ARM and SH4 manuals, as
well as real SH4 hardware.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r-- | fpu/softfloat-specialize.h | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 186b4da..11521ce 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -278,9 +278,6 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) flag aIsLargerSignificand; bits32 av, bv; - if ( STATUS(default_nan_mode) ) - return float32_default_nan; - aIsQuietNaN = float32_is_quiet_nan( a ); aIsSignalingNaN = float32_is_signaling_nan( a ); bIsQuietNaN = float32_is_quiet_nan( b ); @@ -290,6 +287,9 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); + if ( STATUS(default_nan_mode) ) + return float32_default_nan; + if ((bits32)(av<<1) < (bits32)(bv<<1)) { aIsLargerSignificand = 0; } else if ((bits32)(bv<<1) < (bits32)(av<<1)) { @@ -423,9 +423,6 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) flag aIsLargerSignificand; bits64 av, bv; - if ( STATUS(default_nan_mode) ) - return float64_default_nan; - aIsQuietNaN = float64_is_quiet_nan( a ); aIsSignalingNaN = float64_is_signaling_nan( a ); bIsQuietNaN = float64_is_quiet_nan( b ); @@ -435,6 +432,9 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); + if ( STATUS(default_nan_mode) ) + return float64_default_nan; + if ((bits64)(av<<1) < (bits64)(bv<<1)) { aIsLargerSignificand = 0; } else if ((bits64)(bv<<1) < (bits64)(av<<1)) { @@ -574,12 +574,6 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN; flag aIsLargerSignificand; - if ( STATUS(default_nan_mode) ) { - a.low = floatx80_default_nan_low; - a.high = floatx80_default_nan_high; - return a; - } - aIsQuietNaN = floatx80_is_quiet_nan( a ); aIsSignalingNaN = floatx80_is_signaling_nan( a ); bIsQuietNaN = floatx80_is_quiet_nan( b ); @@ -587,6 +581,12 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); + if ( STATUS(default_nan_mode) ) { + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + if (a.low < b.low) { aIsLargerSignificand = 0; } else if (b.low < a.low) { @@ -719,12 +719,6 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM) flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN; flag aIsLargerSignificand; - if ( STATUS(default_nan_mode) ) { - a.low = float128_default_nan_low; - a.high = float128_default_nan_high; - return a; - } - aIsQuietNaN = float128_is_quiet_nan( a ); aIsSignalingNaN = float128_is_signaling_nan( a ); bIsQuietNaN = float128_is_quiet_nan( b ); @@ -732,6 +726,12 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM) if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); + if ( STATUS(default_nan_mode) ) { + a.low = float128_default_nan_low; + a.high = float128_default_nan_high; + return a; + } + if (lt128(a.high<<1, a.low, b.high<<1, b.low)) { aIsLargerSignificand = 0; } else if (lt128(b.high<<1, b.low, a.high<<1, a.low)) { |