softfloat-specialize.h 27.1 KB
Newer Older
1 2 3 4 5
/*
 * QEMU float support
 *
 * Derived from SoftFloat.
 */
B
bellard 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

/*============================================================================

This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2b.

Written by John R. Hauser.  This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704.  Funding was partially provided by the
National Science Foundation under grant MIP-9311980.  The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.

THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.

Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.

=============================================================================*/

/*----------------------------------------------------------------------------
| Raises the exceptions specified by `flags'.  Floating-point traps can be
| defined here if desired.  It is currently not possible for such a trap
| to substitute a result value.  If traps are not implemented, this routine
| should be simply `float_exception_flags |= flags;'.
*----------------------------------------------------------------------------*/

void float_raise( int8 flags STATUS_PARAM )
{
    STATUS(float_exception_flags) |= flags;
}

/*----------------------------------------------------------------------------
| Internal canonical NaN format.
*----------------------------------------------------------------------------*/
typedef struct {
    flag sign;
55
    uint64_t high, low;
B
bellard 已提交
56 57
} commonNaNT;

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
/*----------------------------------------------------------------------------
| Returns 1 if the half-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/

int float16_is_quiet_nan(float16 a_)
{
    uint16_t a = float16_val(a_);
#if SNAN_BIT_IS_ONE
    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
#else
    return ((a & ~0x8000) >= 0x7c80);
#endif
}

/*----------------------------------------------------------------------------
| Returns 1 if the half-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/

int float16_is_signaling_nan(float16 a_)
{
    uint16_t a = float16_val(a_);
#if SNAN_BIT_IS_ONE
    return ((a & ~0x8000) >= 0x7c80);
#else
    return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
#endif
}

/*----------------------------------------------------------------------------
| Returns a quiet NaN if the half-precision floating point value `a' is a
| signaling NaN; otherwise returns `a'.
*----------------------------------------------------------------------------*/
float16 float16_maybe_silence_nan(float16 a_)
{
    if (float16_is_signaling_nan(a_)) {
#if SNAN_BIT_IS_ONE
#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
        return float16_default_nan;
#  else
#    error Rules for silencing a signaling NaN are target-specific
#  endif
#else
        uint16_t a = float16_val(a_);
        a |= (1 << 9);
        return make_float16(a);
#endif
    }
    return a_;
}

110 111 112 113 114 115 116 117 118 119 120 121 122
/*----------------------------------------------------------------------------
| Returns the result of converting the half-precision floating-point NaN
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/

static commonNaNT float16ToCommonNaN( float16 a STATUS_PARAM )
{
    commonNaNT z;

    if ( float16_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
    z.sign = float16_val(a) >> 15;
    z.low = 0;
123
    z.high = ((uint64_t) float16_val(a))<<54;
124 125 126
    return z;
}

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the half-
| precision floating-point format.
*----------------------------------------------------------------------------*/

static float16 commonNaNToFloat16(commonNaNT a STATUS_PARAM)
{
    uint16_t mantissa = a.high>>54;

    if (STATUS(default_nan_mode)) {
        return float16_default_nan;
    }

    if (mantissa) {
        return make_float16(((((uint16_t) a.sign) << 15)
                             | (0x1F << 10) | mantissa));
    } else {
        return float16_default_nan;
    }
}

B
bellard 已提交
148
/*----------------------------------------------------------------------------
T
ths 已提交
149 150
| Returns 1 if the single-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
B
bellard 已提交
151 152
*----------------------------------------------------------------------------*/

153
int float32_is_quiet_nan( float32 a_ )
B
bellard 已提交
154
{
P
pbrook 已提交
155
    uint32_t a = float32_val(a_);
T
ths 已提交
156
#if SNAN_BIT_IS_ONE
T
ths 已提交
157 158
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
#else
159
    return ( 0xFF800000 <= (uint32_t) ( a<<1 ) );
T
ths 已提交
160
#endif
B
bellard 已提交
161 162 163 164 165 166 167
}

/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/

