|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)bignum2.c 5.1 (Berkeley) 4/30/85"; ! 9: #endif not lint ! 10: ! 11: #include <stdio.h> ! 12: #include "as.h" ! 13: Bignum Znumber; /* zero reference */ ! 14: #define MINEXP -32768 /* never generate; reserved for id 0 */ ! 15: ! 16: Bignum intconvert(number, convto) ! 17: Bignum number; ! 18: int convto; ! 19: { ! 20: reg int i; ! 21: if (number.num_tag == convto) ! 22: return(number); ! 23: if (ty_nbyte[number.num_tag] > ty_nbyte[convto] && (passno == 2)){ ! 24: yywarning("Conversion between %s and %s looses significance", ! 25: ty_string[number.num_tag], ! 26: ty_string[convto]); ! 27: } ! 28: for (i = ty_nbyte[convto]; i < ty_nbyte[TYPO]; i++) ! 29: number.num_uchar[i] = 0; ! 30: return(number); ! 31: } ! 32: ! 33: #define CONV(src, dst) (((src) << TYPLG) + (dst)) ! 34: ! 35: Bignum floatconvert(number, convto) ! 36: Bignum number; ! 37: int convto; ! 38: { ! 39: reg u_int *bp; /* r11 */ ! 40: int loss = 0; ! 41: int gain = 0; ! 42: int mixs = 0; ! 43: Ovf ovf; ! 44: ! 45: if (number.num_tag == convto) ! 46: return(number); ! 47: bp = &number.num_uint[0]; ! 48: #ifdef lint ! 49: *bp = *bp; ! 50: #endif lint ! 51: ! 52: switch(CONV(number.num_tag, convto)){ ! 53: ! 54: case CONV(TYPF, TYPD): asm("cvtfd (r11), (r11)"); break; ! 55: case CONV(TYPF, TYPG): mixs++; break; ! 56: case CONV(TYPF, TYPH): mixs++; break; ! 57: ! 58: case CONV(TYPD, TYPF): asm("cvtdf (r11), (r11)"); break; ! 59: case CONV(TYPD, TYPG): mixs++; break; ! 60: case CONV(TYPD, TYPH): mixs++; break; ! 61: ! 62: case CONV(TYPG, TYPF): mixs++; break; ! 63: case CONV(TYPG, TYPD): mixs++; break; ! 64: case CONV(TYPG, TYPH): mixs++; break; ! 65: ! 66: case CONV(TYPH, TYPF): mixs++; break; ! 67: case CONV(TYPH, TYPD): mixs++; break; ! 68: case CONV(TYPH, TYPG): mixs++; break; ! 69: default: panic("Bad floating point conversion?"); ! 70: } ! 71: if ((gain || mixs || loss) && (passno == 2)){ ! 72: yywarning("Converting from %s to %s: %s ", ! 73: ty_string[number.num_tag], ! 74: ty_string[convto], ! 75: gain ? "gains significance" : ! 76: (loss ? "looses significance" : "mixs exponent formats") ! 77: ); ! 78: } ! 79: if (mixs){ ! 80: number = bignumconvert(number, convto, &ovf); ! 81: if (ovf && passno == 2){ ! 82: yywarning("Floating conversion over/underflowed\n"); ! 83: } ! 84: } else { ! 85: number.num_tag = convto; ! 86: } ! 87: return(number); ! 88: } ! 89: ! 90: /* ! 91: * Convert a big number between various representations ! 92: */ ! 93: Bignum bignumconvert(number, toconv, ovfp) ! 94: Bignum number; ! 95: int toconv; ! 96: Ovf *ovfp; ! 97: { ! 98: int tag; ! 99: ! 100: *ovfp = 0; ! 101: tag = number.num_tag; ! 102: if (tag == toconv) ! 103: return(number); ! 104: if (tag == TYPUNPACKED){ ! 105: return(bignumpack(number, toconv, ovfp)); ! 106: } ! 107: if (toconv == TYPUNPACKED){ ! 108: return(bignumunpack(number, ovfp)); ! 109: } ! 110: return(bignumpack(bignumunpack(number, ovfp), toconv, ovfp)); ! 111: } ! 112: ! 113: Bignum bignumunpack(Packed, ovfp) ! 114: Bignum Packed; ! 115: Ovf *ovfp; ! 116: { ! 117: Bignum Mantissa; ! 118: Bignum Enumber; ! 119: reg int i; ! 120: int j; ! 121: int k; ! 122: reg struct ty_bigdesc *p; ! 123: reg chptr packed; ! 124: reg chptr mantissa; ! 125: reg chptr enumber; ! 126: u_short exponent; ! 127: int sign; ! 128: int mask; ! 129: ! 130: p = &ty_bigdesc[Packed.num_tag]; ! 131: ! 132: *ovfp = 0; ! 133: Mantissa = Znumber; ! 134: sign = 0; ! 135: exponent = 0; ! 136: mantissa = CH_FIELD(Mantissa); ! 137: enumber = CH_FIELD(Enumber); ! 138: packed = CH_FIELD(Packed); ! 139: ! 140: if (isclear(packed)){ ! 141: Mantissa.num_tag = TYPUNPACKED; ! 142: Mantissa.num_exponent = MINEXP; ! 143: return(Mantissa); ! 144: } ! 145: /* ! 146: * map the packed number into the mantissa, using ! 147: * the unpacking map ! 148: */ ! 149: mapnumber(mantissa, packed, 16, p->b_upmmap); ! 150: /* ! 151: * perform the mantissa shifting. ! 152: * This may appear to overflow; all that is lost ! 153: * is low order bits of the exponent. ! 154: */ ! 155: (void)numshift(p->b_mlshift, mantissa, mantissa); ! 156: /* ! 157: * handle sign and exponent ! 158: */ ! 159: switch(Packed.num_tag){ ! 160: case TYPB: ! 161: case TYPW: ! 162: case TYPL: ! 163: case TYPO: ! 164: case TYPQ: ! 165: sign = 0; ! 166: exponent = p->b_eexcess; ! 167: if (mantissa[HOC] & SIGNBIT){ ! 168: sign = -1; ! 169: *ovfp |= numnegate(mantissa, mantissa); ! 170: } ! 171: /* ! 172: * Normalize the packed by left shifting, ! 173: * adjusting the exponent as we go. ! 174: * Do a binary weighted left shift for some speed. ! 175: */ ! 176: k = 0; ! 177: for (j = 4; j >= 0; --j){ ! 178: i = 1 << j; /* 16, 8, 4, 2, 1 */ ! 179: while(1){ ! 180: if (k >= p->b_msigbits) ! 181: break; ! 182: mask = ONES(i) << (CH_BITS - i); ! 183: if (mantissa[HOC] & mask) ! 184: break; ! 185: (void)numshift(i, mantissa, mantissa); ! 186: k += i; ! 187: exponent -= i; ! 188: } ! 189: } ! 190: assert(mantissa[HOC] & SIGNBIT, "integer <<ing"); ! 191: /* ! 192: * now, kick the most significant bit off the top ! 193: */ ! 194: (void)numshift(1, mantissa, mantissa); ! 195: break; ! 196: default: ! 197: /* ! 198: * map the exponent into the local area. ! 199: */ ! 200: Enumber = Znumber; ! 201: mapnumber(enumber, packed, 2, p->b_upemap); ! 202: /* ! 203: * Extract the exponent, and get rid ! 204: * of the sign bit ! 205: */ ! 206: exponent = Enumber.num_ushort[0] & ONES(15); ! 207: /* ! 208: * shift the exponent, and get rid of high order ! 209: * trash ! 210: */ ! 211: exponent >>= p->b_ershift; ! 212: exponent &= ONES(p->b_esigbits); ! 213: /* ! 214: * un excess the exponent ! 215: */ ! 216: exponent -= p->b_eexcess; ! 217: /* ! 218: * extract and extend the sign bit ! 219: */ ! 220: sign = (Enumber.num_ushort[0] & ~ONES(15)) ? -1 : 0; ! 221: } ! 222: /* ! 223: * Assemble the pieces, and return the number ! 224: */ ! 225: Mantissa.num_tag = TYPUNPACKED; ! 226: Mantissa.num_sign = sign; ! 227: Mantissa.num_exponent = exponent; ! 228: return(Mantissa); ! 229: } ! 230: ! 231: Bignum bignumpack(Unpacked, toconv, ovfp) ! 232: Bignum Unpacked; ! 233: int toconv; ! 234: Ovf *ovfp; ! 235: { ! 236: Bignum Back; ! 237: Bignum Enumber; ! 238: Bignum Temp; ! 239: ! 240: short exponent; ! 241: char sign; ! 242: reg struct ty_bigdesc *p; ! 243: reg chptr back; ! 244: reg chptr enumber; ! 245: reg chptr temp; ! 246: reg chptr unpacked; ! 247: ! 248: int i,j; ! 249: ! 250: if (Unpacked.num_tag != TYPUNPACKED) ! 251: panic("Argument to bignumpack is not unpacked"); ! 252: ! 253: *ovfp = 0; ! 254: Back = Znumber; ! 255: Temp = Znumber; ! 256: Back.num_tag = toconv; ! 257: ! 258: back = CH_FIELD(Back); ! 259: temp = CH_FIELD(Temp); ! 260: enumber = CH_FIELD(Enumber); ! 261: unpacked = CH_FIELD(Unpacked); ! 262: p = &ty_bigdesc[toconv]; ! 263: ! 264: exponent = Unpacked.num_exponent; ! 265: sign = Unpacked.num_sign; ! 266: if (exponent == MINEXP) ! 267: return(Back); /* identically zero */ ! 268: ! 269: switch(toconv){ ! 270: case TYPB: ! 271: case TYPW: ! 272: case TYPL: ! 273: case TYPQ: ! 274: case TYPO: ! 275: /* ! 276: * Put back in the assumed high order fraction ! 277: * bit that is always a 1. ! 278: */ ! 279: (void)numshift(-1, temp, unpacked); ! 280: temp[HOC] |= SIGNBIT; ! 281: if (exponent > p->b_eexcess){ ! 282: /* ! 283: * Construct the largest positive integer ! 284: */ ! 285: (void)numclear(temp); ! 286: (void)num1comp(temp, temp); ! 287: temp[HOC] &= ~SIGNBIT; ! 288: sign = sign; ! 289: *ovfp |= OVF_OVERFLOW; ! 290: } else ! 291: if (exponent <= 0){ ! 292: /* ! 293: * chop the temp; underflow to integer 0 ! 294: */ ! 295: (void)numclear(temp); ! 296: sign = 0; ! 297: *ovfp |= OVF_UNDERFLOW; ! 298: } else { ! 299: /* ! 300: * denormalize the temp. ! 301: * This will again chop, by shifting ! 302: * bits off the right end into oblivion. ! 303: */ ! 304: for (j = 4; j >= 0; --j){ ! 305: i = 1 << j; /* 16, 8, 4, 2, 1 */ ! 306: while(exponent + i <= p->b_eexcess){ ! 307: numshift(-i, temp, temp); ! 308: exponent += i; ! 309: } ! 310: } ! 311: } ! 312: /* ! 313: * negate the temp if the sign is set ! 314: */ ! 315: if (sign) ! 316: *ovfp |= numnegate(temp, temp); ! 317: /* ! 318: * Stuff the temp number into the return area ! 319: */ ! 320: mapnumber(back, temp, 16, p->b_pmmap); ! 321: return(Back); ! 322: default: ! 323: /* ! 324: * Shift the mantissa to the right, filling in zeroes on ! 325: * the left. This aligns the least significant bit ! 326: * on the bottom of a byte, something that upround ! 327: * will use. ! 328: * Put the result into a temporary. ! 329: * Even though the shift may be zero, there ! 330: * is still a copy involved here. ! 331: */ ! 332: (void)numshift(-(p->b_mlshift), temp, unpacked); ! 333: /* ! 334: * Perform the rounding by adding in 0.5 ulp's ! 335: */ ! 336: exponent = upround(&Temp, p, exponent); ! 337: /* ! 338: * Do a range check on the exponent, in preparation ! 339: * to stuffing it in. ! 340: */ ! 341: if ((short)(exponent + p->b_eexcess) == 0){ ! 342: /* ! 343: * Sorry, no gradual underflow on the ! 344: * VAX. Chop this beasty totally to zero ! 345: */ ! 346: goto zeroret; ! 347: } else ! 348: if ((short)(exponent + p->b_eexcess) < 0){ ! 349: /* ! 350: * True underflow will happen; ! 351: * Chop everything to positive zero ! 352: */ ! 353: zeroret: ! 354: (void)numclear(temp); ! 355: exponent = 0; ! 356: sign = 0; /* avoid reserved operand! */ ! 357: *ovfp |= OVF_UNDERFLOW; ! 358: } else ! 359: if ((unsigned)(exponent + p->b_eexcess) ! 360: >= (unsigned)(1 << p->b_esigbits)){ ! 361: /* ! 362: * Construct the largest magnitude possible ! 363: * floating point unpacked: 0.{1}111111111 ! 364: */ ! 365: (void)numclear(temp); ! 366: (void)num1comp(temp, temp); ! 367: exponent = ONES(p->b_esigbits); ! 368: sign = sign; ! 369: *ovfp |= OVF_OVERFLOW; ! 370: } else { ! 371: /* ! 372: * The exponent will fit. ! 373: * Bias it up, and the common code will stuff it. ! 374: */ ! 375: exponent += p->b_eexcess; ! 376: } ! 377: exponent <<= p->b_ershift; ! 378: /* ! 379: * mask out trash for the sign, and put in the sign. ! 380: */ ! 381: exponent &= ONES(15); ! 382: if (sign) ! 383: exponent |= ~ONES(15); ! 384: Enumber.num_ushort[0] = exponent; ! 385: /* ! 386: * Map the unpacked exponent into the value going back ! 387: */ ! 388: mapnumber(back, enumber, 2, p->b_pemap); ! 389: /* ! 390: * Stuff the unpacked mantissa into the return area ! 391: */ ! 392: mapnumber(back, temp, 16, p->b_pmmap); ! 393: return(Back); ! 394: } ! 395: /*NOTREACHED*/ ! 396: } ! 397: ! 398: mapnumber(chp1, chp2, nbytes, themap) ! 399: chptr chp1, chp2; ! 400: int nbytes; ! 401: char *themap; ! 402: { ! 403: reg int i; ! 404: reg u_char *p1, *p2; ! 405: ! 406: p1 = (u_char *)chp1; ! 407: p2 = (u_char *)chp2; ! 408: for (i = 0; i < nbytes; i++){ ! 409: switch(themap[i]){ ! 410: case NOTAKE: ! 411: break; ! 412: default: ! 413: p1[themap[i]] |= p2[i]; ! 414: break; ! 415: } ! 416: } ! 417: } ! 418: ! 419: #define UPSHIFT 2 ! 420: /* ! 421: * round in 1/2 ulp in the number, possibly modifying ! 422: * the binary exponent if there was total carry out. ! 423: * Return the modified exponent ! 424: */ ! 425: int upround(numberp, p, exponent) ! 426: reg Bignum *numberp; ! 427: reg struct ty_bigdesc *p; ! 428: int exponent; ! 429: { ! 430: reg u_char *bytep; ! 431: int nbytes; ! 432: int byteindex; ! 433: int hofractionbit; ! 434: int ovffractionbit; ! 435: reg int ovfbitindex; ! 436: reg chptr number; ! 437: static Bignum ulp; ! 438: ! 439: /* ! 440: * Find out the byte index of the byte containing the ulp ! 441: */ ! 442: number = CH_FIELD(numberp[0]); ! 443: bytep = numberp->num_uchar; ! 444: ! 445: nbytes = (p->b_msigbits - 1) + p->b_mlshift; ! 446: assert((nbytes % 8) == 0, "mantissa sig bits"); ! 447: nbytes /= 8; ! 448: byteindex = 15 - nbytes; ! 449: assert(byteindex >= 0, "ulp in outer space"); ! 450: /* ! 451: * Shift the number to the right by two places, ! 452: * so that we can do full arithmetic without overflowing ! 453: * to the left. ! 454: */ ! 455: numshift(-UPSHIFT, number, number); ! 456: /* ! 457: * Construct the missing high order fraction bit ! 458: */ ! 459: ovfbitindex = 8 - (p->b_mlshift + UPSHIFT); ! 460: assert(ovfbitindex >= 0, "Shifted byte 15 into byte 14"); ! 461: hofractionbit = (0x01 << ovfbitindex); ! 462: ovffractionbit = (0x02 << ovfbitindex); ! 463: bytep[15] |= hofractionbit; ! 464: /* ! 465: * construct the unit in the last place, and it ! 466: * to the fraction ! 467: */ ! 468: ulp.num_uchar[byteindex] |= (0x80 >> UPSHIFT); ! 469: numaddv(number, number, CH_FIELD(ulp)); ! 470: ulp.num_uchar[byteindex] &= ~(0x80 >> UPSHIFT); ! 471: /* ! 472: * Check if there was an overflow, ! 473: * and adjust by shifting. ! 474: * Also, bring the number back into canonical ! 475: * unpacked form by left shifting by two to undeo ! 476: * what we did before. ! 477: */ ! 478: if (bytep[15] & ovffractionbit){ ! 479: exponent += 1; ! 480: numshift(UPSHIFT - 1, number, number); ! 481: } else { ! 482: numshift(UPSHIFT, number, number); ! 483: } ! 484: /* ! 485: * Clear off trash in the unused bits of the high ! 486: * order byte of the number ! 487: */ ! 488: bytep[15] &= ONES(8 - p->b_mlshift); ! 489: return(exponent); ! 490: } ! 491: #ifdef DEBUG ! 492: bignumprint(number) ! 493: Bignum number; ! 494: { ! 495: printf("Bignum: %s (exp: %d, sign: %d) 0x%08x%08x%08x%08x", ! 496: ty_string[number.num_tag], ! 497: number.num_exponent, ! 498: number.num_sign, ! 499: number.num_uint[3], ! 500: number.num_uint[2], ! 501: number.num_uint[1], ! 502: number.num_uint[0]); ! 503: switch(number.num_tag){ ! 504: case TYPB: ! 505: case TYPW: ! 506: case TYPL: ! 507: case TYPQ: ! 508: case TYPO: ! 509: case TYPUNPACKED: ! 510: break; ! 511: case TYPF: ! 512: printf(" == %10.8e", number.num_num.numFf_float.Ff_value); ! 513: break; ! 514: case TYPD: ! 515: printf(" == %20.17e", number.num_num.numFd_float.Fd_value); ! 516: break; ! 517: case TYPG: ! 518: case TYPH: ! 519: break; ! 520: } ! 521: } ! 522: ! 523: numprintovf(ovf) ! 524: Ovf ovf; ! 525: { ! 526: int i; ! 527: static struct ovftab{ ! 528: Ovf which; ! 529: char *print; ! 530: } ovftab[] = { ! 531: OVF_POSOVF, "posovf", ! 532: OVF_MAXINT, "maxint", ! 533: OVF_ADDV, "addv", ! 534: OVF_LSHIFT, "lshift", ! 535: OVF_F, "F float", ! 536: OVF_D, "D float", ! 537: OVF_G, "G float", ! 538: OVF_H, "H float", ! 539: OVF_OVERFLOW, "cvt overflow", ! 540: OVF_UNDERFLOW, "cvt underflow", ! 541: 0, 0 ! 542: }; ! 543: for(i = 0; ovftab[i].which; i++){ ! 544: if (ovf & ovftab[i].which) ! 545: printf("Overflow(%s) ", ovftab[i].print); ! 546: } ! 547: } ! 548: #endif DEBUG
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.