| 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) %G%"; |
| 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 |