|
|
1.1 ! root 1: /* This is a stripped down version of floatlib.c. It supplies only those ! 2: functions which exist in libgcc, but for which there is not assembly ! 3: language versions in m68k/lb1sf68.asm. ! 4: ! 5: It also includes simplistic support for extended floats (by working in ! 6: double precision). You must compile this file again with -DEXTFLOAT ! 7: to get this support. */ ! 8: ! 9: /* ! 10: ** gnulib support for software floating point. ! 11: ** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved. ! 12: ** Permission is granted to do *anything* you want with this file, ! 13: ** commercial or otherwise, provided this message remains intact. So there! ! 14: ** I would appreciate receiving any updates/patches/changes that anyone ! 15: ** makes, and am willing to be the repository for said changes (am I ! 16: ** making a big mistake?). ! 17: ** ! 18: ** Pat Wood ! 19: ** Pipeline Associates, Inc. ! 20: ** [email protected] or ! 21: ** sun!pipeline!phw or ! 22: ** uunet!motown!pipeline!phw ! 23: ** ! 24: ** 05/01/91 -- V1.0 -- first release to gcc mailing lists ! 25: ** 05/04/91 -- V1.1 -- added float and double prototypes and return values ! 26: ** -- fixed problems with adding and subtracting zero ! 27: ** -- fixed rounding in truncdfsf2 ! 28: ** -- fixed SWAP define and tested on 386 ! 29: */ ! 30: ! 31: /* ! 32: ** The following are routines that replace the gnulib soft floating point ! 33: ** routines that are called automatically when -msoft-float is selected. ! 34: ** The support single and double precision IEEE format, with provisions ! 35: ** for byte-swapped machines (tested on 386). Some of the double-precision ! 36: ** routines work at full precision, but most of the hard ones simply punt ! 37: ** and call the single precision routines, producing a loss of accuracy. ! 38: ** long long support is not assumed or included. ! 39: ** Overall accuracy is close to IEEE (actually 68882) for single-precision ! 40: ** arithmetic. I think there may still be a 1 in 1000 chance of a bit ! 41: ** being rounded the wrong way during a multiply. I'm not fussy enough to ! 42: ** bother with it, but if anyone is, knock yourself out. ! 43: ** ! 44: ** Efficiency has only been addressed where it was obvious that something ! 45: ** would make a big difference. Anyone who wants to do this right for ! 46: ** best speed should go in and rewrite in assembler. ! 47: ** ! 48: ** I have tested this only on a 68030 workstation and 386/ix integrated ! 49: ** in with -msoft-float. ! 50: */ ! 51: ! 52: /* the following deal with IEEE single-precision numbers */ ! 53: #define EXCESS 126L ! 54: #define SIGNBIT 0x80000000L ! 55: #define HIDDEN (1L << 23L) ! 56: #define SIGN(fp) ((fp) & SIGNBIT) ! 57: #define EXP(fp) (((fp) >> 23L) & 0xFF) ! 58: #define MANT(fp) (((fp) & 0x7FFFFFL) | HIDDEN) ! 59: #define PACK(s,e,m) ((s) | ((e) << 23L) | (m)) ! 60: ! 61: /* the following deal with IEEE double-precision numbers */ ! 62: #define EXCESSD 1022 ! 63: #define HIDDEND (1L << 20L) ! 64: #define EXPDBITS 11 ! 65: #define EXPDMASK 0x7FF ! 66: #define EXPD(fp) (((fp.l.upper) >> 20L) & 0x7FFL) ! 67: #define SIGND(fp) ((fp.l.upper) & SIGNBIT) ! 68: #define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ ! 69: (fp.l.lower >> 22)) ! 70: #define MANTDMASK 0xFFFFF /* mask of upper part */ ! 71: ! 72: /* the following deal with IEEE extended-precision numbers */ ! 73: #define EXCESSX 16382 ! 74: #define HIDDENX (1L << 31L) ! 75: #define EXPXBITS 15 ! 76: #define EXPXMASK 0x7FFF ! 77: #define EXPX(fp) (((fp.l.upper) >> 16) & EXPXMASK) ! 78: #define SIGNX(fp) ((fp.l.upper) & SIGNBIT) ! 79: #define MANTXMASK 0x7FFFFFFF /* mask of upper part */ ! 80: ! 81: union double_long ! 82: { ! 83: double d; ! 84: struct { ! 85: long upper; ! 86: unsigned long lower; ! 87: } l; ! 88: }; ! 89: ! 90: union float_long { ! 91: float f; ! 92: long l; ! 93: }; ! 94: ! 95: union long_double_long ! 96: { ! 97: long double ld; ! 98: struct ! 99: { ! 100: long upper; ! 101: unsigned long middle; ! 102: unsigned long lower; ! 103: } l; ! 104: }; ! 105: ! 106: #ifndef EXTFLOAT ! 107: ! 108: /* convert int to double */ ! 109: double ! 110: __floatsidf (int a1) ! 111: { ! 112: long sign = 0, exp = 31 + EXCESSD; ! 113: union double_long dl; ! 114: ! 115: if (!a1) ! 116: { ! 117: dl.l.upper = dl.l.lower = 0; ! 118: return dl.d; ! 119: } ! 120: ! 121: if (a1 < 0) ! 122: { ! 123: sign = SIGNBIT; ! 124: a1 = -a1; ! 125: if (a1 < 0) ! 126: { ! 127: dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L); ! 128: dl.l.lower = 0; ! 129: return dl.d; ! 130: } ! 131: } ! 132: ! 133: while (a1 < 0x1000000) ! 134: { ! 135: a1 <<= 4; ! 136: exp -= 4; ! 137: } ! 138: ! 139: while (a1 < 0x40000000) ! 140: { ! 141: a1 <<= 1; ! 142: exp--; ! 143: } ! 144: ! 145: /* pack up and go home */ ! 146: dl.l.upper = sign; ! 147: dl.l.upper |= exp << 20L; ! 148: dl.l.upper |= (a1 >> 10L) & ~HIDDEND; ! 149: dl.l.lower = a1 << 22L; ! 150: ! 151: return dl.d; ! 152: } ! 153: ! 154: /* convert int to float */ ! 155: float ! 156: __floatsisf (int l) ! 157: { ! 158: double foo = __floatsidf (l); ! 159: return foo; ! 160: } ! 161: ! 162: /* convert float to double */ ! 163: double ! 164: __extendsfdf2 (float a1) ! 165: { ! 166: register union float_long fl1; ! 167: register union double_long dl; ! 168: register long exp; ! 169: ! 170: fl1.f = a1; ! 171: ! 172: if (!fl1.l) ! 173: { ! 174: dl.l.upper = dl.l.lower = 0; ! 175: return dl.d; ! 176: } ! 177: ! 178: dl.l.upper = SIGN (fl1.l); ! 179: exp = EXP (fl1.l) - EXCESS + EXCESSD; ! 180: dl.l.upper |= exp << 20; ! 181: dl.l.upper |= (MANT (fl1.l) & ~HIDDEN) >> 3; ! 182: dl.l.lower = MANT (fl1.l) << 29; ! 183: ! 184: return dl.d; ! 185: } ! 186: ! 187: /* convert double to float */ ! 188: float ! 189: __truncdfsf2 (double a1) ! 190: { ! 191: register long exp; ! 192: register long mant; ! 193: register union float_long fl; ! 194: register union double_long dl1; ! 195: ! 196: dl1.d = a1; ! 197: ! 198: if (!dl1.l.upper && !dl1.l.lower) ! 199: return 0; ! 200: ! 201: exp = EXPD (dl1) - EXCESSD + EXCESS; ! 202: ! 203: /* shift double mantissa 6 bits so we can round */ ! 204: mant = MANTD (dl1) >> 6; ! 205: ! 206: /* now round and shift down */ ! 207: mant += 1; ! 208: mant >>= 1; ! 209: ! 210: /* did the round overflow? */ ! 211: if (mant & 0xFF000000) ! 212: { ! 213: mant >>= 1; ! 214: exp++; ! 215: } ! 216: ! 217: mant &= ~HIDDEN; ! 218: ! 219: /* pack up and go home */ ! 220: fl.l = PACK (SIGND (dl1), exp, mant); ! 221: return (fl.f); ! 222: } ! 223: ! 224: /* convert double to int */ ! 225: int ! 226: __fixdfsi (double a1) ! 227: { ! 228: register union double_long dl1; ! 229: register long exp; ! 230: register long l; ! 231: ! 232: dl1.d = a1; ! 233: ! 234: if (!dl1.l.upper && !dl1.l.lower) ! 235: return 0; ! 236: ! 237: exp = EXPD (dl1) - EXCESSD - 31; ! 238: l = MANTD (dl1); ! 239: ! 240: if (exp > 0) ! 241: { ! 242: /* Return largest integer. */ ! 243: return SIGND (dl1) ? 0x80000000 : 0x7fffffff; ! 244: } ! 245: ! 246: if (exp <= -32) ! 247: return 0; ! 248: ! 249: /* shift down until exp = 0 */ ! 250: if (exp < 0) ! 251: l >>= -exp; ! 252: ! 253: return (SIGND (dl1) ? -l : l); ! 254: } ! 255: ! 256: /* convert float to int */ ! 257: int ! 258: __fixsfsi (float a1) ! 259: { ! 260: double foo = a1; ! 261: return __fixdfsi (foo); ! 262: } ! 263: ! 264: #else /* EXTFLOAT */ ! 265: ! 266: /* Primitive extended precision floating point support. ! 267: ! 268: We assume all numbers are normalized, don't do any rounding, etc. */ ! 269: ! 270: /* Prototypes for the above in case we use them. */ ! 271: double __floatsidf (int); ! 272: float __floatsisf (int); ! 273: double __extendsfdf2 (float); ! 274: float __truncdfsf2 (double); ! 275: int __fixdfsi (double); ! 276: int __fixsfsi (float); ! 277: ! 278: /* convert double to long double */ ! 279: long double ! 280: __extenddfxf2 (double d) ! 281: { ! 282: register union double_long dl; ! 283: register union long_double_long ldl; ! 284: register long exp; ! 285: ! 286: dl.d = d; ! 287: /*printf ("dfxf in: %g\n", d);*/ ! 288: ! 289: if (!dl.l.upper && !dl.l.lower) ! 290: return 0; ! 291: ! 292: ldl.l.upper = SIGND (dl); ! 293: exp = EXPD (dl) - EXCESSD + EXCESSX; ! 294: ldl.l.upper |= exp << 16; ! 295: ldl.l.middle = HIDDENX; ! 296: /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */ ! 297: ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20); ! 298: /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */ ! 299: ldl.l.middle |= dl.l.lower >> (1 + 20); ! 300: /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */ ! 301: ldl.l.lower = dl.l.lower << (32 - 21); ! 302: ! 303: /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/ ! 304: return ldl.ld; ! 305: } ! 306: ! 307: /* convert long double to double */ ! 308: double ! 309: __truncxfdf2 (long double ld) ! 310: { ! 311: register long exp; ! 312: register union double_long dl; ! 313: register union long_double_long ldl; ! 314: ! 315: ldl.ld = ld; ! 316: /*printf ("xfdf in: %s\n", dumpxf (ld));*/ ! 317: ! 318: if (!ldl.l.upper && !ldl.l.middle && !ldl.l.lower) ! 319: return 0; ! 320: ! 321: exp = EXPX (ldl) - EXCESSX + EXCESSD; ! 322: /* ??? quick and dirty: keep `exp' sane */ ! 323: if (exp >= EXPDMASK) ! 324: exp = EXPDMASK - 1; ! 325: dl.l.upper = SIGNX (ldl); ! 326: dl.l.upper |= exp << (32 - (EXPDBITS + 1)); ! 327: /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */ ! 328: dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1); ! 329: dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1)); ! 330: dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1); ! 331: ! 332: /*printf ("xfdf out: %g\n", dl.d);*/ ! 333: return dl.d; ! 334: } ! 335: ! 336: /* convert a float to a long double */ ! 337: long double ! 338: __extendsfxf2 (float f) ! 339: { ! 340: long double foo = __extenddfxf2 (__extendsfdf2 (f)); ! 341: return foo; ! 342: } ! 343: ! 344: /* convert a long double to a float */ ! 345: float ! 346: __truncxfsf2 (long double ld) ! 347: { ! 348: float foo = __truncdfsf2 (__truncxfdf2 (ld)); ! 349: return foo; ! 350: } ! 351: ! 352: /* convert an int to a long double */ ! 353: long double ! 354: __floatsixf (int l) ! 355: { ! 356: double foo = __floatsidf (l); ! 357: return foo; ! 358: } ! 359: ! 360: /* convert a long double to an int */ ! 361: int ! 362: __fixxfsi (long double ld) ! 363: { ! 364: int foo = __fixdfsi ((double) ld); ! 365: return foo; ! 366: } ! 367: ! 368: /* The remaining provide crude math support by working in double precision. */ ! 369: ! 370: long double ! 371: __addxf3 (long double x1, long double x2) ! 372: { ! 373: return (double) x1 + (double) x2; ! 374: } ! 375: ! 376: long double ! 377: __subxf3 (long double x1, long double x2) ! 378: { ! 379: return (double) x1 - (double) x2; ! 380: } ! 381: ! 382: long double ! 383: __mulxf3 (long double x1, long double x2) ! 384: { ! 385: return (double) x1 * (double) x2; ! 386: } ! 387: ! 388: long double ! 389: __divxf3 (long double x1, long double x2) ! 390: { ! 391: return (double) x1 / (double) x2; ! 392: } ! 393: ! 394: long double ! 395: __negxf2 (long double x1) ! 396: { ! 397: return - (double) x1; ! 398: } ! 399: ! 400: long ! 401: __cmpxf2 (long double x1, long double x2) ! 402: { ! 403: return __cmpdf2 ((double) x1, (double) x2); ! 404: } ! 405: ! 406: long ! 407: __eqxf2 (long double x1, long double x2) ! 408: { ! 409: return __cmpdf2 ((double) x1, (double) x2); ! 410: } ! 411: ! 412: long ! 413: __nexf2 (long double x1, long double x2) ! 414: { ! 415: return __cmpdf2 ((double) x1, (double) x2); ! 416: } ! 417: ! 418: long ! 419: __ltxf2 (long double x1, long double x2) ! 420: { ! 421: return __cmpdf2 ((double) x1, (double) x2); ! 422: } ! 423: ! 424: long ! 425: __lexf2 (long double x1, long double x2) ! 426: { ! 427: return __cmpdf2 ((double) x1, (double) x2); ! 428: } ! 429: ! 430: long ! 431: __gtxf2 (long double x1, long double x2) ! 432: { ! 433: return __cmpdf2 ((double) x1, (double) x2); ! 434: } ! 435: ! 436: long ! 437: __gexf2 (long double x1, long double x2) ! 438: { ! 439: return __cmpdf2 ((double) x1, (double) x2); ! 440: } ! 441: ! 442: #endif /* EXTFLOAT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.