P
pbrook 已提交
168
int float32_is_signaling_nan( float32 a_ )
B
bellard 已提交
169
{
P
pbrook 已提交
170
    uint32_t a = float32_val(a_);
T
ths 已提交
171
#if SNAN_BIT_IS_ONE
172
    return ( 0xFF800000 <= (uint32_t) ( a<<1 ) );
T
ths 已提交
173
#else
B
bellard 已提交
174
    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
T
ths 已提交
175
#endif
B
bellard 已提交
176 177
}

178 179 180 181 182 183 184 185 186
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the single-precision floating point value `a' is a
| signaling NaN; otherwise returns `a'.
*----------------------------------------------------------------------------*/

float32 float32_maybe_silence_nan( float32 a_ )
{
    if (float32_is_signaling_nan(a_)) {
#if SNAN_BIT_IS_ONE
187
#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
188 189 190 191
        return float32_default_nan;
#  else
#    error Rules for silencing a signaling NaN are target-specific
#  endif
192
#else
193
        uint32_t a = float32_val(a_);
194 195
        a |= (1 << 22);
        return make_float32(a);
196
#endif
197 198 199 200
    }
    return a_;
}

B
bellard 已提交
201 202 203 204 205 206 207 208 209 210 211
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point NaN
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/

static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
{
    commonNaNT z;

    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
P
pbrook 已提交
212
    z.sign = float32_val(a)>>31;
B
bellard 已提交
213
    z.low = 0;
214
    z.high = ( (uint64_t) float32_val(a) )<<41;
B
bellard 已提交
215 216 217 218 219 220 221 222
    return z;
}

/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the single-
| precision floating-point format.
*----------------------------------------------------------------------------*/

223
static float32 commonNaNToFloat32( commonNaNT a STATUS_PARAM)
B
bellard 已提交
224
{
225
    uint32_t mantissa = a.high>>41;
226 227 228 229 230

    if ( STATUS(default_nan_mode) ) {
        return float32_default_nan;
    }

231 232
    if ( mantissa )
        return make_float32(
233
            ( ( (uint32_t) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
234 235
    else
        return float32_default_nan;
B
bellard 已提交
236 237
}

238 239 240 241 242 243 244
/*----------------------------------------------------------------------------
| Select which NaN to propagate for a two-input operation.
| IEEE754 doesn't specify all the details of this, so the
| algorithm is target-specific.
| The routine is passed various bits of information about the
| two NaNs and should return 0 to select NaN a and 1 for NaN b.
| Note that signalling NaNs are always squashed to quiet NaNs
245 246
| by the caller, by calling floatXX_maybe_silence_nan() before
| returning them.
247 248 249 250 251 252 253 254
|
| aIsLargerSignificand is only valid if both a and b are NaNs
| of some kind, and is true if a has the larger significand,
| or if both a and b have the same significand but a is
| positive but b is negative. It is only needed for the x87
| tie-break rule.
*----------------------------------------------------------------------------*/

255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
#if defined(TARGET_ARM)
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
                    flag aIsLargerSignificand)
{
    /* ARM mandated NaN propagation rules: take the first of:
     *  1. A if it is signaling
     *  2. B if it is signaling
     *  3. A (quiet)
     *  4. B (quiet)
     * A signaling NaN is always quietened before returning it.
     */
    if (aIsSNaN) {
        return 0;
    } else if (bIsSNaN) {
        return 1;
    } else if (aIsQNaN) {
        return 0;
    } else {
        return 1;
    }
}
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
#elif defined(TARGET_MIPS)
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
                    flag aIsLargerSignificand)
{
    /* According to MIPS specifications, if one of the two operands is
     * a sNaN, a new qNaN has to be generated. This is done in
     * floatXX_maybe_silence_nan(). For qNaN inputs the specifications
     * says: "When possible, this QNaN result is one of the operand QNaN
     * values." In practice it seems that most implementations choose
     * the first operand if both operands are qNaN. In short this gives
     * the following rules:
     *  1. A if it is signaling
     *  2. B if it is signaling
     *  3. A (quiet)
     *  4. B (quiet)
     * A signaling NaN is always silenced before returning it.
     */
    if (aIsSNaN) {
        return 0;
    } else if (bIsSNaN) {
        return 1;
    } else if (aIsQNaN) {
        return 0;
    } else {
        return 1;
    }
}
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
#elif defined(TARGET_PPC)
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
                   flag aIsLargerSignificand)
{
    /* PowerPC propagation rules:
     *  1. A if it sNaN or qNaN
     *  2. B if it sNaN or qNaN
     * A signaling NaN is always silenced before returning it.
     */
    if (aIsSNaN || aIsQNaN) {
        return 0;
    } else {
        return 1;
    }
}
318
#else
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
                    flag aIsLargerSignificand)
{
    /* This implements x87 NaN propagation rules:
     * SNaN + QNaN => return the QNaN
     * two SNaNs => return the one with the larger significand, silenced
     * two QNaNs => return the one with the larger significand
     * SNaN and a non-NaN => return the SNaN, silenced
     * QNaN and a non-NaN => return the QNaN
     *
     * If we get down to comparing significands and they are the same,
     * return the NaN with the positive sign bit (if any).
     */
    if (aIsSNaN) {
        if (bIsSNaN) {
            return aIsLargerSignificand ? 0 : 1;
        }
        return bIsQNaN ? 1 : 0;
    }
    else if (aIsQNaN) {
        if (bIsSNaN || !bIsQNaN)
            return 0;
        else {
            return aIsLargerSignificand ? 0 : 1;
        }
    } else {
        return 1;
    }
}
348
#endif
349

