[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 07/20] softfloat: fix float*_scalnb() corner cases
From: |
Aurelien Jarno |
Subject: |
[Qemu-devel] [PATCH 07/20] softfloat: fix float*_scalnb() corner cases |
Date: |
Mon, 18 Apr 2011 22:59:59 +0200 |
float*_scalnb() were not taking into account all cases. This patch fixes
some corner cases:
- NaN values in input were not properly propagated and the invalid flag
not correctly raised. Use propagateFloat*NaN() for that.
- NaN or infinite values in input of floatx80_scalnb() were not correctly
detected due to a typo.
- The sum of exponent and n could overflow, leading to strange results.
Additionally having int16 defined to int make that happening for a very
small range of values. Fix that by saturating n to the maximum exponent
range, and using an explicit wider type if needed.
Signed-off-by: Aurelien Jarno <address@hidden>
---
fpu/softfloat.c | 47 ++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 4368069..8f755c3 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -6333,7 +6333,7 @@ MINMAX(64, 0x7ff)
float32 float32_scalbn( float32 a, int n STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int16_t aExp;
uint32_t aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
@@ -6342,6 +6342,9 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
+ if ( aSig ) {
+ return propagateFloat32NaN( a, a STATUS_VAR );
+ }
return a;
}
if ( aExp != 0 )
@@ -6349,6 +6352,12 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
else if ( aSig == 0 )
return a;
+ if (n > 0x80) {
+ n = 0x80;
+ } else if (n < -0x80) {
+ n = -0x80;
+ }
+
aExp += n - 1;
aSig <<= 7;
return normalizeRoundAndPackFloat32( aSign, aExp, aSig STATUS_VAR );
@@ -6357,7 +6366,7 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
float64 float64_scalbn( float64 a, int n STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int16_t aExp;
uint64_t aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
@@ -6366,6 +6375,9 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
+ if ( aSig ) {
+ return propagateFloat64NaN( a, a STATUS_VAR );
+ }
return a;
}
if ( aExp != 0 )
@@ -6373,6 +6385,12 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
else if ( aSig == 0 )
return a;
+ if (n > 0x1000) {
+ n = 0x1000;
+ } else if (n < -0x1000) {
+ n = -0x1000;
+ }
+
aExp += n - 1;
aSig <<= 10;
return normalizeRoundAndPackFloat64( aSign, aExp, aSig STATUS_VAR );
@@ -6382,19 +6400,29 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
{
flag aSign;
- int16 aExp;
+ int32_t aExp;
uint64_t aSig;
aSig = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
- if ( aExp == 0x7FF ) {
+ if ( aExp == 0x7FFF ) {
+ if ( aSig<<1 ) {
+ return propagateFloatx80NaN( a, a STATUS_VAR );
+ }
return a;
}
+
if (aExp == 0 && aSig == 0)
return a;
+ if (n > 0x10000) {
+ n = 0x10000;
+ } else if (n < -0x10000) {
+ n = -0x10000;
+ }
+
aExp += n;
return normalizeRoundAndPackFloatx80( STATUS(floatx80_rounding_precision),
aSign, aExp, aSig, 0 STATUS_VAR );
@@ -6405,7 +6433,7 @@ floatx80 floatx80_scalbn( floatx80 a, int n STATUS_PARAM )
float128 float128_scalbn( float128 a, int n STATUS_PARAM )
{
flag aSign;
- int32 aExp;
+ int32_t aExp;
uint64_t aSig0, aSig1;
aSig1 = extractFloat128Frac1( a );
@@ -6413,6 +6441,9 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM )
aExp = extractFloat128Exp( a );
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) {
+ return propagateFloat128NaN( a, a STATUS_VAR );
+ }
return a;
}
if ( aExp != 0 )
@@ -6420,6 +6451,12 @@ float128 float128_scalbn( float128 a, int n STATUS_PARAM
)
else if ( aSig0 == 0 && aSig1 == 0 )
return a;
+ if (n > 0x10000) {
+ n = 0x10000;
+ } else if (n < -0x10000) {
+ n = -0x10000;
+ }
+
aExp += n - 1;
return normalizeRoundAndPackFloat128( aSign, aExp, aSig0, aSig1
STATUS_VAR );
--
1.7.2.3
- [Qemu-devel] [PATCH 05/20] softfloat-native: add a few constant values, (continued)
- [Qemu-devel] [PATCH 05/20] softfloat-native: add a few constant values, Aurelien Jarno, 2011/04/18
- [Qemu-devel] [PATCH 01/20] softfloat: fix floatx80 handling of NaN, Aurelien Jarno, 2011/04/18
- [Qemu-devel] [PATCH 16/20] target-i386: add CPU86_LDouble <-> double conversion functions, Aurelien Jarno, 2011/04/18
- [Qemu-devel] [PATCH 04/20] softfloat: add pi constants, Aurelien Jarno, 2011/04/18
- [Qemu-devel] [PATCH 07/20] softfloat: fix float*_scalnb() corner cases,
Aurelien Jarno <=
- [Qemu-devel] [PATCH 12/20] target-i386: fix helper_fxtract() wrt softfloat, Aurelien Jarno, 2011/04/18
- [Qemu-devel] [PATCH 06/20] softfloat: add floatx80_compare*() functions, Aurelien Jarno, 2011/04/18
- [Qemu-devel] [PATCH 08/20] softfloat-native: fix float*_scalbn() functions, Aurelien Jarno, 2011/04/18
- [Qemu-devel] [PATCH 17/20] target-i386: fix logarithmic and trigonometric helpers wrt softfloat, Aurelien Jarno, 2011/04/18