Annotation of GNUtools/cc/floatlib.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

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