B
bellard 已提交
350 351 352 353 354 355 356 357
/*----------------------------------------------------------------------------
| Takes two single-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/

static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
{
358 359
    flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
    flag aIsLargerSignificand;
360
    uint32_t av, bv;
B
bellard 已提交
361

362
    aIsQuietNaN = float32_is_quiet_nan( a );
B
bellard 已提交
363
    aIsSignalingNaN = float32_is_signaling_nan( a );
364
    bIsQuietNaN = float32_is_quiet_nan( b );
B
bellard 已提交
365
    bIsSignalingNaN = float32_is_signaling_nan( b );
P
pbrook 已提交
366 367
    av = float32_val(a);
    bv = float32_val(b);
368

B
bellard 已提交
369
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
370

A
Aurelien Jarno 已提交
371 372 373
    if ( STATUS(default_nan_mode) )
        return float32_default_nan;

374
    if ((uint32_t)(av<<1) < (uint32_t)(bv<<1)) {
375
        aIsLargerSignificand = 0;
376
    } else if ((uint32_t)(bv<<1) < (uint32_t)(av<<1)) {
377 378 379
        aIsLargerSignificand = 1;
    } else {
        aIsLargerSignificand = (av < bv) ? 1 : 0;
B
bellard 已提交
380
    }
381

382
    if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
383
                aIsLargerSignificand)) {
384
        return float32_maybe_silence_nan(b);
385
    } else {
386
        return float32_maybe_silence_nan(a);
B
bellard 已提交
387 388 389 390
    }
}

/*----------------------------------------------------------------------------
T
ths 已提交
391 392
| Returns 1 if the double-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
B
bellard 已提交
393 394
*----------------------------------------------------------------------------*/

395
int float64_is_quiet_nan( float64 a_ )
B
bellard 已提交
396
{
397
    uint64_t a = float64_val(a_);
T
ths 已提交
398
#if SNAN_BIT_IS_ONE
T
ths 已提交
399 400 401 402
    return
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
#else
403
    return ( LIT64( 0xFFF0000000000000 ) <= (uint64_t) ( a<<1 ) );
T
ths 已提交
404
#endif
B
bellard 已提交
405 406 407 408 409 410 411
}

/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/

P
pbrook 已提交
412
int float64_is_signaling_nan( float64 a_ )
B
bellard 已提交
413
{
414
    uint64_t a = float64_val(a_);
T
ths 已提交
415
#if SNAN_BIT_IS_ONE
416
    return ( LIT64( 0xFFF0000000000000 ) <= (uint64_t) ( a<<1 ) );
T
ths 已提交
417
#else
B
bellard 已提交
418 419 420
    return
           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
T
ths 已提交
421
#endif
B
bellard 已提交
422 423
}

424 425 426 427 428 429 430 431 432
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the double-precision floating point value `a' is a
| signaling NaN; otherwise returns `a'.
*----------------------------------------------------------------------------*/

