target-arm: Implement correct NaN propagation rules
[qemu.git] / fpu / softfloat-specialize.h
blobf43f2d0acef6423dfeff11df44a720f406588c51
2 /*============================================================================
4 This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
5 Arithmetic Package, Release 2b.
7 Written by John R. Hauser. This work was made possible in part by the
8 International Computer Science Institute, located at Suite 600, 1947 Center
9 Street, Berkeley, California 94704. Funding was partially provided by the
10 National Science Foundation under grant MIP-9311980. The original version
11 of this code was written as part of a project to build a fixed-point vector
12 processor in collaboration with the University of California at Berkeley,
13 overseen by Profs. Nelson Morgan and John Wawrzynek. More information
14 is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
15 arithmetic/SoftFloat.html'.
17 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
18 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
19 RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
20 AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
21 COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
22 EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
23 INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
24 OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
26 Derivative works are acceptable, even for commercial purposes, so long as
27 (1) the source code for the derivative work includes prominent notice that
28 the work is derivative, and (2) the source code includes prominent notice with
29 these four paragraphs for those parts of this code that are retained.
31 =============================================================================*/
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
39 /*----------------------------------------------------------------------------
40 | Raises the exceptions specified by `flags'. Floating-point traps can be
41 | defined here if desired. It is currently not possible for such a trap
42 | to substitute a result value. If traps are not implemented, this routine
43 | should be simply `float_exception_flags |= flags;'.
44 *----------------------------------------------------------------------------*/
46 void float_raise( int8 flags STATUS_PARAM )
48 STATUS(float_exception_flags) |= flags;
51 /*----------------------------------------------------------------------------
52 | Internal canonical NaN format.
53 *----------------------------------------------------------------------------*/
54 typedef struct {
55 flag sign;
56 bits64 high, low;
57 } commonNaNT;
59 /*----------------------------------------------------------------------------
60 | The pattern for a default generated single-precision NaN.
61 *----------------------------------------------------------------------------*/
62 #if defined(TARGET_SPARC)
63 #define float32_default_nan make_float32(0x7FFFFFFF)
64 #elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
65 #define float32_default_nan make_float32(0x7FC00000)
66 #elif defined(TARGET_HPPA)
67 #define float32_default_nan make_float32(0x7FA00000)
68 #elif SNAN_BIT_IS_ONE
69 #define float32_default_nan make_float32(0x7FBFFFFF)
70 #else
71 #define float32_default_nan make_float32(0xFFC00000)
72 #endif
74 /*----------------------------------------------------------------------------
75 | Returns 1 if the single-precision floating-point value `a' is a quiet
76 | NaN; otherwise returns 0.
77 *----------------------------------------------------------------------------*/
79 int float32_is_quiet_nan( float32 a_ )
81 uint32_t a = float32_val(a_);
82 #if SNAN_BIT_IS_ONE
83 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
84 #else
85 return ( 0xFF800000 <= (bits32) ( a<<1 ) );
86 #endif
89 /*----------------------------------------------------------------------------
90 | Returns 1 if the single-precision floating-point value `a' is a signaling
91 | NaN; otherwise returns 0.
92 *----------------------------------------------------------------------------*/
94 int float32_is_signaling_nan( float32 a_ )
96 uint32_t a = float32_val(a_);
97 #if SNAN_BIT_IS_ONE
98 return ( 0xFF800000 <= (bits32) ( a<<1 ) );
99 #else
100 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
101 #endif
104 /*----------------------------------------------------------------------------
105 | Returns a quiet NaN if the single-precision floating point value `a' is a
106 | signaling NaN; otherwise returns `a'.
107 *----------------------------------------------------------------------------*/
109 float32 float32_maybe_silence_nan( float32 a_ )
111 if (float32_is_signaling_nan(a_)) {
112 uint32_t a = float32_val(a_);
113 #if SNAN_BIT_IS_ONE
114 a &= ~(1 << 22);
115 #else
116 a |= (1 << 22);
117 #endif
118 return make_float32(a);
120 return a_;
123 /*----------------------------------------------------------------------------
124 | Returns the result of converting the single-precision floating-point NaN
125 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
126 | exception is raised.
127 *----------------------------------------------------------------------------*/
129 static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
131 commonNaNT z;
133 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
134 z.sign = float32_val(a)>>31;
135 z.low = 0;
136 z.high = ( (bits64) float32_val(a) )<<41;
137 return z;
140 /*----------------------------------------------------------------------------
141 | Returns the result of converting the canonical NaN `a' to the single-
142 | precision floating-point format.
143 *----------------------------------------------------------------------------*/
145 static float32 commonNaNToFloat32( commonNaNT a )
147 bits32 mantissa = a.high>>41;
148 if ( mantissa )
149 return make_float32(
150 ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
151 else
152 return float32_default_nan;
155 /*----------------------------------------------------------------------------
156 | Select which NaN to propagate for a two-input operation.
157 | IEEE754 doesn't specify all the details of this, so the
158 | algorithm is target-specific.
159 | The routine is passed various bits of information about the
160 | two NaNs and should return 0 to select NaN a and 1 for NaN b.
161 | Note that signalling NaNs are always squashed to quiet NaNs
162 | by the caller, by flipping the SNaN bit before returning them.
164 | aIsLargerSignificand is only valid if both a and b are NaNs
165 | of some kind, and is true if a has the larger significand,
166 | or if both a and b have the same significand but a is
167 | positive but b is negative. It is only needed for the x87
168 | tie-break rule.
169 *----------------------------------------------------------------------------*/
171 #if defined(TARGET_ARM)
172 static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
173 flag aIsLargerSignificand)
175 /* ARM mandated NaN propagation rules: take the first of:
176 * 1. A if it is signaling
177 * 2. B if it is signaling
178 * 3. A (quiet)
179 * 4. B (quiet)
180 * A signaling NaN is always quietened before returning it.
182 if (aIsSNaN) {
183 return 0;
184 } else if (bIsSNaN) {
185 return 1;
186 } else if (aIsQNaN) {
187 return 0;
188 } else {
189 return 1;
192 #else
193 static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
194 flag aIsLargerSignificand)
196 /* This implements x87 NaN propagation rules:
197 * SNaN + QNaN => return the QNaN
198 * two SNaNs => return the one with the larger significand, silenced
199 * two QNaNs => return the one with the larger significand
200 * SNaN and a non-NaN => return the SNaN, silenced
201 * QNaN and a non-NaN => return the QNaN
203 * If we get down to comparing significands and they are the same,
204 * return the NaN with the positive sign bit (if any).
206 if (aIsSNaN) {
207 if (bIsSNaN) {
208 return aIsLargerSignificand ? 0 : 1;
210 return bIsQNaN ? 1 : 0;
212 else if (aIsQNaN) {
213 if (bIsSNaN || !bIsQNaN)
214 return 0;
215 else {
216 return aIsLargerSignificand ? 0 : 1;
218 } else {
219 return 1;
222 #endif
224 /*----------------------------------------------------------------------------
225 | Takes two single-precision floating-point values `a' and `b', one of which
226 | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
227 | signaling NaN, the invalid exception is raised.
228 *----------------------------------------------------------------------------*/
230 static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
232 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN, aIsLargerSignificand;
233 bits32 av, bv, res;
235 if ( STATUS(default_nan_mode) )
236 return float32_default_nan;
238 aIsNaN = float32_is_quiet_nan( a );
239 aIsSignalingNaN = float32_is_signaling_nan( a );
240 bIsNaN = float32_is_quiet_nan( b );
241 bIsSignalingNaN = float32_is_signaling_nan( b );
242 av = float32_val(a);
243 bv = float32_val(b);
244 #if SNAN_BIT_IS_ONE
245 av &= ~0x00400000;
246 bv &= ~0x00400000;
247 #else
248 av |= 0x00400000;
249 bv |= 0x00400000;
250 #endif
251 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
253 if ((bits32)(av<<1) < (bits32)(bv<<1)) {
254 aIsLargerSignificand = 0;
255 } else if ((bits32)(bv<<1) < (bits32)(av<<1)) {
256 aIsLargerSignificand = 1;
257 } else {
258 aIsLargerSignificand = (av < bv) ? 1 : 0;
261 if (pickNaN(aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN,
262 aIsLargerSignificand)) {
263 res = bv;
264 } else {
265 res = av;
268 return make_float32(res);
271 /*----------------------------------------------------------------------------
272 | The pattern for a default generated double-precision NaN.
273 *----------------------------------------------------------------------------*/
274 #if defined(TARGET_SPARC)
275 #define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
276 #elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
277 #define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
278 #elif defined(TARGET_HPPA)
279 #define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
280 #elif SNAN_BIT_IS_ONE
281 #define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
282 #else
283 #define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
284 #endif
286 /*----------------------------------------------------------------------------
287 | Returns 1 if the double-precision floating-point value `a' is a quiet
288 | NaN; otherwise returns 0.
289 *----------------------------------------------------------------------------*/
291 int float64_is_quiet_nan( float64 a_ )
293 bits64 a = float64_val(a_);
294 #if SNAN_BIT_IS_ONE
295 return
296 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
297 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
298 #else
299 return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
300 #endif
303 /*----------------------------------------------------------------------------
304 | Returns 1 if the double-precision floating-point value `a' is a signaling
305 | NaN; otherwise returns 0.
306 *----------------------------------------------------------------------------*/
308 int float64_is_signaling_nan( float64 a_ )
310 bits64 a = float64_val(a_);
311 #if SNAN_BIT_IS_ONE
312 return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
313 #else
314 return
315 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
316 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
317 #endif
320 /*----------------------------------------------------------------------------
321 | Returns a quiet NaN if the double-precision floating point value `a' is a
322 | signaling NaN; otherwise returns `a'.
323 *----------------------------------------------------------------------------*/
325 float64 float64_maybe_silence_nan( float64 a_ )
327 if (float64_is_signaling_nan(a_)) {
328 bits64 a = float64_val(a_);
329 #if SNAN_BIT_IS_ONE
330 a &= ~LIT64( 0x0008000000000000 );
331 #else
332 a |= LIT64( 0x0008000000000000 );
333 #endif
334 return make_float64(a);
336 return a_;
339 /*----------------------------------------------------------------------------
340 | Returns the result of converting the double-precision floating-point NaN
341 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
342 | exception is raised.
343 *----------------------------------------------------------------------------*/
345 static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
347 commonNaNT z;
349 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
350 z.sign = float64_val(a)>>63;
351 z.low = 0;
352 z.high = float64_val(a)<<12;
353 return z;
356 /*----------------------------------------------------------------------------
357 | Returns the result of converting the canonical NaN `a' to the double-
358 | precision floating-point format.
359 *----------------------------------------------------------------------------*/
361 static float64 commonNaNToFloat64( commonNaNT a )
363 bits64 mantissa = a.high>>12;
365 if ( mantissa )
366 return make_float64(
367 ( ( (bits64) a.sign )<<63 )
368 | LIT64( 0x7FF0000000000000 )
369 | ( a.high>>12 ));
370 else
371 return float64_default_nan;
374 /*----------------------------------------------------------------------------
375 | Takes two double-precision floating-point values `a' and `b', one of which
376 | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
377 | signaling NaN, the invalid exception is raised.
378 *----------------------------------------------------------------------------*/
380 static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
382 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN, aIsLargerSignificand;
383 bits64 av, bv, res;
385 if ( STATUS(default_nan_mode) )
386 return float64_default_nan;
388 aIsNaN = float64_is_quiet_nan( a );
389 aIsSignalingNaN = float64_is_signaling_nan( a );
390 bIsNaN = float64_is_quiet_nan( b );
391 bIsSignalingNaN = float64_is_signaling_nan( b );
392 av = float64_val(a);
393 bv = float64_val(b);
394 #if SNAN_BIT_IS_ONE
395 av &= ~LIT64( 0x0008000000000000 );
396 bv &= ~LIT64( 0x0008000000000000 );
397 #else
398 av |= LIT64( 0x0008000000000000 );
399 bv |= LIT64( 0x0008000000000000 );
400 #endif
401 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
403 if ((bits64)(av<<1) < (bits64)(bv<<1)) {
404 aIsLargerSignificand = 0;
405 } else if ((bits64)(bv<<1) < (bits64)(av<<1)) {
406 aIsLargerSignificand = 1;
407 } else {
408 aIsLargerSignificand = (av < bv) ? 1 : 0;
411 if (pickNaN(aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN,
412 aIsLargerSignificand)) {
413 res = bv;
414 } else {
415 res = av;
418 return make_float64(res);
421 #ifdef FLOATX80
423 /*----------------------------------------------------------------------------
424 | The pattern for a default generated extended double-precision NaN. The
425 | `high' and `low' values hold the most- and least-significant bits,
426 | respectively.
427 *----------------------------------------------------------------------------*/
428 #if SNAN_BIT_IS_ONE
429 #define floatx80_default_nan_high 0x7FFF
430 #define floatx80_default_nan_low LIT64( 0xBFFFFFFFFFFFFFFF )
431 #else
432 #define floatx80_default_nan_high 0xFFFF
433 #define floatx80_default_nan_low LIT64( 0xC000000000000000 )
434 #endif
436 /*----------------------------------------------------------------------------
437 | Returns 1 if the extended double-precision floating-point value `a' is a
438 | quiet NaN; otherwise returns 0.
439 *----------------------------------------------------------------------------*/
441 int floatx80_is_quiet_nan( floatx80 a )
443 #if SNAN_BIT_IS_ONE
444 bits64 aLow;
446 aLow = a.low & ~ LIT64( 0x4000000000000000 );
447 return
448 ( ( a.high & 0x7FFF ) == 0x7FFF )
449 && (bits64) ( aLow<<1 )
450 && ( a.low == aLow );
451 #else
452 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
453 #endif
456 /*----------------------------------------------------------------------------
457 | Returns 1 if the extended double-precision floating-point value `a' is a
458 | signaling NaN; otherwise returns 0.
459 *----------------------------------------------------------------------------*/
461 int floatx80_is_signaling_nan( floatx80 a )
463 #if SNAN_BIT_IS_ONE
464 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
465 #else
466 bits64 aLow;
468 aLow = a.low & ~ LIT64( 0x4000000000000000 );
469 return
470 ( ( a.high & 0x7FFF ) == 0x7FFF )
471 && (bits64) ( aLow<<1 )
472 && ( a.low == aLow );
473 #endif
476 /*----------------------------------------------------------------------------
477 | Returns the result of converting the extended double-precision floating-
478 | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
479 | invalid exception is raised.
480 *----------------------------------------------------------------------------*/
482 static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
484 commonNaNT z;
486 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
487 z.sign = a.high>>15;
488 z.low = 0;
489 z.high = a.low;
490 return z;
493 /*----------------------------------------------------------------------------
494 | Returns the result of converting the canonical NaN `a' to the extended
495 | double-precision floating-point format.
496 *----------------------------------------------------------------------------*/
498 static floatx80 commonNaNToFloatx80( commonNaNT a )
500 floatx80 z;
502 if (a.high)
503 z.low = a.high;
504 else
505 z.low = floatx80_default_nan_low;
506 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
507 return z;
510 /*----------------------------------------------------------------------------
511 | Takes two extended double-precision floating-point values `a' and `b', one
512 | of which is a NaN, and returns the appropriate NaN result. If either `a' or
513 | `b' is a signaling NaN, the invalid exception is raised.
514 *----------------------------------------------------------------------------*/
516 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
518 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN, aIsLargerSignificand;
520 if ( STATUS(default_nan_mode) ) {
521 a.low = floatx80_default_nan_low;
522 a.high = floatx80_default_nan_high;
523 return a;
526 aIsNaN = floatx80_is_quiet_nan( a );
527 aIsSignalingNaN = floatx80_is_signaling_nan( a );
528 bIsNaN = floatx80_is_quiet_nan( b );
529 bIsSignalingNaN = floatx80_is_signaling_nan( b );
530 #if SNAN_BIT_IS_ONE
531 a.low &= ~LIT64( 0xC000000000000000 );
532 b.low &= ~LIT64( 0xC000000000000000 );
533 #else
534 a.low |= LIT64( 0xC000000000000000 );
535 b.low |= LIT64( 0xC000000000000000 );
536 #endif
537 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
539 if (a.low < b.low) {
540 aIsLargerSignificand = 0;
541 } else if (b.low < a.low) {
542 aIsLargerSignificand = 1;
543 } else {
544 aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
547 if (pickNaN(aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN,
548 aIsLargerSignificand)) {
549 return b;
550 } else {
551 return a;
555 #endif
557 #ifdef FLOAT128
559 /*----------------------------------------------------------------------------
560 | The pattern for a default generated quadruple-precision NaN. The `high' and
561 | `low' values hold the most- and least-significant bits, respectively.
562 *----------------------------------------------------------------------------*/
563 #if SNAN_BIT_IS_ONE
564 #define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
565 #define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
566 #else
567 #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
568 #define float128_default_nan_low LIT64( 0x0000000000000000 )
569 #endif
571 /*----------------------------------------------------------------------------
572 | Returns 1 if the quadruple-precision floating-point value `a' is a quiet
573 | NaN; otherwise returns 0.
574 *----------------------------------------------------------------------------*/
576 int float128_is_quiet_nan( float128 a )
578 #if SNAN_BIT_IS_ONE
579 return
580 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
581 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
582 #else
583 return
584 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
585 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
586 #endif
589 /*----------------------------------------------------------------------------
590 | Returns 1 if the quadruple-precision floating-point value `a' is a
591 | signaling NaN; otherwise returns 0.
592 *----------------------------------------------------------------------------*/
594 int float128_is_signaling_nan( float128 a )
596 #if SNAN_BIT_IS_ONE
597 return
598 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
599 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
600 #else
601 return
602 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
603 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
604 #endif
607 /*----------------------------------------------------------------------------
608 | Returns the result of converting the quadruple-precision floating-point NaN
609 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
610 | exception is raised.
611 *----------------------------------------------------------------------------*/
613 static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
615 commonNaNT z;
617 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
618 z.sign = a.high>>63;
619 shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
620 return z;
623 /*----------------------------------------------------------------------------
624 | Returns the result of converting the canonical NaN `a' to the quadruple-
625 | precision floating-point format.
626 *----------------------------------------------------------------------------*/
628 static float128 commonNaNToFloat128( commonNaNT a )
630 float128 z;
632 shift128Right( a.high, a.low, 16, &z.high, &z.low );
633 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
634 return z;
637 /*----------------------------------------------------------------------------
638 | Takes two quadruple-precision floating-point values `a' and `b', one of
639 | which is a NaN, and returns the appropriate NaN result. If either `a' or
640 | `b' is a signaling NaN, the invalid exception is raised.
641 *----------------------------------------------------------------------------*/
643 static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
645 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN, aIsLargerSignificand;
647 if ( STATUS(default_nan_mode) ) {
648 a.low = float128_default_nan_low;
649 a.high = float128_default_nan_high;
650 return a;
653 aIsNaN = float128_is_quiet_nan( a );
654 aIsSignalingNaN = float128_is_signaling_nan( a );
655 bIsNaN = float128_is_quiet_nan( b );
656 bIsSignalingNaN = float128_is_signaling_nan( b );
657 #if SNAN_BIT_IS_ONE
658 a.high &= ~LIT64( 0x0000800000000000 );
659 b.high &= ~LIT64( 0x0000800000000000 );
660 #else
661 a.high |= LIT64( 0x0000800000000000 );
662 b.high |= LIT64( 0x0000800000000000 );
663 #endif
664 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
666 if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
667 aIsLargerSignificand = 0;
668 } else if (lt128(b.high<<1, b.low, a.high<<1, a.low)) {
669 aIsLargerSignificand = 1;
670 } else {
671 aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
674 if (pickNaN(aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN,
675 aIsLargerSignificand)) {
676 return b;
677 } else {
678 return a;
682 #endif