]> git.proxmox.com Git - qemu.git/blame - fpu/softfloat-specialize.h
softfloat: add float{x80,128}_maybe_silence_nan()
[qemu.git] / fpu / softfloat-specialize.h
CommitLineData
158142c2
FB
1
2/*============================================================================
3
4This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
5Arithmetic Package, Release 2b.
6
7Written by John R. Hauser. This work was made possible in part by the
8International Computer Science Institute, located at Suite 600, 1947 Center
9Street, Berkeley, California 94704. Funding was partially provided by the
10National Science Foundation under grant MIP-9311980. The original version
11of this code was written as part of a project to build a fixed-point vector
12processor in collaboration with the University of California at Berkeley,
13overseen by Profs. Nelson Morgan and John Wawrzynek. More information
14is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
15arithmetic/SoftFloat.html'.
16
17THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
18been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
19RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
20AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
21COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
22EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
23INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
24OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
25
26Derivative works are acceptable, even for commercial purposes, so long as
27(1) the source code for the derivative work includes prominent notice that
28the work is derivative, and (2) the source code includes prominent notice with
29these four paragraphs for those parts of this code that are retained.
30
31=============================================================================*/
32
34d23861 33#if defined(TARGET_MIPS)
5a6932d5
TS
34#define SNAN_BIT_IS_ONE 1
35#else
36#define SNAN_BIT_IS_ONE 0
37#endif
38
158142c2
FB
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*----------------------------------------------------------------------------*/
45
46void float_raise( int8 flags STATUS_PARAM )
47{
158142c2 48 STATUS(float_exception_flags) |= flags;
158142c2
FB
49}
50
51/*----------------------------------------------------------------------------
52| Internal canonical NaN format.
53*----------------------------------------------------------------------------*/
54typedef struct {
55 flag sign;
56 bits64 high, low;
57} commonNaNT;
58
59/*----------------------------------------------------------------------------
60| The pattern for a default generated single-precision NaN.
61*----------------------------------------------------------------------------*/
85016c98
TS
62#if defined(TARGET_SPARC)
63#define float32_default_nan make_float32(0x7FFFFFFF)
990b3e19 64#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
85016c98 65#define float32_default_nan make_float32(0x7FC00000)
85016c98 66#elif SNAN_BIT_IS_ONE
f090c9d4 67#define float32_default_nan make_float32(0x7FBFFFFF)
b645bb48 68#else
f090c9d4 69#define float32_default_nan make_float32(0xFFC00000)
b645bb48 70#endif
158142c2
FB
71
72/*----------------------------------------------------------------------------
5a6932d5
TS
73| Returns 1 if the single-precision floating-point value `a' is a quiet
74| NaN; otherwise returns 0.
158142c2
FB
75*----------------------------------------------------------------------------*/
76
18569871 77int float32_is_quiet_nan( float32 a_ )
158142c2 78{
f090c9d4 79 uint32_t a = float32_val(a_);
5a6932d5 80#if SNAN_BIT_IS_ONE
b645bb48
TS
81 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
82#else
83 return ( 0xFF800000 <= (bits32) ( a<<1 ) );
84#endif
158142c2
FB
85}
86
87/*----------------------------------------------------------------------------
88| Returns 1 if the single-precision floating-point value `a' is a signaling
89| NaN; otherwise returns 0.
90*----------------------------------------------------------------------------*/
91
f090c9d4 92int float32_is_signaling_nan( float32 a_ )
158142c2 93{
f090c9d4 94 uint32_t a = float32_val(a_);
5a6932d5 95#if SNAN_BIT_IS_ONE
b645bb48
TS
96 return ( 0xFF800000 <= (bits32) ( a<<1 ) );
97#else
158142c2 98 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
b645bb48 99#endif
158142c2
FB
100}
101
b408dbde
PM
102/*----------------------------------------------------------------------------
103| Returns a quiet NaN if the single-precision floating point value `a' is a
104| signaling NaN; otherwise returns `a'.
105*----------------------------------------------------------------------------*/
106
107float32 float32_maybe_silence_nan( float32 a_ )
108{
109 if (float32_is_signaling_nan(a_)) {
b408dbde 110#if SNAN_BIT_IS_ONE
93ae1c6f
AJ
111# if defined(TARGET_MIPS)
112 return float32_default_nan;
113# else
114# error Rules for silencing a signaling NaN are target-specific
115# endif
b408dbde 116#else
93ae1c6f 117 bits32 a = float32_val(a_);
b408dbde 118 a |= (1 << 22);
b408dbde 119 return make_float32(a);
93ae1c6f 120#endif
b408dbde
PM
121 }
122 return a_;
123}
124
158142c2
FB
125/*----------------------------------------------------------------------------
126| Returns the result of converting the single-precision floating-point NaN
127| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
128| exception is raised.
129*----------------------------------------------------------------------------*/
130
131static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
132{
133 commonNaNT z;
134
135 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
f090c9d4 136 z.sign = float32_val(a)>>31;
158142c2 137 z.low = 0;
f090c9d4 138 z.high = ( (bits64) float32_val(a) )<<41;
158142c2 139 return z;
158142c2
FB
140}
141
142/*----------------------------------------------------------------------------
143| Returns the result of converting the canonical NaN `a' to the single-
144| precision floating-point format.
145*----------------------------------------------------------------------------*/
146
147static float32 commonNaNToFloat32( commonNaNT a )
148{
85016c98
TS
149 bits32 mantissa = a.high>>41;
150 if ( mantissa )
151 return make_float32(
152 ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
153 else
154 return float32_default_nan;
158142c2
FB
155}
156
354f211b
PM
157/*----------------------------------------------------------------------------
158| Select which NaN to propagate for a two-input operation.
159| IEEE754 doesn't specify all the details of this, so the
160| algorithm is target-specific.
161| The routine is passed various bits of information about the
162| two NaNs and should return 0 to select NaN a and 1 for NaN b.
163| Note that signalling NaNs are always squashed to quiet NaNs
164| by the caller, by flipping the SNaN bit before returning them.
165|
166| aIsLargerSignificand is only valid if both a and b are NaNs
167| of some kind, and is true if a has the larger significand,
168| or if both a and b have the same significand but a is
169| positive but b is negative. It is only needed for the x87
170| tie-break rule.
171*----------------------------------------------------------------------------*/
172
011da610
PM
173#if defined(TARGET_ARM)
174static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
175 flag aIsLargerSignificand)
176{
177 /* ARM mandated NaN propagation rules: take the first of:
178 * 1. A if it is signaling
179 * 2. B if it is signaling
180 * 3. A (quiet)
181 * 4. B (quiet)
182 * A signaling NaN is always quietened before returning it.
183 */
184 if (aIsSNaN) {
185 return 0;
186 } else if (bIsSNaN) {
187 return 1;
188 } else if (aIsQNaN) {
189 return 0;
190 } else {
191 return 1;
192 }
193}
194#else
354f211b
PM
195static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
196 flag aIsLargerSignificand)
197{
198 /* This implements x87 NaN propagation rules:
199 * SNaN + QNaN => return the QNaN
200 * two SNaNs => return the one with the larger significand, silenced
201 * two QNaNs => return the one with the larger significand
202 * SNaN and a non-NaN => return the SNaN, silenced
203 * QNaN and a non-NaN => return the QNaN
204 *
205 * If we get down to comparing significands and they are the same,
206 * return the NaN with the positive sign bit (if any).
207 */
208 if (aIsSNaN) {
209 if (bIsSNaN) {
210 return aIsLargerSignificand ? 0 : 1;
211 }
212 return bIsQNaN ? 1 : 0;
213 }
214 else if (aIsQNaN) {
215 if (bIsSNaN || !bIsQNaN)
216 return 0;
217 else {
218 return aIsLargerSignificand ? 0 : 1;
219 }
220 } else {
221 return 1;
222 }
223}
011da610 224#endif
354f211b 225
158142c2
FB
226/*----------------------------------------------------------------------------
227| Takes two single-precision floating-point values `a' and `b', one of which
228| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
229| signaling NaN, the invalid exception is raised.
230*----------------------------------------------------------------------------*/
231
232static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
233{
d735d695
AJ
234 flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
235 flag aIsLargerSignificand;
f090c9d4 236 bits32 av, bv, res;
158142c2 237
5c7908ed
PB
238 if ( STATUS(default_nan_mode) )
239 return float32_default_nan;
240
d735d695 241 aIsQuietNaN = float32_is_quiet_nan( a );
158142c2 242 aIsSignalingNaN = float32_is_signaling_nan( a );
d735d695 243 bIsQuietNaN = float32_is_quiet_nan( b );
158142c2 244 bIsSignalingNaN = float32_is_signaling_nan( b );
f090c9d4
PB
245 av = float32_val(a);
246 bv = float32_val(b);
5a6932d5 247#if SNAN_BIT_IS_ONE
f090c9d4
PB
248 av &= ~0x00400000;
249 bv &= ~0x00400000;
b645bb48 250#else
f090c9d4
PB
251 av |= 0x00400000;
252 bv |= 0x00400000;
b645bb48 253#endif
158142c2 254 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
354f211b
PM
255
256 if ((bits32)(av<<1) < (bits32)(bv<<1)) {
257 aIsLargerSignificand = 0;
258 } else if ((bits32)(bv<<1) < (bits32)(av<<1)) {
259 aIsLargerSignificand = 1;
260 } else {
261 aIsLargerSignificand = (av < bv) ? 1 : 0;
158142c2 262 }
354f211b 263
d735d695 264 if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
354f211b 265 aIsLargerSignificand)) {
f090c9d4 266 res = bv;
354f211b
PM
267 } else {
268 res = av;
158142c2 269 }
354f211b 270
f090c9d4 271 return make_float32(res);
158142c2
FB
272}
273
274/*----------------------------------------------------------------------------
275| The pattern for a default generated double-precision NaN.
276*----------------------------------------------------------------------------*/
85016c98
TS
277#if defined(TARGET_SPARC)
278#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
990b3e19 279#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
85016c98 280#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
85016c98 281#elif SNAN_BIT_IS_ONE
f090c9d4 282#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
b645bb48 283#else
f090c9d4 284#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
b645bb48 285#endif
158142c2
FB
286
287/*----------------------------------------------------------------------------
5a6932d5
TS
288| Returns 1 if the double-precision floating-point value `a' is a quiet
289| NaN; otherwise returns 0.
158142c2
FB
290*----------------------------------------------------------------------------*/
291
18569871 292int float64_is_quiet_nan( float64 a_ )
158142c2 293{
f090c9d4 294 bits64 a = float64_val(a_);
5a6932d5 295#if SNAN_BIT_IS_ONE
b645bb48
TS
296 return
297 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
298 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
299#else
300 return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
301#endif
158142c2
FB
302}
303
304/*----------------------------------------------------------------------------
305| Returns 1 if the double-precision floating-point value `a' is a signaling
306| NaN; otherwise returns 0.
307*----------------------------------------------------------------------------*/
308
f090c9d4 309int float64_is_signaling_nan( float64 a_ )
158142c2 310{
f090c9d4 311 bits64 a = float64_val(a_);
5a6932d5 312#if SNAN_BIT_IS_ONE
b645bb48
TS
313 return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
314#else
158142c2
FB
315 return
316 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
317 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
b645bb48 318#endif
158142c2
FB
319}
320
b408dbde
PM
321/*----------------------------------------------------------------------------
322| Returns a quiet NaN if the double-precision floating point value `a' is a
323| signaling NaN; otherwise returns `a'.
324*----------------------------------------------------------------------------*/
325
326float64 float64_maybe_silence_nan( float64 a_ )
327{
328 if (float64_is_signaling_nan(a_)) {
b408dbde 329#if SNAN_BIT_IS_ONE
93ae1c6f
AJ
330# if defined(TARGET_MIPS)
331 return float64_default_nan;
332# else
333# error Rules for silencing a signaling NaN are target-specific
334# endif
b408dbde 335#else
93ae1c6f 336 bits64 a = float64_val(a_);
b408dbde 337 a |= LIT64( 0x0008000000000000 );
b408dbde 338 return make_float64(a);
93ae1c6f 339#endif
b408dbde
PM
340 }
341 return a_;
342}
343
158142c2
FB
344/*----------------------------------------------------------------------------
345| Returns the result of converting the double-precision floating-point NaN
346| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
347| exception is raised.
348*----------------------------------------------------------------------------*/
349
350static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
351{
352 commonNaNT z;
353
354 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
f090c9d4 355 z.sign = float64_val(a)>>63;
158142c2 356 z.low = 0;
f090c9d4 357 z.high = float64_val(a)<<12;
158142c2 358 return z;
158142c2
FB
359}
360
361/*----------------------------------------------------------------------------
362| Returns the result of converting the canonical NaN `a' to the double-
363| precision floating-point format.
364*----------------------------------------------------------------------------*/
365
366static float64 commonNaNToFloat64( commonNaNT a )
367{
85016c98
TS
368 bits64 mantissa = a.high>>12;
369
370 if ( mantissa )
371 return make_float64(
372 ( ( (bits64) a.sign )<<63 )
373 | LIT64( 0x7FF0000000000000 )
374 | ( a.high>>12 ));
375 else
376 return float64_default_nan;
158142c2
FB
377}
378
379/*----------------------------------------------------------------------------
380| Takes two double-precision floating-point values `a' and `b', one of which
381| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
382| signaling NaN, the invalid exception is raised.
383*----------------------------------------------------------------------------*/
384
385static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
386{
d735d695
AJ
387 flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
388 flag aIsLargerSignificand;
f090c9d4 389 bits64 av, bv, res;
158142c2 390
5c7908ed
PB
391 if ( STATUS(default_nan_mode) )
392 return float64_default_nan;
393
d735d695 394 aIsQuietNaN = float64_is_quiet_nan( a );
158142c2 395 aIsSignalingNaN = float64_is_signaling_nan( a );
d735d695 396 bIsQuietNaN = float64_is_quiet_nan( b );
158142c2 397 bIsSignalingNaN = float64_is_signaling_nan( b );
f090c9d4
PB
398 av = float64_val(a);
399 bv = float64_val(b);
5a6932d5 400#if SNAN_BIT_IS_ONE
f090c9d4
PB
401 av &= ~LIT64( 0x0008000000000000 );
402 bv &= ~LIT64( 0x0008000000000000 );
b645bb48 403#else
f090c9d4
PB
404 av |= LIT64( 0x0008000000000000 );
405 bv |= LIT64( 0x0008000000000000 );
b645bb48 406#endif
158142c2 407 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
354f211b
PM
408
409 if ((bits64)(av<<1) < (bits64)(bv<<1)) {
410 aIsLargerSignificand = 0;
411 } else if ((bits64)(bv<<1) < (bits64)(av<<1)) {
412 aIsLargerSignificand = 1;
413 } else {
414 aIsLargerSignificand = (av < bv) ? 1 : 0;
158142c2 415 }
354f211b 416
d735d695 417 if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
354f211b 418 aIsLargerSignificand)) {
f090c9d4 419 res = bv;
354f211b
PM
420 } else {
421 res = av;
158142c2 422 }
354f211b 423
f090c9d4 424 return make_float64(res);
158142c2
FB
425}
426
427#ifdef FLOATX80
428
429/*----------------------------------------------------------------------------
430| The pattern for a default generated extended double-precision NaN. The
431| `high' and `low' values hold the most- and least-significant bits,
432| respectively.
433*----------------------------------------------------------------------------*/
5a6932d5
TS
434#if SNAN_BIT_IS_ONE
435#define floatx80_default_nan_high 0x7FFF
436#define floatx80_default_nan_low LIT64( 0xBFFFFFFFFFFFFFFF )
437#else
158142c2
FB
438#define floatx80_default_nan_high 0xFFFF
439#define floatx80_default_nan_low LIT64( 0xC000000000000000 )
5a6932d5 440#endif
158142c2
FB
441
442/*----------------------------------------------------------------------------
443| Returns 1 if the extended double-precision floating-point value `a' is a
5a6932d5 444| quiet NaN; otherwise returns 0.
158142c2
FB
445*----------------------------------------------------------------------------*/
446
18569871 447int floatx80_is_quiet_nan( floatx80 a )
158142c2 448{
5a6932d5
TS
449#if SNAN_BIT_IS_ONE
450 bits64 aLow;
158142c2 451
5a6932d5
TS
452 aLow = a.low & ~ LIT64( 0x4000000000000000 );
453 return
454 ( ( a.high & 0x7FFF ) == 0x7FFF )
455 && (bits64) ( aLow<<1 )
456 && ( a.low == aLow );
457#else
158142c2 458 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
5a6932d5 459#endif
158142c2
FB
460}
461
462/*----------------------------------------------------------------------------
463| Returns 1 if the extended double-precision floating-point value `a' is a
464| signaling NaN; otherwise returns 0.
465*----------------------------------------------------------------------------*/
466
750afe93 467int floatx80_is_signaling_nan( floatx80 a )
158142c2 468{
5a6932d5
TS
469#if SNAN_BIT_IS_ONE
470 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
471#else
158142c2
FB
472 bits64 aLow;
473
474 aLow = a.low & ~ LIT64( 0x4000000000000000 );
475 return
476 ( ( a.high & 0x7FFF ) == 0x7FFF )
477 && (bits64) ( aLow<<1 )
478 && ( a.low == aLow );
5a6932d5 479#endif
158142c2
FB
480}
481
f6a7d92a
AJ
482/*----------------------------------------------------------------------------
483| Returns a quiet NaN if the extended double-precision floating point value
484| `a' is a signaling NaN; otherwise returns `a'.
485*----------------------------------------------------------------------------*/
486
487floatx80 floatx80_maybe_silence_nan( floatx80 a )
488{
489 if (floatx80_is_signaling_nan(a)) {
490#if SNAN_BIT_IS_ONE
491# if defined(TARGET_MIPS)
492 a.low = floatx80_default_nan_low;
493 a.high = floatx80_default_nan_high;
494# else
495# error Rules for silencing a signaling NaN are target-specific
496# endif
497#else
498 a.low |= LIT64( 0xC000000000000000 );
499 return a;
500#endif
501 }
502 return a;
503}
504
158142c2
FB
505/*----------------------------------------------------------------------------
506| Returns the result of converting the extended double-precision floating-
507| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
508| invalid exception is raised.
509*----------------------------------------------------------------------------*/
510
511static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
512{
513 commonNaNT z;
514
515 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
516 z.sign = a.high>>15;
517 z.low = 0;
85016c98 518 z.high = a.low;
158142c2 519 return z;
158142c2
FB
520}
521
522/*----------------------------------------------------------------------------
523| Returns the result of converting the canonical NaN `a' to the extended
524| double-precision floating-point format.
525*----------------------------------------------------------------------------*/
526
527static floatx80 commonNaNToFloatx80( commonNaNT a )
528{
529 floatx80 z;
530
85016c98
TS
531 if (a.high)
532 z.low = a.high;
533 else
534 z.low = floatx80_default_nan_low;
158142c2
FB
535 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
536 return z;
158142c2
FB
537}
538
539/*----------------------------------------------------------------------------
540| Takes two extended double-precision floating-point values `a' and `b', one
541| of which is a NaN, and returns the appropriate NaN result. If either `a' or
542| `b' is a signaling NaN, the invalid exception is raised.
543*----------------------------------------------------------------------------*/
544
545static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
546{
d735d695
AJ
547 flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
548 flag aIsLargerSignificand;
158142c2 549
5c7908ed
PB
550 if ( STATUS(default_nan_mode) ) {
551 a.low = floatx80_default_nan_low;
552 a.high = floatx80_default_nan_high;
553 return a;
554 }
555
d735d695 556 aIsQuietNaN = floatx80_is_quiet_nan( a );
158142c2 557 aIsSignalingNaN = floatx80_is_signaling_nan( a );
d735d695 558 bIsQuietNaN = floatx80_is_quiet_nan( b );
158142c2 559 bIsSignalingNaN = floatx80_is_signaling_nan( b );
5a6932d5
TS
560#if SNAN_BIT_IS_ONE
561 a.low &= ~LIT64( 0xC000000000000000 );
562 b.low &= ~LIT64( 0xC000000000000000 );
563#else
158142c2
FB
564 a.low |= LIT64( 0xC000000000000000 );
565 b.low |= LIT64( 0xC000000000000000 );
5a6932d5 566#endif
158142c2 567 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
354f211b
PM
568
569 if (a.low < b.low) {
570 aIsLargerSignificand = 0;
571 } else if (b.low < a.low) {
572 aIsLargerSignificand = 1;
573 } else {
574 aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
158142c2 575 }
354f211b 576
d735d695 577 if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
354f211b 578 aIsLargerSignificand)) {
158142c2 579 return b;
354f211b
PM
580 } else {
581 return a;
158142c2 582 }
158142c2
FB
583}
584
585#endif
586
587#ifdef FLOAT128
588
589/*----------------------------------------------------------------------------
590| The pattern for a default generated quadruple-precision NaN. The `high' and
591| `low' values hold the most- and least-significant bits, respectively.
592*----------------------------------------------------------------------------*/
5a6932d5
TS
593#if SNAN_BIT_IS_ONE
594#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
595#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
596#else
158142c2
FB
597#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
598#define float128_default_nan_low LIT64( 0x0000000000000000 )
5a6932d5 599#endif
158142c2
FB
600
601/*----------------------------------------------------------------------------
5a6932d5
TS
602| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
603| NaN; otherwise returns 0.
158142c2
FB
604*----------------------------------------------------------------------------*/
605
18569871 606int float128_is_quiet_nan( float128 a )
158142c2 607{
5a6932d5
TS
608#if SNAN_BIT_IS_ONE
609 return
610 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
611 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
612#else
158142c2
FB
613 return
614 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
615 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
5a6932d5 616#endif
158142c2
FB
617}
618
619/*----------------------------------------------------------------------------
620| Returns 1 if the quadruple-precision floating-point value `a' is a
621| signaling NaN; otherwise returns 0.
622*----------------------------------------------------------------------------*/
623
750afe93 624int float128_is_signaling_nan( float128 a )
158142c2 625{
5a6932d5
TS
626#if SNAN_BIT_IS_ONE
627 return
628 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
629 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
630#else
158142c2
FB
631 return
632 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
633 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
5a6932d5 634#endif
158142c2
FB
635}
636
f6a7d92a
AJ
637/*----------------------------------------------------------------------------
638| Returns a quiet NaN if the quadruple-precision floating point value `a' is
639| a signaling NaN; otherwise returns `a'.
640*----------------------------------------------------------------------------*/
641
642float128 float128_maybe_silence_nan( float128 a )
643{
644 if (float128_is_signaling_nan(a)) {
645#if SNAN_BIT_IS_ONE
646# if defined(TARGET_MIPS)
647 a.low = float128_default_nan_low;
648 a.high = float128_default_nan_high;
649# else
650# error Rules for silencing a signaling NaN are target-specific
651# endif
652#else
653 a.high |= LIT64( 0x0000800000000000 );
654 return a;
655#endif
656 }
657 return a;
658}
659
158142c2
FB
660/*----------------------------------------------------------------------------
661| Returns the result of converting the quadruple-precision floating-point NaN
662| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
663| exception is raised.
664*----------------------------------------------------------------------------*/
665
666static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
667{
668 commonNaNT z;
669
670 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
671 z.sign = a.high>>63;
672 shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
673 return z;
158142c2
FB
674}
675
676/*----------------------------------------------------------------------------
677| Returns the result of converting the canonical NaN `a' to the quadruple-
678| precision floating-point format.
679*----------------------------------------------------------------------------*/
680
681static float128 commonNaNToFloat128( commonNaNT a )
682{
683 float128 z;
684
685 shift128Right( a.high, a.low, 16, &z.high, &z.low );
85016c98 686 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
158142c2 687 return z;
158142c2
FB
688}
689
690/*----------------------------------------------------------------------------
691| Takes two quadruple-precision floating-point values `a' and `b', one of
692| which is a NaN, and returns the appropriate NaN result. If either `a' or
693| `b' is a signaling NaN, the invalid exception is raised.
694*----------------------------------------------------------------------------*/
695
696static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
697{
d735d695
AJ
698 flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
699 flag aIsLargerSignificand;
158142c2 700
5c7908ed
PB
701 if ( STATUS(default_nan_mode) ) {
702 a.low = float128_default_nan_low;
703 a.high = float128_default_nan_high;
704 return a;
705 }
706
d735d695 707 aIsQuietNaN = float128_is_quiet_nan( a );
158142c2 708 aIsSignalingNaN = float128_is_signaling_nan( a );
d735d695 709 bIsQuietNaN = float128_is_quiet_nan( b );
158142c2 710 bIsSignalingNaN = float128_is_signaling_nan( b );
5a6932d5
TS
711#if SNAN_BIT_IS_ONE
712 a.high &= ~LIT64( 0x0000800000000000 );
713 b.high &= ~LIT64( 0x0000800000000000 );
714#else
158142c2
FB
715 a.high |= LIT64( 0x0000800000000000 );
716 b.high |= LIT64( 0x0000800000000000 );
5a6932d5 717#endif
158142c2 718 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
354f211b
PM
719
720 if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
721 aIsLargerSignificand = 0;
722 } else if (lt128(b.high<<1, b.low, a.high<<1, a.low)) {
723 aIsLargerSignificand = 1;
724 } else {
725 aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
158142c2 726 }
354f211b 727
d735d695 728 if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
354f211b 729 aIsLargerSignificand)) {
158142c2 730 return b;
354f211b
PM
731 } else {
732 return a;
158142c2 733 }
158142c2
FB
734}
735
736#endif