Commit b645bb48850fea8db017026897827f0ab42fbdea
1 parent
5a1e8ffb
Fix softfloat NaN handling.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2805 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
38 additions
and
10 deletions
fpu/softfloat-specialize.h
| @@ -61,7 +61,11 @@ typedef struct { | @@ -61,7 +61,11 @@ typedef struct { | ||
| 61 | /*---------------------------------------------------------------------------- | 61 | /*---------------------------------------------------------------------------- |
| 62 | | The pattern for a default generated single-precision NaN. | 62 | | The pattern for a default generated single-precision NaN. |
| 63 | *----------------------------------------------------------------------------*/ | 63 | *----------------------------------------------------------------------------*/ |
| 64 | +#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | ||
| 65 | +#define float32_default_nan 0xFF800000 | ||
| 66 | +#else | ||
| 64 | #define float32_default_nan 0xFFC00000 | 67 | #define float32_default_nan 0xFFC00000 |
| 68 | +#endif | ||
| 65 | 69 | ||
| 66 | /*---------------------------------------------------------------------------- | 70 | /*---------------------------------------------------------------------------- |
| 67 | | Returns 1 if the single-precision floating-point value `a' is a NaN; | 71 | | Returns 1 if the single-precision floating-point value `a' is a NaN; |
| @@ -70,9 +74,11 @@ typedef struct { | @@ -70,9 +74,11 @@ typedef struct { | ||
| 70 | 74 | ||
| 71 | int float32_is_nan( float32 a ) | 75 | int float32_is_nan( float32 a ) |
| 72 | { | 76 | { |
| 73 | - | ||
| 74 | - return ( 0xFF000000 < (bits32) ( a<<1 ) ); | ||
| 75 | - | 77 | +#if defined(TARGET_MIPS) || defined(TARGET_HPPA) |
| 78 | + return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); | ||
| 79 | +#else | ||
| 80 | + return ( 0xFF800000 <= (bits32) ( a<<1 ) ); | ||
| 81 | +#endif | ||
| 76 | } | 82 | } |
| 77 | 83 | ||
| 78 | /*---------------------------------------------------------------------------- | 84 | /*---------------------------------------------------------------------------- |
| @@ -82,9 +88,11 @@ int float32_is_nan( float32 a ) | @@ -82,9 +88,11 @@ int float32_is_nan( float32 a ) | ||
| 82 | 88 | ||
| 83 | int float32_is_signaling_nan( float32 a ) | 89 | int float32_is_signaling_nan( float32 a ) |
| 84 | { | 90 | { |
| 85 | - | 91 | +#if defined(TARGET_MIPS) || defined(TARGET_HPPA) |
| 92 | + return ( 0xFF800000 <= (bits32) ( a<<1 ) ); | ||
| 93 | +#else | ||
| 86 | return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); | 94 | return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); |
| 87 | - | 95 | +#endif |
| 88 | } | 96 | } |
| 89 | 97 | ||
| 90 | /*---------------------------------------------------------------------------- | 98 | /*---------------------------------------------------------------------------- |
| @@ -131,8 +139,13 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) | @@ -131,8 +139,13 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) | ||
| 131 | aIsSignalingNaN = float32_is_signaling_nan( a ); | 139 | aIsSignalingNaN = float32_is_signaling_nan( a ); |
| 132 | bIsNaN = float32_is_nan( b ); | 140 | bIsNaN = float32_is_nan( b ); |
| 133 | bIsSignalingNaN = float32_is_signaling_nan( b ); | 141 | bIsSignalingNaN = float32_is_signaling_nan( b ); |
| 142 | +#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | ||
| 143 | + a &= ~0x00400000; | ||
| 144 | + b &= ~0x00400000; | ||
| 145 | +#else | ||
| 134 | a |= 0x00400000; | 146 | a |= 0x00400000; |
| 135 | b |= 0x00400000; | 147 | b |= 0x00400000; |
| 148 | +#endif | ||
| 136 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); | 149 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); |
| 137 | if ( aIsSignalingNaN ) { | 150 | if ( aIsSignalingNaN ) { |
| 138 | if ( bIsSignalingNaN ) goto returnLargerSignificand; | 151 | if ( bIsSignalingNaN ) goto returnLargerSignificand; |
| @@ -154,7 +167,11 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) | @@ -154,7 +167,11 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) | ||
| 154 | /*---------------------------------------------------------------------------- | 167 | /*---------------------------------------------------------------------------- |
| 155 | | The pattern for a default generated double-precision NaN. | 168 | | The pattern for a default generated double-precision NaN. |
| 156 | *----------------------------------------------------------------------------*/ | 169 | *----------------------------------------------------------------------------*/ |
| 170 | +#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | ||
| 171 | +#define float64_default_nan LIT64( 0xFFF0000000000000 ) | ||
| 172 | +#else | ||
| 157 | #define float64_default_nan LIT64( 0xFFF8000000000000 ) | 173 | #define float64_default_nan LIT64( 0xFFF8000000000000 ) |
| 174 | +#endif | ||
| 158 | 175 | ||
| 159 | /*---------------------------------------------------------------------------- | 176 | /*---------------------------------------------------------------------------- |
| 160 | | Returns 1 if the double-precision floating-point value `a' is a NaN; | 177 | | Returns 1 if the double-precision floating-point value `a' is a NaN; |
| @@ -163,9 +180,13 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) | @@ -163,9 +180,13 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) | ||
| 163 | 180 | ||
| 164 | int float64_is_nan( float64 a ) | 181 | int float64_is_nan( float64 a ) |
| 165 | { | 182 | { |
| 166 | - | ||
| 167 | - return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); | ||
| 168 | - | 183 | +#if defined(TARGET_MIPS) || defined(TARGET_HPPA) |
| 184 | + return | ||
| 185 | + ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) | ||
| 186 | + && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); | ||
| 187 | +#else | ||
| 188 | + return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) ); | ||
| 189 | +#endif | ||
| 169 | } | 190 | } |
| 170 | 191 | ||
| 171 | /*---------------------------------------------------------------------------- | 192 | /*---------------------------------------------------------------------------- |
| @@ -175,11 +196,13 @@ int float64_is_nan( float64 a ) | @@ -175,11 +196,13 @@ int float64_is_nan( float64 a ) | ||
| 175 | 196 | ||
| 176 | int float64_is_signaling_nan( float64 a ) | 197 | int float64_is_signaling_nan( float64 a ) |
| 177 | { | 198 | { |
| 178 | - | 199 | +#if defined(TARGET_MIPS) || defined(TARGET_HPPA) |
| 200 | + return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) ); | ||
| 201 | +#else | ||
| 179 | return | 202 | return |
| 180 | ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) | 203 | ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) |
| 181 | && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); | 204 | && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); |
| 182 | - | 205 | +#endif |
| 183 | } | 206 | } |
| 184 | 207 | ||
| 185 | /*---------------------------------------------------------------------------- | 208 | /*---------------------------------------------------------------------------- |
| @@ -229,8 +252,13 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) | @@ -229,8 +252,13 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) | ||
| 229 | aIsSignalingNaN = float64_is_signaling_nan( a ); | 252 | aIsSignalingNaN = float64_is_signaling_nan( a ); |
| 230 | bIsNaN = float64_is_nan( b ); | 253 | bIsNaN = float64_is_nan( b ); |
| 231 | bIsSignalingNaN = float64_is_signaling_nan( b ); | 254 | bIsSignalingNaN = float64_is_signaling_nan( b ); |
| 255 | +#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | ||
| 256 | + a &= ~LIT64( 0x0008000000000000 ); | ||
| 257 | + b &= ~LIT64( 0x0008000000000000 ); | ||
| 258 | +#else | ||
| 232 | a |= LIT64( 0x0008000000000000 ); | 259 | a |= LIT64( 0x0008000000000000 ); |
| 233 | b |= LIT64( 0x0008000000000000 ); | 260 | b |= LIT64( 0x0008000000000000 ); |
| 261 | +#endif | ||
| 234 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); | 262 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); |
| 235 | if ( aIsSignalingNaN ) { | 263 | if ( aIsSignalingNaN ) { |
| 236 | if ( bIsSignalingNaN ) goto returnLargerSignificand; | 264 | if ( bIsSignalingNaN ) goto returnLargerSignificand; |