|
|
1.1 ! root 1: /* ! 2: ** libgcc support for software floating point. ! 3: ** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved. ! 4: ** Permission is granted to do *anything* you want with this file, ! 5: ** commercial or otherwise, provided this message remains intact. So there! ! 6: ** I would appreciate receiving any updates/patches/changes that anyone ! 7: ** makes, and am willing to be the repository for said changes (am I ! 8: ** making a big mistake?). ! 9: ! 10: Warning! Only single-precision is actually implemented. This file ! 11: won't really be much use until double-precision is supported. ! 12: ! 13: However, once that is done, this file might eventually become a ! 14: replacement for libgcc1.c. It might also make possible ! 15: cross-compilation for an IEEE target machine from a non-IEEE ! 16: host such as a VAX. ! 17: ! 18: If you'd like to work on completing this, please talk to [email protected]. ! 19: ! 20: ! 21: ** ! 22: ** Pat Wood ! 23: ** Pipeline Associates, Inc. ! 24: ** [email protected] or ! 25: ** sun!pipeline!phw or ! 26: ** uunet!motown!pipeline!phw ! 27: ** ! 28: ** 05/01/91 -- V1.0 -- first release to gcc mailing lists ! 29: ** 05/04/91 -- V1.1 -- added float and double prototypes and return values ! 30: ** -- fixed problems with adding and subtracting zero ! 31: ** -- fixed rounding in truncdfsf2 ! 32: ** -- fixed SWAP define and tested on 386 ! 33: */ ! 34: ! 35: /* ! 36: ** The following are routines that replace the libgcc soft floating point ! 37: ** routines that are called automatically when -msoft-float is selected. ! 38: ** The support single and double precision IEEE format, with provisions ! 39: ** for byte-swapped machines (tested on 386). Some of the double-precision ! 40: ** routines work at full precision, but most of the hard ones simply punt ! 41: ** and call the single precision routines, producing a loss of accuracy. ! 42: ** long long support is not assumed or included. ! 43: ** Overall accuracy is close to IEEE (actually 68882) for single-precision ! 44: ** arithmetic. I think there may still be a 1 in 1000 chance of a bit ! 45: ** being rounded the wrong way during a multiply. I'm not fussy enough to ! 46: ** bother with it, but if anyone is, knock yourself out. ! 47: ** ! 48: ** Efficiency has only been addressed where it was obvious that something ! 49: ** would make a big difference. Anyone who wants to do this right for ! 50: ** best speed should go in and rewrite in assembler. ! 51: ** ! 52: ** I have tested this only on a 68030 workstation and 386/ix integrated ! 53: ** in with -msoft-float. ! 54: */ ! 55: ! 56: /* the following deal with IEEE single-precision numbers */ ! 57: #define EXCESS 126 ! 58: #define SIGNBIT 0x80000000 ! 59: #define HIDDEN (1 << 23) ! 60: #define SIGN(fp) ((fp) & SIGNBIT) ! 61: #define EXP(fp) (((fp) >> 23) & 0xFF) ! 62: #define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN) ! 63: #define PACK(s,e,m) ((s) | ((e) << 23) | (m)) ! 64: ! 65: /* the following deal with IEEE double-precision numbers */ ! 66: #define EXCESSD 1022 ! 67: #define HIDDEND (1 << 20) ! 68: #define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) ! 69: #define SIGND(fp) ((fp.l.upper) & SIGNBIT) ! 70: #define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ ! 71: (fp.l.lower >> 22)) ! 72: ! 73: /* define SWAP for 386/960 reverse-byte-order brain-damaged CPUs */ ! 74: union double_long ! 75: { ! 76: double d; ! 77: #ifdef SWAP ! 78: struct { ! 79: unsigned long lower; ! 80: long upper; ! 81: } l; ! 82: #else ! 83: struct { ! 84: long upper; ! 85: unsigned long lower; ! 86: } l; ! 87: #endif ! 88: }; ! 89: ! 90: union float_long ! 91: { ! 92: float f; ! 93: long l; ! 94: }; ! 95: ! 96: /* add two floats */ ! 97: float ! 98: __addsf3 (float a1, float a2) ! 99: { ! 100: register long mant1, mant2; ! 101: register union float_long fl1, fl2; ! 102: register int exp1, exp2; ! 103: int sign = 0; ! 104: ! 105: fl1.f = a1; ! 106: fl2.f = a2; ! 107: ! 108: /* check for zero args */ ! 109: if (!fl1.l) ! 110: return (fl2.f); ! 111: if (!fl2.l) ! 112: return (fl1.f); ! 113: ! 114: exp1 = EXP (fl1.l); ! 115: exp2 = EXP (fl2.l); ! 116: ! 117: if (exp1 > exp2 + 25) ! 118: return (fl1.l); ! 119: if (exp2 > exp1 + 25) ! 120: return (fl2.l); ! 121: ! 122: /* do everything in excess precision so's we can round later */ ! 123: mant1 = MANT (fl1.l) << 6; ! 124: mant2 = MANT (fl2.l) << 6; ! 125: ! 126: if (SIGN (fl1.l)) ! 127: mant1 = -mant1; ! 128: if (SIGN (fl2.l)) ! 129: mant2 = -mant2; ! 130: ! 131: if (exp1 > exp2) ! 132: { ! 133: mant2 >>= exp1 - exp2; ! 134: } ! 135: else ! 136: { ! 137: mant1 >>= exp2 - exp1; ! 138: exp1 = exp2; ! 139: } ! 140: mant1 += mant2; ! 141: ! 142: if (mant1 < 0) ! 143: { ! 144: mant1 = -mant1; ! 145: sign = SIGNBIT; ! 146: } ! 147: else if (!mant1) ! 148: return (0); ! 149: ! 150: /* normalize up */ ! 151: while (!(mant1 & 0xE0000000)) ! 152: { ! 153: mant1 <<= 1; ! 154: exp1--; ! 155: } ! 156: ! 157: /* normalize down? */ ! 158: if (mant1 & (1 << 30)) ! 159: { ! 160: mant1 >>= 1; ! 161: exp1++; ! 162: } ! 163: ! 164: /* round to even */ ! 165: mant1 += (mant1 & 0x40) ? 0x20 : 0x1F; ! 166: ! 167: /* normalize down? */ ! 168: if (mant1 & (1 << 30)) ! 169: { ! 170: mant1 >>= 1; ! 171: exp1++; ! 172: } ! 173: ! 174: /* lose extra precision */ ! 175: mant1 >>= 6; ! 176: ! 177: /* turn off hidden bit */ ! 178: mant1 &= ~HIDDEN; ! 179: ! 180: /* pack up and go home */ ! 181: fl1.l = PACK (sign, exp1, mant1); ! 182: return (fl1.f); ! 183: } ! 184: ! 185: /* subtract two floats */ ! 186: float ! 187: __subsf3 (float a1, float a2) ! 188: { ! 189: register union float_long fl1, fl2; ! 190: ! 191: fl1.f = a1; ! 192: fl2.f = a2; ! 193: ! 194: /* check for zero args */ ! 195: if (!fl2.l) ! 196: return (fl1.f); ! 197: if (!fl1.l) ! 198: return (-fl2.f); ! 199: ! 200: /* twiddle sign bit and add */ ! 201: fl2.l ^= SIGNBIT; ! 202: return __addsf3 (a1, fl2.f); ! 203: } ! 204: ! 205: /* compare two floats */ ! 206: long ! 207: __cmpsf2 (float a1, float a2) ! 208: { ! 209: register union float_long fl1, fl2; ! 210: ! 211: fl1.f = a1; ! 212: fl2.f = a2; ! 213: ! 214: if (SIGN (fl1.l) && SIGN (fl2.l)) ! 215: { ! 216: fl1.l ^= SIGNBIT; ! 217: fl2.l ^= SIGNBIT; ! 218: } ! 219: if (fl1.l < fl2.l) ! 220: return (-1); ! 221: if (fl1.l > fl2.l) ! 222: return (1); ! 223: return (0); ! 224: } ! 225: ! 226: /* multiply two floats */ ! 227: float ! 228: __mulsf3 (float a1, float a2) ! 229: { ! 230: register union float_long fl1, fl2; ! 231: register unsigned long result; ! 232: register int exp; ! 233: int sign; ! 234: ! 235: fl1.f = a1; ! 236: fl2.f = a2; ! 237: ! 238: if (!fl1.l || !fl2.l) ! 239: return (0); ! 240: ! 241: /* compute sign and exponent */ ! 242: sign = SIGN (fl1.l) ^ SIGN (fl2.l); ! 243: exp = EXP (fl1.l) - EXCESS; ! 244: exp += EXP (fl2.l); ! 245: ! 246: fl1.l = MANT (fl1.l); ! 247: fl2.l = MANT (fl2.l); ! 248: ! 249: /* the multiply is done as one 16x16 multiply and two 16x8 multiples */ ! 250: result = (fl1.l >> 8) * (fl2.l >> 8); ! 251: result += ((fl1.l & 0xFF) * (fl2.l >> 8)) >> 8; ! 252: result += ((fl2.l & 0xFF) * (fl1.l >> 8)) >> 8; ! 253: ! 254: if (result & 0x80000000) ! 255: { ! 256: /* round */ ! 257: result += 0x80; ! 258: result >>= 8; ! 259: } ! 260: else ! 261: { ! 262: /* round */ ! 263: result += 0x40; ! 264: result >>= 7; ! 265: exp--; ! 266: } ! 267: ! 268: result &= ~HIDDEN; ! 269: ! 270: /* pack up and go home */ ! 271: fl1.l = PACK (sign, exp, result); ! 272: return (fl1.f); ! 273: } ! 274: ! 275: /* divide two floats */ ! 276: float ! 277: __divsf3 (float a1, float a2) ! 278: { ! 279: register union float_long fl1, fl2; ! 280: register int result; ! 281: register int mask; ! 282: register int exp, sign; ! 283: ! 284: fl1.f = a1; ! 285: fl2.f = a2; ! 286: ! 287: /* subtract exponents */ ! 288: exp = EXP (fl1.l) - EXP (fl2.l) + EXCESS; ! 289: ! 290: /* compute sign */ ! 291: sign = SIGN (fl1.l) ^ SIGN (fl2.l); ! 292: ! 293: /* divide by zero??? */ ! 294: if (!fl2.l) ! 295: /* return NaN or -NaN */ ! 296: return (sign ? 0xFFFFFFFF : 0x7FFFFFFF); ! 297: ! 298: /* numerator zero??? */ ! 299: if (!fl1.l) ! 300: return (0); ! 301: ! 302: /* now get mantissas */ ! 303: fl1.l = MANT (fl1.l); ! 304: fl2.l = MANT (fl2.l); ! 305: ! 306: /* this assures we have 25 bits of precision in the end */ ! 307: if (fl1.l < fl2.l) ! 308: { ! 309: fl1.l <<= 1; ! 310: exp--; ! 311: } ! 312: ! 313: /* now we perform repeated subtraction of fl2.l from fl1.l */ ! 314: mask = 0x1000000; ! 315: result = 0; ! 316: while (mask) ! 317: { ! 318: if (fl1.l >= fl2.l) ! 319: { ! 320: result |= mask; ! 321: fl1.l -= fl2.l; ! 322: } ! 323: fl1.l <<= 1; ! 324: mask >>= 1; ! 325: } ! 326: ! 327: /* round */ ! 328: result += 1; ! 329: ! 330: /* normalize down */ ! 331: exp++; ! 332: result >>= 1; ! 333: ! 334: result &= ~HIDDEN; ! 335: ! 336: /* pack up and go home */ ! 337: fl1.l = PACK (sign, exp, result); ! 338: return (fl1.f); ! 339: } ! 340: ! 341: /* convert int to double */ ! 342: double ! 343: __floatsidf (register long a1) ! 344: { ! 345: register int sign = 0, exp = 31 + EXCESSD; ! 346: union double_long dl; ! 347: ! 348: if (!a1) ! 349: { ! 350: dl.l.upper = dl.l.lower = 0; ! 351: return (dl.d); ! 352: } ! 353: ! 354: if (a1 < 0) ! 355: { ! 356: sign = SIGNBIT; ! 357: a1 = -a1; ! 358: } ! 359: ! 360: while (a1 < 0x1000000) ! 361: { ! 362: a1 <<= 4; ! 363: exp -= 4; ! 364: } ! 365: ! 366: while (a1 < 0x40000000) ! 367: { ! 368: a1 <<= 1; ! 369: exp--; ! 370: } ! 371: ! 372: /* pack up and go home */ ! 373: dl.l.upper = sign; ! 374: dl.l.upper |= exp << 20; ! 375: dl.l.upper |= (a1 >> 10) & ~HIDDEND; ! 376: dl.l.lower = a1 << 22; ! 377: ! 378: return (dl.d); ! 379: } ! 380: ! 381: /* negate a float */ ! 382: float ! 383: __negsf2 (float a1) ! 384: { ! 385: register union float_long fl1; ! 386: ! 387: fl1.f = a1; ! 388: if (!fl1.l) ! 389: return (0); ! 390: ! 391: fl1.l ^= SIGNBIT; ! 392: return (fl1.f); ! 393: } ! 394: ! 395: /* negate a double */ ! 396: double ! 397: __negdf2 (double a1) ! 398: { ! 399: register union double_long dl1; ! 400: ! 401: dl1.d = a1; ! 402: ! 403: if (!dl1.l.upper && !dl1.l.lower) ! 404: return (dl1.d); ! 405: ! 406: dl1.l.upper ^= SIGNBIT; ! 407: return (dl1.d); ! 408: } ! 409: ! 410: /* convert float to double */ ! 411: double ! 412: __extendsfdf2 (float a1) ! 413: { ! 414: register union float_long fl1; ! 415: register union double_long dl; ! 416: register int exp; ! 417: ! 418: fl1.f = a1; ! 419: ! 420: if (!fl1.l) ! 421: { ! 422: dl.l.upper = dl.l.lower = 0; ! 423: return (dl.d); ! 424: } ! 425: ! 426: dl.l.upper = SIGN (fl1.l); ! 427: exp = EXP (fl1.l) - EXCESS + EXCESSD; ! 428: dl.l.upper |= exp << 20; ! 429: dl.l.upper |= (MANT (fl1.l) & ~HIDDEN) >> 3; ! 430: dl.l.lower = MANT (fl1.l) << 29; ! 431: ! 432: return (dl.d); ! 433: } ! 434: ! 435: /* convert double to float */ ! 436: float ! 437: __truncdfsf2 (double a1) ! 438: { ! 439: register int exp; ! 440: register long mant; ! 441: register union float_long fl; ! 442: register union double_long dl1; ! 443: ! 444: dl1.d = a1; ! 445: ! 446: if (!dl1.l.upper && !dl1.l.lower) ! 447: return (0); ! 448: ! 449: exp = EXPD (dl1) - EXCESSD + EXCESS; ! 450: ! 451: /* shift double mantissa 6 bits so we can round */ ! 452: mant = MANTD (dl1) >> 6; ! 453: ! 454: /* now round and shift down */ ! 455: mant += 1; ! 456: mant >>= 1; ! 457: ! 458: /* did the round overflow? */ ! 459: if (mant & 0xFF000000) ! 460: { ! 461: mant >>= 1; ! 462: exp++; ! 463: } ! 464: ! 465: mant &= ~HIDDEN; ! 466: ! 467: /* pack up and go home */ ! 468: fl.l = PACK (SIGND (dl1), exp, mant); ! 469: return (fl.f); ! 470: } ! 471: ! 472: /* compare two doubles */ ! 473: long ! 474: __cmpdf2 (double a1, double a2) ! 475: { ! 476: register union double_long dl1, dl2; ! 477: ! 478: dl1.d = a1; ! 479: dl2.d = a2; ! 480: ! 481: if (SIGND (dl1) && SIGND (dl2)) ! 482: { ! 483: dl1.l.upper ^= SIGNBIT; ! 484: dl2.l.upper ^= SIGNBIT; ! 485: } ! 486: if (dl1.l.upper < dl2.l.upper) ! 487: return (-1); ! 488: if (dl1.l.upper > dl2.l.upper) ! 489: return (1); ! 490: if (dl1.l.lower < dl2.l.lower) ! 491: return (-1); ! 492: if (dl1.l.lower > dl2.l.lower) ! 493: return (1); ! 494: return (0); ! 495: } ! 496: ! 497: /* convert double to int */ ! 498: long ! 499: __fixdfsi (double a1) ! 500: { ! 501: register union double_long dl1; ! 502: register int exp; ! 503: register long l; ! 504: ! 505: dl1.d = a1; ! 506: ! 507: if (!dl1.l.upper && !dl1.l.lower) ! 508: return (0); ! 509: ! 510: exp = EXPD (dl1) - EXCESSD - 31; ! 511: l = MANTD (dl1); ! 512: ! 513: if (exp > 0) ! 514: return (0x7FFFFFFF | SIGND (dl1)); /* largest integer */ ! 515: ! 516: /* shift down until exp = 0 or l = 0 */ ! 517: if (exp < 0 && exp > -32 && l) ! 518: l >>= -exp; ! 519: else ! 520: return (0); ! 521: ! 522: return (SIGND (dl1) ? -l : l); ! 523: } ! 524: ! 525: /* convert double to unsigned int */ ! 526: unsigned ! 527: long __fixunsdfsi (double a1) ! 528: { ! 529: register union double_long dl1; ! 530: register int exp; ! 531: register unsigned long l; ! 532: ! 533: dl1.d = a1; ! 534: ! 535: if (!dl1.l.upper && !dl1.l.lower) ! 536: return (0); ! 537: ! 538: exp = EXPD (dl1) - EXCESSD - 32; ! 539: l = (((((dl1.l.upper) & 0xFFFFF) | HIDDEND) << 11) | (dl1.l.lower >> 21)); ! 540: ! 541: if (exp > 0) ! 542: return (0xFFFFFFFF); /* largest integer */ ! 543: ! 544: /* shift down until exp = 0 or l = 0 */ ! 545: if (exp < 0 && exp > -32 && l) ! 546: l >>= -exp; ! 547: else ! 548: return (0); ! 549: ! 550: return (l); ! 551: } ! 552: ! 553: /* For now, the hard double-precision routines simply ! 554: punt and do it in single */ ! 555: /* addtwo doubles */ ! 556: double ! 557: __adddf3 (double a1, double a2) ! 558: { ! 559: return ((float) a1 + (float) a2); ! 560: } ! 561: ! 562: /* subtract two doubles */ ! 563: double ! 564: __subdf3 (double a1, double a2) ! 565: { ! 566: return ((float) a1 - (float) a2); ! 567: } ! 568: ! 569: /* multiply two doubles */ ! 570: double ! 571: __muldf3 (double a1, double a2) ! 572: { ! 573: return ((float) a1 * (float) a2); ! 574: } ! 575: ! 576: /* divide two doubles */ ! 577: double ! 578: __divdf3 (double a1, double a2) ! 579: { ! 580: return ((float) a1 / (float) a2); ! 581: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.