qemu/fpu/softfloat-specialize.h
<<
>>
Prefs
   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
  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
  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{
  48    STATUS(float_exception_flags) |= flags;
  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*----------------------------------------------------------------------------*/
  62#if defined(TARGET_SPARC)
  63#define float32_default_nan make_float32(0x7FFFFFFF)
  64#elif defined(TARGET_POWERPC) || defined(TARGET_ARM)
  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
  73
  74/*----------------------------------------------------------------------------
  75| Returns 1 if the single-precision floating-point value `a' is a quiet
  76| NaN; otherwise returns 0.
  77*----------------------------------------------------------------------------*/
  78
  79int float32_is_nan( float32 a_ )
  80{
  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
  87}
  88
  89/*----------------------------------------------------------------------------
  90| Returns 1 if the single-precision floating-point value `a' is a signaling
  91| NaN; otherwise returns 0.
  92*----------------------------------------------------------------------------*/
  93
  94int float32_is_signaling_nan( float32 a_ )
  95{
  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
 102}
 103
 104/*----------------------------------------------------------------------------
 105| Returns the result of converting the single-precision floating-point NaN
 106| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 107| exception is raised.
 108*----------------------------------------------------------------------------*/
 109
 110static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
 111{
 112    commonNaNT z;
 113
 114    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
 115    z.sign = float32_val(a)>>31;
 116    z.low = 0;
 117    z.high = ( (bits64) float32_val(a) )<<41;
 118    return z;
 119}
 120
 121/*----------------------------------------------------------------------------
 122| Returns the result of converting the canonical NaN `a' to the single-
 123| precision floating-point format.
 124*----------------------------------------------------------------------------*/
 125
 126static float32 commonNaNToFloat32( commonNaNT a )
 127{
 128    bits32 mantissa = a.high>>41;
 129    if ( mantissa )
 130        return make_float32(
 131            ( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
 132    else
 133        return float32_default_nan;
 134}
 135
 136/*----------------------------------------------------------------------------
 137| Takes two single-precision floating-point values `a' and `b', one of which
 138| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
 139| signaling NaN, the invalid exception is raised.
 140*----------------------------------------------------------------------------*/
 141
 142static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
 143{
 144    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
 145    bits32 av, bv, res;
 146
 147    if ( STATUS(default_nan_mode) )
 148        return float32_default_nan;
 149
 150    aIsNaN = float32_is_nan( a );
 151    aIsSignalingNaN = float32_is_signaling_nan( a );
 152    bIsNaN = float32_is_nan( b );
 153    bIsSignalingNaN = float32_is_signaling_nan( b );
 154    av = float32_val(a);
 155    bv = float32_val(b);
 156#if SNAN_BIT_IS_ONE
 157    av &= ~0x00400000;
 158    bv &= ~0x00400000;
 159#else
 160    av |= 0x00400000;
 161    bv |= 0x00400000;
 162#endif
 163    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 164    if ( aIsSignalingNaN ) {
 165        if ( bIsSignalingNaN ) goto returnLargerSignificand;
 166        res = bIsNaN ? bv : av;
 167    }
 168    else if ( aIsNaN ) {
 169        if ( bIsSignalingNaN | ! bIsNaN )
 170            res = av;
 171        else {
 172 returnLargerSignificand:
 173            if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
 174                res = bv;
 175            else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
 176                res = av;
 177            else
 178                res = ( av < bv ) ? av : bv;
 179        }
 180    }
 181    else {
 182        res = bv;
 183    }
 184    return make_float32(res);
 185}
 186
 187/*----------------------------------------------------------------------------
 188| The pattern for a default generated double-precision NaN.
 189*----------------------------------------------------------------------------*/
 190#if defined(TARGET_SPARC)
 191#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
 192#elif defined(TARGET_POWERPC) || defined(TARGET_ARM)
 193#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
 194#elif defined(TARGET_HPPA)
 195#define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
 196#elif SNAN_BIT_IS_ONE
 197#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
 198#else
 199#define float64_default_nan make_float64(LIT64( 0xFFF8000000000000 ))
 200#endif
 201
 202/*----------------------------------------------------------------------------
 203| Returns 1 if the double-precision floating-point value `a' is a quiet
 204| NaN; otherwise returns 0.
 205*----------------------------------------------------------------------------*/
 206
 207int float64_is_nan( float64 a_ )
 208{
 209    bits64 a = float64_val(a_);
 210#if SNAN_BIT_IS_ONE
 211    return
 212           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
 213        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
 214#else
 215    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
 216#endif
 217}
 218
 219/*----------------------------------------------------------------------------
 220| Returns 1 if the double-precision floating-point value `a' is a signaling
 221| NaN; otherwise returns 0.
 222*----------------------------------------------------------------------------*/
 223
 224int float64_is_signaling_nan( float64 a_ )
 225{
 226    bits64 a = float64_val(a_);
 227#if SNAN_BIT_IS_ONE
 228    return ( LIT64( 0xFFF0000000000000 ) <= (bits64) ( a<<1 ) );
 229#else
 230    return
 231           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
 232        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
 233#endif
 234}
 235
 236/*----------------------------------------------------------------------------
 237| Returns the result of converting the double-precision floating-point NaN
 238| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 239| exception is raised.
 240*----------------------------------------------------------------------------*/
 241
 242static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
 243{
 244    commonNaNT z;
 245
 246    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
 247    z.sign = float64_val(a)>>63;
 248    z.low = 0;
 249    z.high = float64_val(a)<<12;
 250    return z;
 251}
 252
 253/*----------------------------------------------------------------------------
 254| Returns the result of converting the canonical NaN `a' to the double-
 255| precision floating-point format.
 256*----------------------------------------------------------------------------*/
 257
 258static float64 commonNaNToFloat64( commonNaNT a )
 259{
 260    bits64 mantissa = a.high>>12;
 261
 262    if ( mantissa )
 263        return make_float64(
 264              ( ( (bits64) a.sign )<<63 )
 265            | LIT64( 0x7FF0000000000000 )
 266            | ( a.high>>12 ));
 267    else
 268        return float64_default_nan;
 269}
 270
 271/*----------------------------------------------------------------------------
 272| Takes two double-precision floating-point values `a' and `b', one of which
 273| is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
 274| signaling NaN, the invalid exception is raised.
 275*----------------------------------------------------------------------------*/
 276
 277static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
 278{
 279    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
 280    bits64 av, bv, res;
 281
 282    if ( STATUS(default_nan_mode) )
 283        return float64_default_nan;
 284
 285    aIsNaN = float64_is_nan( a );
 286    aIsSignalingNaN = float64_is_signaling_nan( a );
 287    bIsNaN = float64_is_nan( b );
 288    bIsSignalingNaN = float64_is_signaling_nan( b );
 289    av = float64_val(a);
 290    bv = float64_val(b);
 291#if SNAN_BIT_IS_ONE
 292    av &= ~LIT64( 0x0008000000000000 );
 293    bv &= ~LIT64( 0x0008000000000000 );
 294#else
 295    av |= LIT64( 0x0008000000000000 );
 296    bv |= LIT64( 0x0008000000000000 );
 297#endif
 298    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 299    if ( aIsSignalingNaN ) {
 300        if ( bIsSignalingNaN ) goto returnLargerSignificand;
 301        res = bIsNaN ? bv : av;
 302    }
 303    else if ( aIsNaN ) {
 304        if ( bIsSignalingNaN | ! bIsNaN )
 305            res = av;
 306        else {
 307 returnLargerSignificand:
 308            if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
 309                res = bv;
 310            else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
 311                res = av;
 312            else
 313                res = ( av < bv ) ? av : bv;
 314        }
 315    }
 316    else {
 317        res = bv;
 318    }
 319    return make_float64(res);
 320}
 321
 322#ifdef FLOATX80
 323
 324/*----------------------------------------------------------------------------
 325| The pattern for a default generated extended double-precision NaN.  The
 326| `high' and `low' values hold the most- and least-significant bits,
 327| respectively.
 328*----------------------------------------------------------------------------*/
 329#if SNAN_BIT_IS_ONE
 330#define floatx80_default_nan_high 0x7FFF
 331#define floatx80_default_nan_low  LIT64( 0xBFFFFFFFFFFFFFFF )
 332#else
 333#define floatx80_default_nan_high 0xFFFF
 334#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
 335#endif
 336
 337/*----------------------------------------------------------------------------
 338| Returns 1 if the extended double-precision floating-point value `a' is a
 339| quiet NaN; otherwise returns 0.
 340*----------------------------------------------------------------------------*/
 341
 342int floatx80_is_nan( floatx80 a )
 343{
 344#if SNAN_BIT_IS_ONE
 345    bits64 aLow;
 346
 347    aLow = a.low & ~ LIT64( 0x4000000000000000 );
 348    return
 349           ( ( a.high & 0x7FFF ) == 0x7FFF )
 350        && (bits64) ( aLow<<1 )
 351        && ( a.low == aLow );
 352#else
 353    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
 354#endif
 355}
 356
 357/*----------------------------------------------------------------------------
 358| Returns 1 if the extended double-precision floating-point value `a' is a
 359| signaling NaN; otherwise returns 0.
 360*----------------------------------------------------------------------------*/
 361
 362int floatx80_is_signaling_nan( floatx80 a )
 363{
 364#if SNAN_BIT_IS_ONE
 365    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
 366#else
 367    bits64 aLow;
 368
 369    aLow = a.low & ~ LIT64( 0x4000000000000000 );
 370    return
 371           ( ( a.high & 0x7FFF ) == 0x7FFF )
 372        && (bits64) ( aLow<<1 )
 373        && ( a.low == aLow );
 374#endif
 375}
 376
 377/*----------------------------------------------------------------------------
 378| Returns the result of converting the extended double-precision floating-
 379| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
 380| invalid exception is raised.
 381*----------------------------------------------------------------------------*/
 382
 383static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
 384{
 385    commonNaNT z;
 386
 387    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
 388    z.sign = a.high>>15;
 389    z.low = 0;
 390    z.high = a.low;
 391    return z;
 392}
 393
 394/*----------------------------------------------------------------------------
 395| Returns the result of converting the canonical NaN `a' to the extended
 396| double-precision floating-point format.
 397*----------------------------------------------------------------------------*/
 398
 399static floatx80 commonNaNToFloatx80( commonNaNT a )
 400{
 401    floatx80 z;
 402
 403    if (a.high)
 404        z.low = a.high;
 405    else
 406        z.low = floatx80_default_nan_low;
 407    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
 408    return z;
 409}
 410
 411/*----------------------------------------------------------------------------
 412| Takes two extended double-precision floating-point values `a' and `b', one
 413| of which is a NaN, and returns the appropriate NaN result.  If either `a' or
 414| `b' is a signaling NaN, the invalid exception is raised.
 415*----------------------------------------------------------------------------*/
 416
 417static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
 418{
 419    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
 420
 421    if ( STATUS(default_nan_mode) ) {
 422        a.low = floatx80_default_nan_low;
 423        a.high = floatx80_default_nan_high;
 424        return a;
 425    }
 426
 427    aIsNaN = floatx80_is_nan( a );
 428    aIsSignalingNaN = floatx80_is_signaling_nan( a );
 429    bIsNaN = floatx80_is_nan( b );
 430    bIsSignalingNaN = floatx80_is_signaling_nan( b );
 431#if SNAN_BIT_IS_ONE
 432    a.low &= ~LIT64( 0xC000000000000000 );
 433    b.low &= ~LIT64( 0xC000000000000000 );
 434#else
 435    a.low |= LIT64( 0xC000000000000000 );
 436    b.low |= LIT64( 0xC000000000000000 );
 437#endif
 438    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 439    if ( aIsSignalingNaN ) {
 440        if ( bIsSignalingNaN ) goto returnLargerSignificand;
 441        return bIsNaN ? b : a;
 442    }
 443    else if ( aIsNaN ) {
 444        if ( bIsSignalingNaN | ! bIsNaN ) return a;
 445 returnLargerSignificand:
 446        if ( a.low < b.low ) return b;
 447        if ( b.low < a.low ) return a;
 448        return ( a.high < b.high ) ? a : b;
 449    }
 450    else {
 451        return b;
 452    }
 453}
 454
 455#endif
 456
 457#ifdef FLOAT128
 458
 459/*----------------------------------------------------------------------------
 460| The pattern for a default generated quadruple-precision NaN.  The `high' and
 461| `low' values hold the most- and least-significant bits, respectively.
 462*----------------------------------------------------------------------------*/
 463#if SNAN_BIT_IS_ONE
 464#define float128_default_nan_high LIT64( 0x7FFF7FFFFFFFFFFF )
 465#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
 466#else
 467#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
 468#define float128_default_nan_low  LIT64( 0x0000000000000000 )
 469#endif
 470
 471/*----------------------------------------------------------------------------
 472| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
 473| NaN; otherwise returns 0.
 474*----------------------------------------------------------------------------*/
 475
 476int float128_is_nan( float128 a )
 477{
 478#if SNAN_BIT_IS_ONE
 479    return
 480           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
 481        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
 482#else
 483    return
 484           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
 485        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
 486#endif
 487}
 488
 489/*----------------------------------------------------------------------------
 490| Returns 1 if the quadruple-precision floating-point value `a' is a
 491| signaling NaN; otherwise returns 0.
 492*----------------------------------------------------------------------------*/
 493
 494int float128_is_signaling_nan( float128 a )
 495{
 496#if SNAN_BIT_IS_ONE
 497    return
 498           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
 499        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
 500#else
 501    return
 502           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
 503        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
 504#endif
 505}
 506
 507/*----------------------------------------------------------------------------
 508| Returns the result of converting the quadruple-precision floating-point NaN
 509| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
 510| exception is raised.
 511*----------------------------------------------------------------------------*/
 512
 513static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
 514{
 515    commonNaNT z;
 516
 517    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR);
 518    z.sign = a.high>>63;
 519    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
 520    return z;
 521}
 522
 523/*----------------------------------------------------------------------------
 524| Returns the result of converting the canonical NaN `a' to the quadruple-
 525| precision floating-point format.
 526*----------------------------------------------------------------------------*/
 527
 528static float128 commonNaNToFloat128( commonNaNT a )
 529{
 530    float128 z;
 531
 532    shift128Right( a.high, a.low, 16, &z.high, &z.low );
 533    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
 534    return z;
 535}
 536
 537/*----------------------------------------------------------------------------
 538| Takes two quadruple-precision floating-point values `a' and `b', one of
 539| which is a NaN, and returns the appropriate NaN result.  If either `a' or
 540| `b' is a signaling NaN, the invalid exception is raised.
 541*----------------------------------------------------------------------------*/
 542
 543static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
 544{
 545    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
 546
 547    if ( STATUS(default_nan_mode) ) {
 548        a.low = float128_default_nan_low;
 549        a.high = float128_default_nan_high;
 550        return a;
 551    }
 552
 553    aIsNaN = float128_is_nan( a );
 554    aIsSignalingNaN = float128_is_signaling_nan( a );
 555    bIsNaN = float128_is_nan( b );
 556    bIsSignalingNaN = float128_is_signaling_nan( b );
 557#if SNAN_BIT_IS_ONE
 558    a.high &= ~LIT64( 0x0000800000000000 );
 559    b.high &= ~LIT64( 0x0000800000000000 );
 560#else
 561    a.high |= LIT64( 0x0000800000000000 );
 562    b.high |= LIT64( 0x0000800000000000 );
 563#endif
 564    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
 565    if ( aIsSignalingNaN ) {
 566        if ( bIsSignalingNaN ) goto returnLargerSignificand;
 567        return bIsNaN ? b : a;
 568    }
 569    else if ( aIsNaN ) {
 570        if ( bIsSignalingNaN | ! bIsNaN ) return a;
 571 returnLargerSignificand:
 572        if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
 573        if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
 574        return ( a.high < b.high ) ? a : b;
 575    }
 576    else {
 577        return b;
 578    }
 579}
 580
 581#endif
 582