float64 float64_maybe_silence_nan( float64 a_ )
{
    if (float64_is_signaling_nan(a_)) {
#if SNAN_BIT_IS_ONE
433
#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
434 435 436 437
        return float64_default_nan;
#  else
#    error Rules for silencing a signaling NaN are target-specific
#  endif
438
#else
439
        uint64_t a = float64_val(a_);
440 441
        a |= LIT64( 0x0008000000000000 );
        return make_float64(a);
442
#endif
443 444 445 446
    }
    return a_;
}

B
bellard 已提交
447 448 449 450 451 452 453 454 455 456 457
/*----------------------------------------------------------------------------
| Returns the result of converting the double-precision floating-point NaN
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/

static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
{
    commonNaNT z;

    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
P
pbrook 已提交
458
    z.sign = float64_val(a)>>63;
B
bellard 已提交
459
    z.low = 0;
P
pbrook 已提交
460
    z.high = float64_val(a)<<12;
B
bellard 已提交
461 462 463 464 465 466 467 468
    return z;
}

/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the double-
| precision floating-point format.
*----------------------------------------------------------------------------*/

469
static float64 commonNaNToFloat64( commonNaNT a STATUS_PARAM)
B
bellard 已提交
470
{
471
    uint64_t mantissa = a.high>>12;
472

473 474 475 476
    if ( STATUS(default_nan_mode) ) {
        return float64_default_nan;
    }

477 478
    if ( mantissa )
        return make_float64(
479
              ( ( (uint64_t) a.sign )<<63 )
480 481 482 483
            | LIT64( 0x7FF0000000000000 )
            | ( a.high>>12 ));
    else
        return float64_default_nan;
B
bellard 已提交
484 485 486 487 488 489 490 491 492 493
}

/*----------------------------------------------------------------------------
| Takes two double-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/

static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
{
494 495
    flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
    flag aIsLargerSignificand;
496
    uint64_t av, bv;
B
bellard 已提交
497

498
    aIsQuietNaN = float64_is_quiet_nan( a );
B
bellard 已提交
499
    aIsSignalingNaN = float64_is_signaling_nan( a );
500
    bIsQuietNaN = float64_is_quiet_nan( b );
B
bellard 已提交
501
    bIsSignalingNaN = float64_is_signaling_nan( b );
P
pbrook 已提交
502 503
    av = float64_val(a);
    bv = float64_val(b);
504

B
bellard 已提交
505
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
506

A
Aurelien Jarno 已提交
507 508 509
    if ( STATUS(default_nan_mode) )
        return float64_default_nan;

510
    if ((uint64_t)(av<<1) < (uint64_t)(bv<<1)) {
511
        aIsLargerSignificand = 0;
512
    } else if ((uint64_t)(bv<<1) < (uint64_t)(av<<1)) {
513 514 515
        aIsLargerSignificand = 1;
    } else {
        aIsLargerSignificand = (av < bv) ? 1 : 0;
B
bellard 已提交
516
    }
517

518
    if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
519
                aIsLargerSignificand)) {
520
        return float64_maybe_silence_nan(b);
521
    } else {
522
        return float64_maybe_silence_nan(a);
B
bellard 已提交
523 524 525 526 527 528 529
    }
}

#ifdef FLOATX80

/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
530 531
| quiet NaN; otherwise returns 0. This slightly differs from the same
| function for other types as floatx80 has an explicit bit.
B
bellard 已提交
532 533
*----------------------------------------------------------------------------*/

534
int floatx80_is_quiet_nan( floatx80 a )
B
bellard 已提交
535
{
T
ths 已提交
536
#if SNAN_BIT_IS_ONE
537
    uint64_t aLow;
B
bellard 已提交
538

T
ths 已提交
539 540 541
    aLow = a.low & ~ LIT64( 0x4000000000000000 );
    return
           ( ( a.high & 0x7FFF ) == 0x7FFF )
542
        && (uint64_t) ( aLow<<1 )
T
ths 已提交
543 544
        && ( a.low == aLow );
#else
545
    return ( ( a.high & 0x7FFF ) == 0x7FFF )
546
        && (LIT64( 0x8000000000000000 ) <= ((uint64_t) ( a.low<<1 )));
T
ths 已提交
547
#endif
B
bellard 已提交
548 549 550 551
}

