|
|
1.1 ! root 1: ! 2: /*============================================================================ ! 3: ! 4: This C source file is an extension to the SoftFloat IEC/IEEE Floating-point ! 5: Arithmetic Package, Release 2a. ! 6: ! 7: =============================================================================*/ ! 8: ! 9: #include "softfloat.h" ! 10: ! 11: /*---------------------------------------------------------------------------- ! 12: | Methods for detecting special conditions for mathematical functions ! 13: | supported by MC68881 and MC68862 mathematical coprocessor. ! 14: *----------------------------------------------------------------------------*/ ! 15: ! 16: #define pi_sig0 LIT64(0xc90fdaa22168c234) ! 17: #define pi_sig1 LIT64(0xc4c6628b80dc1cd1) ! 18: ! 19: #define pi_exp 0x4000 ! 20: #define piby2_exp 0x3FFF ! 21: #define piby4_exp 0x3FFE ! 22: ! 23: #define one_exp 0x3FFF ! 24: #define one_sig LIT64(0x8000000000000000) ! 25: ! 26: /*---------------------------------------------------------------------------- ! 27: | Arc cosine ! 28: *----------------------------------------------------------------------------*/ ! 29: ! 30: floatx80 floatx80_acos_check(floatx80 a, flag *e) ! 31: { ! 32: flag aSign; ! 33: int32 aExp; ! 34: bits64 aSig; ! 35: ! 36: *e = 1; ! 37: ! 38: aSig = extractFloatx80Frac(a); ! 39: aExp = extractFloatx80Exp(a); ! 40: aSign = extractFloatx80Sign(a); ! 41: ! 42: if (aExp == 0x7FFF && (bits64) (aSig<<1)) { ! 43: return propagateFloatx80NaNOneArg(a); ! 44: } ! 45: ! 46: if (aExp > one_exp || (aExp == one_exp && aSig > one_sig)) { ! 47: float_raise(float_flag_invalid); ! 48: a.low = floatx80_default_nan_low; ! 49: a.high = floatx80_default_nan_high; ! 50: return a; ! 51: } ! 52: ! 53: if (aExp == 0) { ! 54: if (aSig == 0) return roundAndPackFloatx80(floatx80_rounding_precision, ! 55: 0, piby2_exp, pi_sig0, pi_sig1); ! 56: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 57: } ! 58: ! 59: *e = 0; ! 60: return a; ! 61: } ! 62: ! 63: /*---------------------------------------------------------------------------- ! 64: | Arc sine ! 65: *----------------------------------------------------------------------------*/ ! 66: ! 67: floatx80 floatx80_asin_check(floatx80 a, flag *e) ! 68: { ! 69: flag aSign; ! 70: int32 aExp; ! 71: bits64 aSig; ! 72: ! 73: *e = 1; ! 74: ! 75: aSig = extractFloatx80Frac(a); ! 76: aExp = extractFloatx80Exp(a); ! 77: aSign = extractFloatx80Sign(a); ! 78: ! 79: if (aExp == 0x7FFF && (bits64) (aSig<<1)) { ! 80: return propagateFloatx80NaNOneArg(a); ! 81: } ! 82: ! 83: if (aExp > one_exp || (aExp == one_exp && aSig > one_sig)) { ! 84: float_raise(float_flag_invalid); ! 85: a.low = floatx80_default_nan_low; ! 86: a.high = floatx80_default_nan_high; ! 87: return a; ! 88: } ! 89: ! 90: if (aExp == 0) { ! 91: if (aSig == 0) return packFloatx80(aSign, 0, 0); ! 92: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 93: } ! 94: ! 95: *e = 0; ! 96: return a; ! 97: } ! 98: ! 99: /*---------------------------------------------------------------------------- ! 100: | Arc tangent ! 101: *----------------------------------------------------------------------------*/ ! 102: ! 103: floatx80 floatx80_atan_check(floatx80 a, flag *e) ! 104: { ! 105: flag aSign; ! 106: int32 aExp; ! 107: bits64 aSig; ! 108: ! 109: *e = 1; ! 110: ! 111: aSig = extractFloatx80Frac(a); ! 112: aExp = extractFloatx80Exp(a); ! 113: aSign = extractFloatx80Sign(a); ! 114: ! 115: if (aExp == 0x7FFF) { ! 116: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 117: return roundAndPackFloatx80(floatx80_rounding_precision, ! 118: aSign, piby2_exp, pi_sig0, pi_sig1); ! 119: } ! 120: ! 121: if (aExp == 0) { ! 122: if (aSig == 0) return packFloatx80(aSign, 0, 0); ! 123: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 124: } ! 125: ! 126: *e = 0; ! 127: return a; ! 128: } ! 129: ! 130: /*---------------------------------------------------------------------------- ! 131: | Hyperbolic arc tangent ! 132: *----------------------------------------------------------------------------*/ ! 133: ! 134: floatx80 floatx80_atanh_check(floatx80 a, flag *e) ! 135: { ! 136: flag aSign; ! 137: int32 aExp; ! 138: bits64 aSig; ! 139: ! 140: *e = 1; ! 141: ! 142: aSig = extractFloatx80Frac(a); ! 143: aExp = extractFloatx80Exp(a); ! 144: aSign = extractFloatx80Sign(a); ! 145: ! 146: if (aExp == 0x7FFF && (bits64) (aSig<<1)) { ! 147: return propagateFloatx80NaNOneArg(a); ! 148: } ! 149: ! 150: if (aExp >= one_exp) { ! 151: if (aExp == one_exp && aSig == one_sig) { ! 152: float_raise(float_flag_divbyzero); ! 153: packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); ! 154: } ! 155: float_raise(float_flag_invalid); ! 156: a.low = floatx80_default_nan_low; ! 157: a.high = floatx80_default_nan_high; ! 158: return a; ! 159: } ! 160: ! 161: if (aExp == 0) { ! 162: if (aSig == 0) return packFloatx80(aSign, 0, 0); ! 163: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 164: } ! 165: ! 166: *e = 0; ! 167: return a; ! 168: } ! 169: ! 170: /*---------------------------------------------------------------------------- ! 171: | Cosine ! 172: *----------------------------------------------------------------------------*/ ! 173: ! 174: floatx80 floatx80_cos_check(floatx80 a, flag *e) ! 175: { ! 176: flag aSign; ! 177: int32 aExp; ! 178: bits64 aSig; ! 179: ! 180: *e = 1; ! 181: ! 182: aSig = extractFloatx80Frac(a); ! 183: aExp = extractFloatx80Exp(a); ! 184: aSign = extractFloatx80Sign(a); ! 185: ! 186: if (aExp == 0x7FFF) { ! 187: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 188: float_raise(float_flag_invalid); ! 189: a.low = floatx80_default_nan_low; ! 190: a.high = floatx80_default_nan_high; ! 191: return a; ! 192: } ! 193: ! 194: if (aExp == 0) { ! 195: if (aSig == 0) return packFloatx80(0, one_exp, one_sig); ! 196: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 197: } ! 198: ! 199: *e = 0; ! 200: return a; ! 201: } ! 202: ! 203: /*---------------------------------------------------------------------------- ! 204: | Hyperbolic cosine ! 205: *----------------------------------------------------------------------------*/ ! 206: ! 207: floatx80 floatx80_cosh_check(floatx80 a, flag *e) ! 208: { ! 209: flag aSign; ! 210: int32 aExp; ! 211: bits64 aSig; ! 212: ! 213: *e = 1; ! 214: ! 215: aSig = extractFloatx80Frac(a); ! 216: aExp = extractFloatx80Exp(a); ! 217: aSign = extractFloatx80Sign(a); ! 218: ! 219: if (aExp == 0x7FFF) { ! 220: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 221: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 222: } ! 223: ! 224: if (aExp == 0) { ! 225: if (aSig == 0) return packFloatx80(0, one_exp, one_sig); ! 226: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 227: } ! 228: ! 229: *e = 0; ! 230: return a; ! 231: } ! 232: ! 233: /*---------------------------------------------------------------------------- ! 234: | e to x ! 235: *----------------------------------------------------------------------------*/ ! 236: ! 237: floatx80 floatx80_etox_check(floatx80 a, flag *e) ! 238: { ! 239: flag aSign; ! 240: int32 aExp; ! 241: bits64 aSig; ! 242: ! 243: *e = 1; ! 244: ! 245: aSig = extractFloatx80Frac(a); ! 246: aExp = extractFloatx80Exp(a); ! 247: aSign = extractFloatx80Sign(a); ! 248: ! 249: if (aExp == 0x7FFF) { ! 250: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 251: if (aSign) return packFloatx80(0, 0, 0); ! 252: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 253: } ! 254: ! 255: if (aExp == 0) { ! 256: if (aSig == 0) return packFloatx80(0, one_exp, one_sig); ! 257: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 258: } ! 259: ! 260: *e = 0; ! 261: return a; ! 262: } ! 263: ! 264: /*---------------------------------------------------------------------------- ! 265: | e to x minus 1 ! 266: *----------------------------------------------------------------------------*/ ! 267: ! 268: floatx80 floatx80_etoxm1_check(floatx80 a, flag *e) ! 269: { ! 270: flag aSign; ! 271: int32 aExp; ! 272: bits64 aSig; ! 273: ! 274: *e = 1; ! 275: ! 276: aSig = extractFloatx80Frac(a); ! 277: aExp = extractFloatx80Exp(a); ! 278: aSign = extractFloatx80Sign(a); ! 279: ! 280: if (aExp == 0x7FFF) { ! 281: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 282: if (aSign) return packFloatx80(aSign, one_exp, one_sig); ! 283: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 284: } ! 285: ! 286: if (aExp == 0) { ! 287: if (aSig == 0) return packFloatx80(aSign, 0, 0); ! 288: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 289: } ! 290: ! 291: *e = 0; ! 292: return a; ! 293: } ! 294: ! 295: /*---------------------------------------------------------------------------- ! 296: | Log base 10 ! 297: *----------------------------------------------------------------------------*/ ! 298: ! 299: floatx80 floatx80_log10_check(floatx80 a, flag *e) ! 300: { ! 301: flag aSign; ! 302: int32 aExp; ! 303: bits64 aSig; ! 304: ! 305: *e = 1; ! 306: ! 307: aSig = extractFloatx80Frac(a); ! 308: aExp = extractFloatx80Exp(a); ! 309: aSign = extractFloatx80Sign(a); ! 310: ! 311: if (aExp == 0x7FFF) { ! 312: if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a); ! 313: if (aSign == 0) ! 314: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 315: } ! 316: ! 317: if (aExp == 0) { ! 318: if (aSig == 0) { ! 319: float_raise(float_flag_divbyzero); ! 320: return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); ! 321: } ! 322: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 323: } ! 324: ! 325: if (aSign) { ! 326: float_raise(float_flag_invalid); ! 327: a.low = floatx80_default_nan_low; ! 328: a.high = floatx80_default_nan_high; ! 329: return a; ! 330: } ! 331: ! 332: *e = 0; ! 333: return a; ! 334: } ! 335: ! 336: /*---------------------------------------------------------------------------- ! 337: | Log base 2 ! 338: *----------------------------------------------------------------------------*/ ! 339: ! 340: floatx80 floatx80_log2_check(floatx80 a, flag *e) ! 341: { ! 342: flag aSign; ! 343: int32 aExp; ! 344: bits64 aSig; ! 345: ! 346: *e = 1; ! 347: ! 348: aSig = extractFloatx80Frac(a); ! 349: aExp = extractFloatx80Exp(a); ! 350: aSign = extractFloatx80Sign(a); ! 351: ! 352: if (aExp == 0x7FFF) { ! 353: if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a); ! 354: if (aSign == 0) ! 355: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 356: } ! 357: ! 358: if (aExp == 0) { ! 359: if (aSig == 0) { ! 360: float_raise(float_flag_divbyzero); ! 361: return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); ! 362: } ! 363: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 364: } ! 365: ! 366: if (aSign) { ! 367: float_raise(float_flag_invalid); ! 368: a.low = floatx80_default_nan_low; ! 369: a.high = floatx80_default_nan_high; ! 370: return a; ! 371: } ! 372: ! 373: *e = 0; ! 374: return a; ! 375: } ! 376: ! 377: /*---------------------------------------------------------------------------- ! 378: | Log base e ! 379: *----------------------------------------------------------------------------*/ ! 380: ! 381: floatx80 floatx80_logn_check(floatx80 a, flag *e) ! 382: { ! 383: flag aSign; ! 384: int32 aExp; ! 385: bits64 aSig; ! 386: ! 387: *e = 1; ! 388: ! 389: aSig = extractFloatx80Frac(a); ! 390: aExp = extractFloatx80Exp(a); ! 391: aSign = extractFloatx80Sign(a); ! 392: ! 393: if (aExp == 0x7FFF) { ! 394: if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a); ! 395: if (aSign == 0) ! 396: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 397: } ! 398: ! 399: if (aExp == 0) { ! 400: if (aSig == 0) { ! 401: float_raise(float_flag_divbyzero); ! 402: return packFloatx80(1, 0x7FFF, floatx80_default_infinity_low); ! 403: } ! 404: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 405: } ! 406: ! 407: if (aSign) { ! 408: float_raise(float_flag_invalid); ! 409: a.low = floatx80_default_nan_low; ! 410: a.high = floatx80_default_nan_high; ! 411: return a; ! 412: } ! 413: ! 414: *e = 0; ! 415: return a; ! 416: } ! 417: ! 418: /*---------------------------------------------------------------------------- ! 419: | Log base e of x plus 1 ! 420: *----------------------------------------------------------------------------*/ ! 421: ! 422: floatx80 floatx80_lognp1_check(floatx80 a, flag *e) ! 423: { ! 424: flag aSign; ! 425: int32 aExp; ! 426: bits64 aSig; ! 427: ! 428: *e = 1; ! 429: ! 430: aSig = extractFloatx80Frac(a); ! 431: aExp = extractFloatx80Exp(a); ! 432: aSign = extractFloatx80Sign(a); ! 433: ! 434: if (aExp == 0x7FFF) { ! 435: if ((bits64) (aSig<<1)) propagateFloatx80NaNOneArg(a); ! 436: if (aSign) { ! 437: float_raise(float_flag_invalid); ! 438: a.low = floatx80_default_nan_low; ! 439: a.high = floatx80_default_nan_high; ! 440: return a; ! 441: } ! 442: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 443: } ! 444: ! 445: if (aExp == 0) { ! 446: if (aSig == 0) return packFloatx80(aSign, 0, 0); ! 447: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 448: } ! 449: ! 450: if (aSign && aExp >= one_exp) { ! 451: if (aExp == one_exp && aSig == one_sig) { ! 452: float_raise(float_flag_divbyzero); ! 453: packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); /* NaN? */ ! 454: } ! 455: float_raise(float_flag_invalid); ! 456: a.low = floatx80_default_nan_low; ! 457: a.high = floatx80_default_nan_high; ! 458: return a; ! 459: } ! 460: ! 461: *e = 0; ! 462: return a; ! 463: } ! 464: ! 465: /*---------------------------------------------------------------------------- ! 466: | Sine ! 467: *----------------------------------------------------------------------------*/ ! 468: ! 469: floatx80 floatx80_sin_check(floatx80 a, flag *e) ! 470: { ! 471: flag aSign; ! 472: int32 aExp; ! 473: bits64 aSig; ! 474: ! 475: *e = 1; ! 476: ! 477: aSig = extractFloatx80Frac(a); ! 478: aExp = extractFloatx80Exp(a); ! 479: aSign = extractFloatx80Sign(a); ! 480: ! 481: if (aExp == 0x7FFF) { ! 482: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 483: float_raise(float_flag_invalid); ! 484: a.low = floatx80_default_nan_low; ! 485: a.high = floatx80_default_nan_high; ! 486: return a; ! 487: } ! 488: ! 489: if (aExp == 0) { ! 490: if (aSig == 0) return packFloatx80(aSign, 0, 0); ! 491: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 492: } ! 493: ! 494: *e = 0; ! 495: return a; ! 496: } ! 497: ! 498: /*---------------------------------------------------------------------------- ! 499: | Hyperbolic sine ! 500: *----------------------------------------------------------------------------*/ ! 501: ! 502: floatx80 floatx80_sinh_check(floatx80 a, flag *e) ! 503: { ! 504: flag aSign; ! 505: int32 aExp; ! 506: bits64 aSig; ! 507: ! 508: *e = 1; ! 509: ! 510: aSig = extractFloatx80Frac(a); ! 511: aExp = extractFloatx80Exp(a); ! 512: aSign = extractFloatx80Sign(a); ! 513: ! 514: if (aExp == 0x7FFF) { ! 515: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 516: return packFloatx80(aSign, 0x7FFF, floatx80_default_infinity_low); ! 517: } ! 518: ! 519: if (aExp == 0) { ! 520: if (aSig == 0) return packFloatx80(aSign, 0, 0); ! 521: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 522: } ! 523: ! 524: *e = 0; ! 525: return a; ! 526: } ! 527: ! 528: /*---------------------------------------------------------------------------- ! 529: | Tangent ! 530: *----------------------------------------------------------------------------*/ ! 531: ! 532: floatx80 floatx80_tan_check(floatx80 a, flag *e) ! 533: { ! 534: flag aSign; ! 535: int32 aExp; ! 536: bits64 aSig; ! 537: ! 538: *e = 1; ! 539: ! 540: aSig = extractFloatx80Frac(a); ! 541: aExp = extractFloatx80Exp(a); ! 542: aSign = extractFloatx80Sign(a); ! 543: ! 544: if (aExp == 0x7FFF) { ! 545: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 546: float_raise(float_flag_invalid); ! 547: a.low = floatx80_default_nan_low; ! 548: a.high = floatx80_default_nan_high; ! 549: return a; ! 550: } ! 551: ! 552: if (aExp == 0) { ! 553: if (aSig == 0) return packFloatx80(aSign, 0, 0); ! 554: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 555: } ! 556: ! 557: *e = 0; ! 558: return a; ! 559: } ! 560: ! 561: /*---------------------------------------------------------------------------- ! 562: | Hyperbolic tangent ! 563: *----------------------------------------------------------------------------*/ ! 564: ! 565: floatx80 floatx80_tanh_check(floatx80 a, flag *e) ! 566: { ! 567: flag aSign; ! 568: int32 aExp; ! 569: bits64 aSig; ! 570: ! 571: *e = 1; ! 572: ! 573: aSig = extractFloatx80Frac(a); ! 574: aExp = extractFloatx80Exp(a); ! 575: aSign = extractFloatx80Sign(a); ! 576: ! 577: if (aExp == 0x7FFF) { ! 578: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 579: return packFloatx80(aSign, one_exp, one_sig); ! 580: } ! 581: ! 582: if (aExp == 0) { ! 583: if (aSig == 0) return packFloatx80(aSign, 0, 0); ! 584: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 585: } ! 586: ! 587: *e = 0; ! 588: return a; ! 589: } ! 590: ! 591: /*---------------------------------------------------------------------------- ! 592: | 10 to x ! 593: *----------------------------------------------------------------------------*/ ! 594: ! 595: floatx80 floatx80_tentox_check(floatx80 a, flag *e) ! 596: { ! 597: flag aSign; ! 598: int32 aExp; ! 599: bits64 aSig; ! 600: ! 601: *e = 1; ! 602: ! 603: aSig = extractFloatx80Frac(a); ! 604: aExp = extractFloatx80Exp(a); ! 605: aSign = extractFloatx80Sign(a); ! 606: ! 607: if (aExp == 0x7FFF) { ! 608: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 609: if (aSign) return packFloatx80(0, 0, 0); ! 610: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 611: } ! 612: ! 613: if (aExp == 0) { ! 614: if (aSig == 0) return packFloatx80(0, one_exp, one_sig); ! 615: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 616: } ! 617: ! 618: *e = 0; ! 619: return a; ! 620: } ! 621: ! 622: /*---------------------------------------------------------------------------- ! 623: | 2 to x ! 624: *----------------------------------------------------------------------------*/ ! 625: ! 626: floatx80 floatx80_twotox_check(floatx80 a, flag *e) ! 627: { ! 628: flag aSign; ! 629: int32 aExp; ! 630: bits64 aSig; ! 631: ! 632: *e = 1; ! 633: ! 634: aSig = extractFloatx80Frac(a); ! 635: aExp = extractFloatx80Exp(a); ! 636: aSign = extractFloatx80Sign(a); ! 637: ! 638: if (aExp == 0x7FFF) { ! 639: if ((bits64) (aSig<<1)) return propagateFloatx80NaNOneArg(a); ! 640: if (aSign) return packFloatx80(0, 0, 0); ! 641: return packFloatx80(0, 0x7FFF, floatx80_default_infinity_low); ! 642: } ! 643: ! 644: if (aExp == 0) { ! 645: if (aSig == 0) return packFloatx80(0, one_exp, one_sig); ! 646: normalizeFloatx80Subnormal(aSig, &aExp, &aSig); ! 647: } ! 648: ! 649: *e = 0; ! 650: return a; ! 651: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.