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) 04/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 549