|
|
1.1 ! root 1: ! 2: /*============================================================================ ! 3: ! 4: This C source fragment is part of the SoftFloat IEC/IEEE Floating-point ! 5: Arithmetic Package, Release 2b. ! 6: ! 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'. ! 16: ! 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. ! 25: ! 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. ! 30: ! 31: =============================================================================*/ ! 32: ! 33: /*---------------------------------------------------------------------------- ! 34: | Underflow tininess-detection mode, statically initialized to default value. ! 35: | (The declaration in `softfloat.h' must match the `int8' type here.) ! 36: *----------------------------------------------------------------------------*/ ! 37: int8 float_detect_tininess = float_tininess_before_rounding; ! 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 to ! 42: | substitute a result value. If traps are not implemented, this routine ! 43: | should be simply `float_exception_flags |= flags;'. ! 44: *----------------------------------------------------------------------------*/ ! 45: ! 46: void float_raise( int8 flags ) ! 47: { ! 48: ! 49: float_exception_flags |= flags; ! 50: ! 51: } ! 52: ! 53: #ifdef SOFTFLOAT_I860 ! 54: void float_raise2( int8 flags ) ! 55: { ! 56: ! 57: float_exception_flags2 |= flags; ! 58: ! 59: } ! 60: #endif ! 61: ! 62: /*---------------------------------------------------------------------------- ! 63: | Internal canonical NaN format. ! 64: *----------------------------------------------------------------------------*/ ! 65: typedef struct { ! 66: flag sign; ! 67: bits64 high, low; ! 68: } commonNaNT; ! 69: ! 70: /*---------------------------------------------------------------------------- ! 71: | Returns 1 if the single-precision floating-point value `a' is a NaN; ! 72: | otherwise returns 0. ! 73: *----------------------------------------------------------------------------*/ ! 74: ! 75: flag float32_is_nan( float32 a ) ! 76: { ! 77: ! 78: return ( 0xFF000000 < (bits32) ( a<<1 ) ); ! 79: ! 80: } ! 81: ! 82: /*---------------------------------------------------------------------------- ! 83: | Returns 1 if the single-precision floating-point value `a' is a signaling ! 84: | NaN; otherwise returns 0. ! 85: *----------------------------------------------------------------------------*/ ! 86: ! 87: flag float32_is_signaling_nan( float32 a ) ! 88: { ! 89: ! 90: return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); ! 91: ! 92: } ! 93: ! 94: /*---------------------------------------------------------------------------- ! 95: | Returns the result of converting the single-precision floating-point NaN ! 96: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid ! 97: | exception is raised. ! 98: *----------------------------------------------------------------------------*/ ! 99: ! 100: static commonNaNT float32ToCommonNaN( float32 a ) ! 101: { ! 102: commonNaNT z; ! 103: ! 104: #ifdef SOFTFLOAT_I860 ! 105: if ( float32_is_signaling_nan( a ) ) float_raise2( float_flag_signaling ); ! 106: #else ! 107: if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_signaling ); ! 108: #endif ! 109: z.sign = a>>31; ! 110: z.low = 0; ! 111: z.high = ( (bits64) a )<<41; ! 112: return z; ! 113: ! 114: } ! 115: ! 116: /*---------------------------------------------------------------------------- ! 117: | Returns the result of converting the canonical NaN `a' to the single- ! 118: | precision floating-point format. ! 119: *----------------------------------------------------------------------------*/ ! 120: ! 121: static float32 commonNaNToFloat32( commonNaNT a ) ! 122: { ! 123: ! 124: return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); ! 125: ! 126: } ! 127: ! 128: /*---------------------------------------------------------------------------- ! 129: | Takes two single-precision floating-point values `a' and `b', one of which ! 130: | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a ! 131: | signaling NaN, the invalid exception is raised. ! 132: *----------------------------------------------------------------------------*/ ! 133: ! 134: static float32 propagateFloat32NaN( float32 a, float32 b ) ! 135: { ! 136: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; ! 137: ! 138: aIsNaN = float32_is_nan( a ); ! 139: aIsSignalingNaN = float32_is_signaling_nan( a ); ! 140: bIsNaN = float32_is_nan( b ); ! 141: bIsSignalingNaN = float32_is_signaling_nan( b ); ! 142: a |= 0x00400000; ! 143: b |= 0x00400000; ! 144: #ifdef SOFTFLOAT_I860 ! 145: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise2( float_flag_signaling ); ! 146: #else ! 147: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling ); ! 148: #endif ! 149: if ( aIsNaN ) { ! 150: return ( aIsSignalingNaN & bIsNaN ) ? b : a; ! 151: } ! 152: else { ! 153: return b; ! 154: } ! 155: ! 156: } ! 157: ! 158: /*---------------------------------------------------------------------------- ! 159: | Returns 1 if the double-precision floating-point value `a' is a NaN; ! 160: | otherwise returns 0. ! 161: *----------------------------------------------------------------------------*/ ! 162: ! 163: flag float64_is_nan( float64 a ) ! 164: { ! 165: ! 166: return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); ! 167: ! 168: } ! 169: ! 170: /*---------------------------------------------------------------------------- ! 171: | Returns 1 if the double-precision floating-point value `a' is a signaling ! 172: | NaN; otherwise returns 0. ! 173: *----------------------------------------------------------------------------*/ ! 174: ! 175: flag float64_is_signaling_nan( float64 a ) ! 176: { ! 177: ! 178: return ! 179: ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) ! 180: && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); ! 181: ! 182: } ! 183: ! 184: /*---------------------------------------------------------------------------- ! 185: | Returns the result of converting the double-precision floating-point NaN ! 186: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid ! 187: | exception is raised. ! 188: *----------------------------------------------------------------------------*/ ! 189: ! 190: static commonNaNT float64ToCommonNaN( float64 a ) ! 191: { ! 192: commonNaNT z; ! 193: ! 194: #ifdef SOFTFLOAT_I860 ! 195: if ( float64_is_signaling_nan( a ) ) float_raise2( float_flag_signaling ); ! 196: #else ! 197: if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_signaling ); ! 198: #endif ! 199: z.sign = a>>63; ! 200: z.low = 0; ! 201: z.high = a<<12; ! 202: return z; ! 203: ! 204: } ! 205: ! 206: /*---------------------------------------------------------------------------- ! 207: | Returns the result of converting the canonical NaN `a' to the double- ! 208: | precision floating-point format. ! 209: *----------------------------------------------------------------------------*/ ! 210: ! 211: static float64 commonNaNToFloat64( commonNaNT a ) ! 212: { ! 213: ! 214: return ! 215: ( ( (bits64) a.sign )<<63 ) ! 216: | LIT64( 0x7FF8000000000000 ) ! 217: | ( a.high>>12 ); ! 218: ! 219: } ! 220: ! 221: /*---------------------------------------------------------------------------- ! 222: | Takes two double-precision floating-point values `a' and `b', one of which ! 223: | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a ! 224: | signaling NaN, the invalid exception is raised. ! 225: *----------------------------------------------------------------------------*/ ! 226: ! 227: static float64 propagateFloat64NaN( float64 a, float64 b ) ! 228: { ! 229: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; ! 230: ! 231: aIsNaN = float64_is_nan( a ); ! 232: aIsSignalingNaN = float64_is_signaling_nan( a ); ! 233: bIsNaN = float64_is_nan( b ); ! 234: bIsSignalingNaN = float64_is_signaling_nan( b ); ! 235: a |= LIT64( 0x0008000000000000 ); ! 236: b |= LIT64( 0x0008000000000000 ); ! 237: #ifdef SOFTFLOAT_I860 ! 238: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise2( float_flag_signaling ); ! 239: #else ! 240: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling ); ! 241: #endif ! 242: if ( aIsNaN ) { ! 243: return ( aIsSignalingNaN & bIsNaN ) ? b : a; ! 244: } ! 245: else { ! 246: return b; ! 247: } ! 248: ! 249: } ! 250: ! 251: #ifdef FLOATX80 ! 252: ! 253: /*---------------------------------------------------------------------------- ! 254: | Returns 1 if the extended double-precision floating-point value `a' is a ! 255: | NaN; otherwise returns 0. ! 256: *----------------------------------------------------------------------------*/ ! 257: ! 258: flag floatx80_is_nan( floatx80 a ) ! 259: { ! 260: ! 261: return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); ! 262: ! 263: } ! 264: ! 265: /*---------------------------------------------------------------------------- ! 266: | Returns 1 if the extended double-precision floating-point value `a' is a ! 267: | signaling NaN; otherwise returns 0. ! 268: *----------------------------------------------------------------------------*/ ! 269: ! 270: flag floatx80_is_signaling_nan( floatx80 a ) ! 271: { ! 272: bits64 aLow; ! 273: ! 274: aLow = a.low & ~ LIT64( 0x4000000000000000 ); ! 275: return ! 276: ( ( a.high & 0x7FFF ) == 0x7FFF ) ! 277: && (bits64) ( aLow<<1 ) ! 278: && ( a.low == aLow ); ! 279: ! 280: } ! 281: ! 282: #ifdef SOFTFLOAT_68K // 28-12-2016: Added for Previous: ! 283: ! 284: /*---------------------------------------------------------------------------- ! 285: | Returns 1 if the extended double-precision floating-point value `a' is ! 286: | zero; otherwise returns 0. ! 287: *----------------------------------------------------------------------------*/ ! 288: ! 289: flag floatx80_is_zero( floatx80 a ) ! 290: { ! 291: ! 292: return ( ( a.high & 0x7FFF ) < 0x7FFF ) && ( a.low == 0 ); ! 293: ! 294: } ! 295: ! 296: /*---------------------------------------------------------------------------- ! 297: | Returns 1 if the extended double-precision floating-point value `a' is ! 298: | infinity; otherwise returns 0. ! 299: *----------------------------------------------------------------------------*/ ! 300: ! 301: flag floatx80_is_infinity( floatx80 a ) ! 302: { ! 303: ! 304: return ( ( a.high & 0x7FFF ) == 0x7FFF ) && ( (bits64) ( a.low<<1 ) == 0 ); ! 305: ! 306: } ! 307: ! 308: /*---------------------------------------------------------------------------- ! 309: | Returns 1 if the extended double-precision floating-point value `a' is ! 310: | negative; otherwise returns 0. ! 311: *----------------------------------------------------------------------------*/ ! 312: ! 313: flag floatx80_is_negative( floatx80 a ) ! 314: { ! 315: ! 316: return ( ( a.high & 0x8000 ) == 0x8000 ); ! 317: ! 318: } ! 319: ! 320: /*---------------------------------------------------------------------------- ! 321: | Returns 1 if the extended double-precision floating-point value `a' is ! 322: | denormal; otherwise returns 0. ! 323: *----------------------------------------------------------------------------*/ ! 324: ! 325: flag floatx80_is_denormal( floatx80 a ) ! 326: { ! 327: ! 328: return ! 329: ( ( a.high & 0x7FFF ) == 0 ) ! 330: && ( (bits64) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x0000000000000000 ) ) ! 331: && (bits64) ( a.low<<1 ); ! 332: ! 333: } ! 334: ! 335: /*---------------------------------------------------------------------------- ! 336: | Returns 1 if the extended double-precision floating-point value `a' is ! 337: | unnormal; otherwise returns 0. ! 338: *----------------------------------------------------------------------------*/ ! 339: ! 340: flag floatx80_is_unnormal( floatx80 a ) ! 341: { ! 342: ! 343: return ! 344: ( ( a.high & 0x7FFF ) > 0 ) ! 345: && ( ( a.high & 0x7FFF ) < 0x7FFF) ! 346: && ( (bits64) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x0000000000000000 ) ); ! 347: ! 348: } ! 349: ! 350: /*---------------------------------------------------------------------------- ! 351: | Returns 1 if the extended double-precision floating-point value `a' is ! 352: | normal; otherwise returns 0. ! 353: *----------------------------------------------------------------------------*/ ! 354: ! 355: flag floatx80_is_normal( floatx80 a ) ! 356: { ! 357: ! 358: return ! 359: ( ( a.high & 0x7FFF ) < 0x7FFF ) ! 360: && ( (bits64) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x8000000000000000 ) ); ! 361: ! 362: } ! 363: ! 364: #endif // End of addition for Previous ! 365: ! 366: /*---------------------------------------------------------------------------- ! 367: | Returns the result of converting the extended double-precision floating- ! 368: | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the ! 369: | invalid exception is raised. ! 370: *----------------------------------------------------------------------------*/ ! 371: ! 372: static commonNaNT floatx80ToCommonNaN( floatx80 a ) ! 373: { ! 374: commonNaNT z; ! 375: ! 376: if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_signaling ); ! 377: z.sign = a.high>>15; ! 378: z.low = 0; ! 379: z.high = a.low<<1; ! 380: return z; ! 381: ! 382: } ! 383: ! 384: /*---------------------------------------------------------------------------- ! 385: | Returns the result of converting the canonical NaN `a' to the extended ! 386: | double-precision floating-point format. ! 387: *----------------------------------------------------------------------------*/ ! 388: ! 389: static floatx80 commonNaNToFloatx80( commonNaNT a ) ! 390: { ! 391: floatx80 z; ! 392: #ifdef SOFTFLOAT_68K ! 393: z.low = LIT64( 0x4000000000000000 ) | ( a.high>>1 ); ! 394: #else ! 395: z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); ! 396: #endif ! 397: z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; ! 398: return z; ! 399: ! 400: } ! 401: ! 402: /*---------------------------------------------------------------------------- ! 403: | Takes two extended double-precision floating-point values `a' and `b', one ! 404: | of which is a NaN, and returns the appropriate NaN result. If either `a' or ! 405: | `b' is a signaling NaN, the invalid exception is raised. ! 406: *----------------------------------------------------------------------------*/ ! 407: ! 408: floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) ! 409: { ! 410: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; ! 411: ! 412: aIsNaN = floatx80_is_nan( a ); ! 413: aIsSignalingNaN = floatx80_is_signaling_nan( a ); ! 414: bIsNaN = floatx80_is_nan( b ); ! 415: bIsSignalingNaN = floatx80_is_signaling_nan( b ); ! 416: #ifdef SOFTFLOAT_68K ! 417: a.low |= LIT64( 0x4000000000000000 ); ! 418: b.low |= LIT64( 0x4000000000000000 ); ! 419: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling ); ! 420: return aIsNaN ? a : b; ! 421: #else ! 422: a.low |= LIT64( 0xC000000000000000 ); ! 423: b.low |= LIT64( 0xC000000000000000 ); ! 424: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling ); ! 425: if ( aIsNaN ) { ! 426: return ( aIsSignalingNaN & bIsNaN ) ? b : a; ! 427: } ! 428: else { ! 429: return b; ! 430: } ! 431: #endif ! 432: ! 433: } ! 434: ! 435: #ifdef SOFTFLOAT_68K ! 436: /*---------------------------------------------------------------------------- ! 437: | Takes extended double-precision floating-point NaN `a' and returns the ! 438: | appropriate NaN result. If `a' is a signaling NaN, the invalid exception ! 439: | is raised. ! 440: *----------------------------------------------------------------------------*/ ! 441: ! 442: floatx80 propagateFloatx80NaNOneArg(floatx80 a) ! 443: { ! 444: if ( floatx80_is_signaling_nan( a ) ) ! 445: float_raise( float_flag_signaling ); ! 446: ! 447: a.low |= LIT64( 0x4000000000000000 ); ! 448: ! 449: return a; ! 450: } ! 451: #endif ! 452: ! 453: #define EXP_BIAS 0x3FFF ! 454: ! 455: /*---------------------------------------------------------------------------- ! 456: | Returns the fraction bits of the extended double-precision floating-point ! 457: | value `a'. ! 458: *----------------------------------------------------------------------------*/ ! 459: ! 460: bits64 extractFloatx80Frac( floatx80 a ) ! 461: { ! 462: ! 463: return a.low; ! 464: ! 465: } ! 466: ! 467: /*---------------------------------------------------------------------------- ! 468: | Returns the exponent bits of the extended double-precision floating-point ! 469: | value `a'. ! 470: *----------------------------------------------------------------------------*/ ! 471: ! 472: int32 extractFloatx80Exp( floatx80 a ) ! 473: { ! 474: ! 475: return a.high & 0x7FFF; ! 476: ! 477: } ! 478: ! 479: /*---------------------------------------------------------------------------- ! 480: | Returns the sign bit of the extended double-precision floating-point value ! 481: | `a'. ! 482: *----------------------------------------------------------------------------*/ ! 483: ! 484: flag extractFloatx80Sign( floatx80 a ) ! 485: { ! 486: ! 487: return a.high>>15; ! 488: ! 489: } ! 490: ! 491: #endif ! 492: ! 493: #ifdef FLOAT128 ! 494: ! 495: /*---------------------------------------------------------------------------- ! 496: | Returns 1 if the quadruple-precision floating-point value `a' is a NaN; ! 497: | otherwise returns 0. ! 498: *----------------------------------------------------------------------------*/ ! 499: ! 500: flag float128_is_nan( float128 a ) ! 501: { ! 502: ! 503: return ! 504: ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) ! 505: && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); ! 506: ! 507: } ! 508: ! 509: /*---------------------------------------------------------------------------- ! 510: | Returns 1 if the quadruple-precision floating-point value `a' is a ! 511: | signaling NaN; otherwise returns 0. ! 512: *----------------------------------------------------------------------------*/ ! 513: ! 514: flag float128_is_signaling_nan( float128 a ) ! 515: { ! 516: ! 517: return ! 518: ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) ! 519: && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); ! 520: ! 521: } ! 522: ! 523: /*---------------------------------------------------------------------------- ! 524: | Returns the result of converting the quadruple-precision floating-point NaN ! 525: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid ! 526: | exception is raised. ! 527: *----------------------------------------------------------------------------*/ ! 528: ! 529: static commonNaNT float128ToCommonNaN( float128 a ) ! 530: { ! 531: commonNaNT z; ! 532: ! 533: if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_signaling ); ! 534: z.sign = a.high>>63; ! 535: shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); ! 536: return z; ! 537: ! 538: } ! 539: ! 540: /*---------------------------------------------------------------------------- ! 541: | Returns the result of converting the canonical NaN `a' to the quadruple- ! 542: | precision floating-point format. ! 543: *----------------------------------------------------------------------------*/ ! 544: ! 545: static float128 commonNaNToFloat128( commonNaNT a ) ! 546: { ! 547: float128 z; ! 548: ! 549: shift128Right( a.high, a.low, 16, &z.high, &z.low ); ! 550: z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); ! 551: return z; ! 552: ! 553: } ! 554: ! 555: /*---------------------------------------------------------------------------- ! 556: | Takes two quadruple-precision floating-point values `a' and `b', one of ! 557: | which is a NaN, and returns the appropriate NaN result. If either `a' or ! 558: | `b' is a signaling NaN, the invalid exception is raised. ! 559: *----------------------------------------------------------------------------*/ ! 560: ! 561: static float128 propagateFloat128NaN( float128 a, float128 b ) ! 562: { ! 563: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; ! 564: ! 565: aIsNaN = float128_is_nan( a ); ! 566: aIsSignalingNaN = float128_is_signaling_nan( a ); ! 567: bIsNaN = float128_is_nan( b ); ! 568: bIsSignalingNaN = float128_is_signaling_nan( b ); ! 569: a.high |= LIT64( 0x0000800000000000 ); ! 570: b.high |= LIT64( 0x0000800000000000 ); ! 571: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling ); ! 572: if ( aIsNaN ) { ! 573: return ( aIsSignalingNaN & bIsNaN ) ? b : a; ! 574: } ! 575: else { ! 576: return b; ! 577: } ! 578: ! 579: } ! 580: ! 581: #endif ! 582:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.