/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
552 553
| signaling NaN; otherwise returns 0. This slightly differs from the same
| function for other types as floatx80 has an explicit bit.
B
bellard 已提交
554 555
*----------------------------------------------------------------------------*/

556
int floatx80_is_signaling_nan( floatx80 a )
B
bellard 已提交
557
{
T
ths 已提交
558
#if SNAN_BIT_IS_ONE
559
    return ( ( a.high & 0x7FFF ) == 0x7FFF )
560
        && (LIT64( 0x8000000000000000 ) <= ((uint64_t) ( a.low<<1 )));
T
ths 已提交
561
#else
562
    uint64_t aLow;
B
bellard 已提交
563 564 565 566

    aLow = a.low & ~ LIT64( 0x4000000000000000 );
    return
           ( ( a.high & 0x7FFF ) == 0x7FFF )
567
        && (uint64_t) ( aLow<<1 )
B
bellard 已提交
568
        && ( a.low == aLow );
T
ths 已提交
569
#endif
B
bellard 已提交
570 571
}

572 573 574 575 576 577 578 579 580
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the extended double-precision floating point value
| `a' is a signaling NaN; otherwise returns `a'.
*----------------------------------------------------------------------------*/

floatx80 floatx80_maybe_silence_nan( floatx80 a )
{
    if (floatx80_is_signaling_nan(a)) {
#if SNAN_BIT_IS_ONE
581
#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
582 583 584 585 586 587 588 589 590 591 592 593 594
        a.low = floatx80_default_nan_low;
        a.high = floatx80_default_nan_high;
#  else
#    error Rules for silencing a signaling NaN are target-specific
#  endif
#else
        a.low |= LIT64( 0xC000000000000000 );
        return a;
#endif
    }
    return a;
}

B
bellard 已提交
595 596 597 598 599 600 601 602 603 604 605 606 607
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
| invalid exception is raised.
*----------------------------------------------------------------------------*/

static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
{
    commonNaNT z;

    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
    z.sign = a.high>>15;
    z.low = 0;
608
    z.high = a.low;
B
bellard 已提交
609 610 611 612 613 614 615 616
    return z;
}

/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the extended
| double-precision floating-point format.
*----------------------------------------------------------------------------*/

617
static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM)
B
bellard 已提交
618 619 620
{
    floatx80 z;

621 622 623 624 625 626
    if ( STATUS(default_nan_mode) ) {
        z.low = floatx80_default_nan_low;
        z.high = floatx80_default_nan_high;
        return z;
    }

627 628 629 630
    if (a.high)
        z.low = a.high;
    else
        z.low = floatx80_default_nan_low;
631
    z.high = ( ( (uint16_t) a.sign )<<15 ) | 0x7FFF;
B
bellard 已提交
632 633 634 635 636 637 638 639 640 641 642
    return z;
}

/*----------------------------------------------------------------------------
| Takes two extended double-precision floating-point values `a' and `b', one
| of which is a NaN, and returns the appropriate NaN result.  If either `a' or
| `b' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/

static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
{
643 644
    flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
    flag aIsLargerSignificand;
B
bellard 已提交
645

646
    aIsQuietNaN = floatx80_is_quiet_nan( a );
B
bellard 已提交
647
    aIsSignalingNaN = floatx80_is_signaling_nan( a );
648
    bIsQuietNaN = floatx80_is_quiet_nan( b );
B
bellard 已提交
649
    bIsSignalingNaN = floatx80_is_signaling_nan( b );
650

B
bellard 已提交
651
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
652

A
Aurelien Jarno 已提交
653 654 655 656 657 658
    if ( STATUS(default_nan_mode) ) {
        a.low = floatx80_default_nan_low;
        a.high = floatx80_default_nan_high;
        return a;
    }

659 660 661 662 663 664
    if (a.low < b.low) {
        aIsLargerSignificand = 0;
    } else if (b.low < a.low) {
        aIsLargerSignificand = 1;
    } else {
        aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
B
bellard 已提交
665
    }
666

667
    if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
668
                aIsLargerSignificand)) {
669
        return floatx80_maybe_silence_nan(b);
670
    } else {
671
        return floatx80_maybe_silence_nan(a);
B
bellard 已提交
672 673 674 675 676 677 678 679
    }
}

#endif

#ifdef FLOAT128

/*----------------------------------------------------------------------------
T
ths 已提交
680 681
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
B
bellard 已提交
682 683
*----------------------------------------------------------------------------*/

