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 | - | ... | ... |