Commit | Line | Data |
---|---|---|
d4b6f0a4 RH |
1 | /* |
2 | * Copyright (c) 1982 Regents of the University of California | |
3 | */ | |
4 | #ifndef lint | |
f70ab843 | 5 | static char sccsid[] = "@(#)bignum2.c 4.3 %G%"; |
d4b6f0a4 RH |
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 |