684
int float128_is_quiet_nan( float128 a )
B
bellard 已提交
685
{
T
ths 已提交
686 687 688 689 690
#if SNAN_BIT_IS_ONE
    return
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
#else
B
bellard 已提交
691
    return
692
           ( LIT64( 0xFFFE000000000000 ) <= (uint64_t) ( a.high<<1 ) )
B
bellard 已提交
693
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
T
ths 已提交
694
#endif
B
bellard 已提交
695 696 697 698 699 700 701
}

/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is a
| signaling NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/

702
int float128_is_signaling_nan( float128 a )
B
bellard 已提交
703
{
T
ths 已提交
704 705
#if SNAN_BIT_IS_ONE
    return
706
           ( LIT64( 0xFFFE000000000000 ) <= (uint64_t) ( a.high<<1 ) )
T
ths 已提交
707 708
        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
#else
B
bellard 已提交
709 710 711
    return
           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
T
ths 已提交
712
#endif
B
bellard 已提交
713 714
}

715 716 717 718 719 720 721 722 723
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the quadruple-precision floating point value `a' is
| a signaling NaN; otherwise returns `a'.
*----------------------------------------------------------------------------*/

float128 float128_maybe_silence_nan( float128 a )
{
    if (float128_is_signaling_nan(a)) {
#if SNAN_BIT_IS_ONE
724
#  if defined(TARGET_MIPS) || defined(TARGET_SH4)
725 726 727 728 729 730 731 732 733 734 735 736 737
        a.low = float128_default_nan_low;
        a.high = float128_default_nan_high;
#  else
#    error Rules for silencing a signaling NaN are target-specific
#  endif
#else
        a.high |= LIT64( 0x0000800000000000 );
        return a;
#endif
    }
    return a;
}

B
bellard 已提交
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point NaN
| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/

static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
{
    commonNaNT z;

    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
    z.sign = a.high>>63;
    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
    return z;
}

/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the quadruple-
| precision floating-point format.
*----------------------------------------------------------------------------*/

759
static float128 commonNaNToFloat128( commonNaNT a STATUS_PARAM)
B
bellard 已提交
760 761 762
{
    float128 z;

763 764 765 766 767 768
    if ( STATUS(default_nan_mode) ) {
        z.low = float128_default_nan_low;
        z.high = float128_default_nan_high;
        return z;
    }

B
bellard 已提交
769
    shift128Right( a.high, a.low, 16, &z.high, &z.low );
770
    z.high |= ( ( (uint64_t) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
B
bellard 已提交
771 772 773 774 775 776 777 778 779 780 781
    return z;
}

/*----------------------------------------------------------------------------
| Takes two quadruple-precision floating-point values `a' and `b', one of
| which is a NaN, and returns the appropriate NaN result.  If either `a' or
| `b' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/

static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
{
782 783
    flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
    flag aIsLargerSignificand;
B
bellard 已提交
784

785
    aIsQuietNaN = float128_is_quiet_nan( a );
B
bellard 已提交
786
    aIsSignalingNaN = float128_is_signaling_nan( a );
787
    bIsQuietNaN = float128_is_quiet_nan( b );
B
bellard 已提交
788
    bIsSignalingNaN = float128_is_signaling_nan( b );
789

B
bellard 已提交
790
    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
791

A
Aurelien Jarno 已提交
792 793 794 795 796 797
    if ( STATUS(default_nan_mode) ) {
        a.low = float128_default_nan_low;
        a.high = float128_default_nan_high;
        return a;
    }

798 799 800 801 802 803
    if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
        aIsLargerSignificand = 0;
    } else if (lt128(b.high<<1, b.low, a.high<<1, a.low)) {
        aIsLargerSignificand = 1;
    } else {
        aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
B
bellard 已提交
804
    }
805

806
    if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
807
                aIsLargerSignificand)) {
808
        return float128_maybe_silence_nan(b);
809
    } else {
810
        return float128_maybe_silence_nan(a);
B
bellard 已提交
811 812 813 814
    }
}

#endif