Commit 5a6932d51d1b34b68b3f10fc5ac65598bece88c0
1 parent
7863667f
Fix NaN handling for MIPS and HPPA.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3655 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
68 additions
and
40 deletions
fpu/softfloat-specialize.h
| ... | ... | @@ -30,6 +30,12 @@ these four paragraphs for those parts of this code that are retained. |
| 30 | 30 | |
| 31 | 31 | =============================================================================*/ |
| 32 | 32 | |
| 33 | +#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | |
| 34 | +#define SNAN_BIT_IS_ONE 1 | |
| 35 | +#else | |
| 36 | +#define SNAN_BIT_IS_ONE 0 | |
| 37 | +#endif | |
| 38 | + | |
| 33 | 39 | /*---------------------------------------------------------------------------- |
| 34 | 40 | | Underflow tininess-detection mode, statically initialized to default value. |
| 35 | 41 | | (The declaration in `softfloat.h' must match the `int8' type here.) |
| ... | ... | @@ -45,9 +51,7 @@ int8 float_detect_tininess = float_tininess_after_rounding; |
| 45 | 51 | |
| 46 | 52 | void float_raise( int8 flags STATUS_PARAM ) |
| 47 | 53 | { |
| 48 | - | |
| 49 | 54 | STATUS(float_exception_flags) |= flags; |
| 50 | - | |
| 51 | 55 | } |
| 52 | 56 | |
| 53 | 57 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -61,20 +65,20 @@ typedef struct { |
| 61 | 65 | /*---------------------------------------------------------------------------- |
| 62 | 66 | | The pattern for a default generated single-precision NaN. |
| 63 | 67 | *----------------------------------------------------------------------------*/ |
| 64 | -#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | |
| 65 | -#define float32_default_nan 0xFF800000 | |
| 68 | +#if SNAN_BIT_IS_ONE | |
| 69 | +#define float32_default_nan 0x7FBFFFFF | |
| 66 | 70 | #else |
| 67 | 71 | #define float32_default_nan 0xFFC00000 |
| 68 | 72 | #endif |
| 69 | 73 | |
| 70 | 74 | /*---------------------------------------------------------------------------- |
| 71 | -| Returns 1 if the single-precision floating-point value `a' is a NaN; | |
| 72 | -| otherwise returns 0. | |
| 75 | +| Returns 1 if the single-precision floating-point value `a' is a quiet | |
| 76 | +| NaN; otherwise returns 0. | |
| 73 | 77 | *----------------------------------------------------------------------------*/ |
| 74 | 78 | |
| 75 | 79 | int float32_is_nan( float32 a ) |
| 76 | 80 | { |
| 77 | -#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | |
| 81 | +#if SNAN_BIT_IS_ONE | |
| 78 | 82 | return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); |
| 79 | 83 | #else |
| 80 | 84 | return ( 0xFF800000 <= (bits32) ( a<<1 ) ); |
| ... | ... | @@ -88,7 +92,7 @@ int float32_is_nan( float32 a ) |
| 88 | 92 | |
| 89 | 93 | int float32_is_signaling_nan( float32 a ) |
| 90 | 94 | { |
| 91 | -#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | |
| 95 | +#if SNAN_BIT_IS_ONE | |
| 92 | 96 | return ( 0xFF800000 <= (bits32) ( a<<1 ) ); |
| 93 | 97 | #else |
| 94 | 98 | return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); |
| ... | ... | @@ -110,7 +114,6 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM ) |
| 110 | 114 | z.low = 0; |
| 111 | 115 | z.high = ( (bits64) a )<<41; |
| 112 | 116 | return z; |
| 113 | - | |
| 114 | 117 | } |
| 115 | 118 | |
| 116 | 119 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -120,9 +123,7 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM ) |
| 120 | 123 | |
| 121 | 124 | static float32 commonNaNToFloat32( commonNaNT a ) |
| 122 | 125 | { |
| 123 | - | |
| 124 | 126 | return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); |
| 125 | - | |
| 126 | 127 | } |
| 127 | 128 | |
| 128 | 129 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -139,7 +140,7 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) |
| 139 | 140 | aIsSignalingNaN = float32_is_signaling_nan( a ); |
| 140 | 141 | bIsNaN = float32_is_nan( b ); |
| 141 | 142 | bIsSignalingNaN = float32_is_signaling_nan( b ); |
| 142 | -#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | |
| 143 | +#if SNAN_BIT_IS_ONE | |
| 143 | 144 | a &= ~0x00400000; |
| 144 | 145 | b &= ~0x00400000; |
| 145 | 146 | #else |
| ... | ... | @@ -161,26 +162,25 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) |
| 161 | 162 | else { |
| 162 | 163 | return b; |
| 163 | 164 | } |
| 164 | - | |
| 165 | 165 | } |
| 166 | 166 | |
| 167 | 167 | /*---------------------------------------------------------------------------- |
| 168 | 168 | | The pattern for a default generated double-precision NaN. |
| 169 | 169 | *----------------------------------------------------------------------------*/ |
| 170 | -#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | |
| 171 | -#define float64_default_nan LIT64( 0xFFF0000000000000 ) | |
| 170 | +#if SNAN_BIT_IS_ONE | |
| 171 | +#define float64_default_nan LIT64( 0x7FF7FFFFFFFFFFFF ) | |
| 172 | 172 | #else |
| 173 | 173 | #define float64_default_nan LIT64( 0xFFF8000000000000 ) |
| 174 | 174 | #endif |
| 175 | 175 | |
| 176 | 176 | /*---------------------------------------------------------------------------- |
| 177 | -| Returns 1 if the double-precision floating-point value `a' is a NaN; | |
| 178 | -| otherwise returns 0. | |
| 177 | +| Returns 1 if the double-precision floating-point value `a' is a quiet | |
| 178 | +| NaN; otherwise returns 0. | |
| 179 | 179 | *----------------------------------------------------------------------------*/ |
| 180 | 180 | |
| 181 | 181 | int float64_is_nan( float64 a ) |
| 182 | 182 | { |
| 183 | -#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | |
| 183 | +#if SNAN_BIT_IS_ONE | |
| 184 | 184 | return |
| 185 | 185 | ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) |
| 186 | 186 | && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); |
| ... | ... | @@ -196,7 +196,7 @@ int float64_is_nan( float64 a ) |
| 196 | 196 | |
| 197 | 197 | int float64_is_signaling_nan( float64 a ) |
| 198 | 198 | { |
| 199 | -#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | |
| 199 | +#if SNAN_BIT_IS_ONE | |
| 200 | 200 | return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) ); |
| 201 | 201 | #else |
| 202 | 202 | return |
| ... | ... | @@ -220,7 +220,6 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM) |
| 220 | 220 | z.low = 0; |
| 221 | 221 | z.high = a<<12; |
| 222 | 222 | return z; |
| 223 | - | |
| 224 | 223 | } |
| 225 | 224 | |
| 226 | 225 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -230,12 +229,10 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM) |
| 230 | 229 | |
| 231 | 230 | static float64 commonNaNToFloat64( commonNaNT a ) |
| 232 | 231 | { |
| 233 | - | |
| 234 | 232 | return |
| 235 | 233 | ( ( (bits64) a.sign )<<63 ) |
| 236 | 234 | | LIT64( 0x7FF8000000000000 ) |
| 237 | 235 | | ( a.high>>12 ); |
| 238 | - | |
| 239 | 236 | } |
| 240 | 237 | |
| 241 | 238 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -252,7 +249,7 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) |
| 252 | 249 | aIsSignalingNaN = float64_is_signaling_nan( a ); |
| 253 | 250 | bIsNaN = float64_is_nan( b ); |
| 254 | 251 | bIsSignalingNaN = float64_is_signaling_nan( b ); |
| 255 | -#if defined(TARGET_MIPS) || defined(TARGET_HPPA) | |
| 252 | +#if SNAN_BIT_IS_ONE | |
| 256 | 253 | a &= ~LIT64( 0x0008000000000000 ); |
| 257 | 254 | b &= ~LIT64( 0x0008000000000000 ); |
| 258 | 255 | #else |
| ... | ... | @@ -274,7 +271,6 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) |
| 274 | 271 | else { |
| 275 | 272 | return b; |
| 276 | 273 | } |
| 277 | - | |
| 278 | 274 | } |
| 279 | 275 | |
| 280 | 276 | #ifdef FLOATX80 |
| ... | ... | @@ -284,19 +280,32 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) |
| 284 | 280 | | `high' and `low' values hold the most- and least-significant bits, |
| 285 | 281 | | respectively. |
| 286 | 282 | *----------------------------------------------------------------------------*/ |
| 283 | +#if SNAN_BIT_IS_ONE | |
| 284 | +#define floatx80_default_nan_high 0x7FFF | |
| 285 | +#define floatx80_default_nan_low LIT64( 0xBFFFFFFFFFFFFFFF ) | |
| 286 | +#else | |
| 287 | 287 | #define floatx80_default_nan_high 0xFFFF |
| 288 | 288 | #define floatx80_default_nan_low LIT64( 0xC000000000000000 ) |
| 289 | +#endif | |
| 289 | 290 | |
| 290 | 291 | /*---------------------------------------------------------------------------- |
| 291 | 292 | | Returns 1 if the extended double-precision floating-point value `a' is a |
| 292 | -| NaN; otherwise returns 0. | |
| 293 | +| quiet NaN; otherwise returns 0. | |
| 293 | 294 | *----------------------------------------------------------------------------*/ |
| 294 | 295 | |
| 295 | 296 | int floatx80_is_nan( floatx80 a ) |
| 296 | 297 | { |
| 298 | +#if SNAN_BIT_IS_ONE | |
| 299 | + bits64 aLow; | |
| 297 | 300 | |
| 301 | + aLow = a.low & ~ LIT64( 0x4000000000000000 ); | |
| 302 | + return | |
| 303 | + ( ( a.high & 0x7FFF ) == 0x7FFF ) | |
| 304 | + && (bits64) ( aLow<<1 ) | |
| 305 | + && ( a.low == aLow ); | |
| 306 | +#else | |
| 298 | 307 | return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); |
| 299 | - | |
| 308 | +#endif | |
| 300 | 309 | } |
| 301 | 310 | |
| 302 | 311 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -306,6 +315,9 @@ int floatx80_is_nan( floatx80 a ) |
| 306 | 315 | |
| 307 | 316 | int floatx80_is_signaling_nan( floatx80 a ) |
| 308 | 317 | { |
| 318 | +#if SNAN_BIT_IS_ONE | |
| 319 | + return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); | |
| 320 | +#else | |
| 309 | 321 | bits64 aLow; |
| 310 | 322 | |
| 311 | 323 | aLow = a.low & ~ LIT64( 0x4000000000000000 ); |
| ... | ... | @@ -313,7 +325,7 @@ int floatx80_is_signaling_nan( floatx80 a ) |
| 313 | 325 | ( ( a.high & 0x7FFF ) == 0x7FFF ) |
| 314 | 326 | && (bits64) ( aLow<<1 ) |
| 315 | 327 | && ( a.low == aLow ); |
| 316 | - | |
| 328 | +#endif | |
| 317 | 329 | } |
| 318 | 330 | |
| 319 | 331 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -331,7 +343,6 @@ static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM) |
| 331 | 343 | z.low = 0; |
| 332 | 344 | z.high = a.low<<1; |
| 333 | 345 | return z; |
| 334 | - | |
| 335 | 346 | } |
| 336 | 347 | |
| 337 | 348 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -346,7 +357,6 @@ static floatx80 commonNaNToFloatx80( commonNaNT a ) |
| 346 | 357 | z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); |
| 347 | 358 | z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; |
| 348 | 359 | return z; |
| 349 | - | |
| 350 | 360 | } |
| 351 | 361 | |
| 352 | 362 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -363,8 +373,13 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) |
| 363 | 373 | aIsSignalingNaN = floatx80_is_signaling_nan( a ); |
| 364 | 374 | bIsNaN = floatx80_is_nan( b ); |
| 365 | 375 | bIsSignalingNaN = floatx80_is_signaling_nan( b ); |
| 376 | +#if SNAN_BIT_IS_ONE | |
| 377 | + a.low &= ~LIT64( 0xC000000000000000 ); | |
| 378 | + b.low &= ~LIT64( 0xC000000000000000 ); | |
| 379 | +#else | |
| 366 | 380 | a.low |= LIT64( 0xC000000000000000 ); |
| 367 | 381 | b.low |= LIT64( 0xC000000000000000 ); |
| 382 | +#endif | |
| 368 | 383 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); |
| 369 | 384 | if ( aIsSignalingNaN ) { |
| 370 | 385 | if ( bIsSignalingNaN ) goto returnLargerSignificand; |
| ... | ... | @@ -380,7 +395,6 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) |
| 380 | 395 | else { |
| 381 | 396 | return b; |
| 382 | 397 | } |
| 383 | - | |
| 384 | 398 | } |
| 385 | 399 | |
| 386 | 400 | #endif |
| ... | ... | @@ -391,21 +405,30 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) |
| 391 | 405 | | The pattern for a default generated quadruple-precision NaN. The `high' and |
| 392 | 406 | | `low' values hold the most- and least-significant bits, respectively. |
| 393 | 407 | *----------------------------------------------------------------------------*/ |
| 408 | +#if SNAN_BIT_IS_ONE | |
| 409 | +#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF ) | |
| 410 | +#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) | |
| 411 | +#else | |
| 394 | 412 | #define float128_default_nan_high LIT64( 0xFFFF800000000000 ) |
| 395 | 413 | #define float128_default_nan_low LIT64( 0x0000000000000000 ) |
| 414 | +#endif | |
| 396 | 415 | |
| 397 | 416 | /*---------------------------------------------------------------------------- |
| 398 | -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; | |
| 399 | -| otherwise returns 0. | |
| 417 | +| Returns 1 if the quadruple-precision floating-point value `a' is a quiet | |
| 418 | +| NaN; otherwise returns 0. | |
| 400 | 419 | *----------------------------------------------------------------------------*/ |
| 401 | 420 | |
| 402 | 421 | int float128_is_nan( float128 a ) |
| 403 | 422 | { |
| 404 | - | |
| 423 | +#if SNAN_BIT_IS_ONE | |
| 424 | + return | |
| 425 | + ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) | |
| 426 | + && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); | |
| 427 | +#else | |
| 405 | 428 | return |
| 406 | 429 | ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) |
| 407 | 430 | && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); |
| 408 | - | |
| 431 | +#endif | |
| 409 | 432 | } |
| 410 | 433 | |
| 411 | 434 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -415,11 +438,15 @@ int float128_is_nan( float128 a ) |
| 415 | 438 | |
| 416 | 439 | int float128_is_signaling_nan( float128 a ) |
| 417 | 440 | { |
| 418 | - | |
| 441 | +#if SNAN_BIT_IS_ONE | |
| 442 | + return | |
| 443 | + ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) | |
| 444 | + && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); | |
| 445 | +#else | |
| 419 | 446 | return |
| 420 | 447 | ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) |
| 421 | 448 | && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); |
| 422 | - | |
| 449 | +#endif | |
| 423 | 450 | } |
| 424 | 451 | |
| 425 | 452 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -436,7 +463,6 @@ static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM) |
| 436 | 463 | z.sign = a.high>>63; |
| 437 | 464 | shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); |
| 438 | 465 | return z; |
| 439 | - | |
| 440 | 466 | } |
| 441 | 467 | |
| 442 | 468 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -451,7 +477,6 @@ static float128 commonNaNToFloat128( commonNaNT a ) |
| 451 | 477 | shift128Right( a.high, a.low, 16, &z.high, &z.low ); |
| 452 | 478 | z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); |
| 453 | 479 | return z; |
| 454 | - | |
| 455 | 480 | } |
| 456 | 481 | |
| 457 | 482 | /*---------------------------------------------------------------------------- |
| ... | ... | @@ -468,8 +493,13 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM) |
| 468 | 493 | aIsSignalingNaN = float128_is_signaling_nan( a ); |
| 469 | 494 | bIsNaN = float128_is_nan( b ); |
| 470 | 495 | bIsSignalingNaN = float128_is_signaling_nan( b ); |
| 496 | +#if SNAN_BIT_IS_ONE | |
| 497 | + a.high &= ~LIT64( 0x0000800000000000 ); | |
| 498 | + b.high &= ~LIT64( 0x0000800000000000 ); | |
| 499 | +#else | |
| 471 | 500 | a.high |= LIT64( 0x0000800000000000 ); |
| 472 | 501 | b.high |= LIT64( 0x0000800000000000 ); |
| 502 | +#endif | |
| 473 | 503 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR); |
| 474 | 504 | if ( aIsSignalingNaN ) { |
| 475 | 505 | if ( bIsSignalingNaN ) goto returnLargerSignificand; |
| ... | ... | @@ -485,8 +515,6 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM) |
| 485 | 515 | else { |
| 486 | 516 | return b; |
| 487 | 517 | } |
| 488 | - | |
| 489 | 518 | } |
| 490 | 519 | |
| 491 | 520 | #endif |
| 492 | - | ... | ... |