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