Annotation of gcc/config/m68k/fpgnulib.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.