Commit | Line | Data |
---|---|---|
d4b6f0a4 | 1 | /* |
bcf1365c DF |
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. | |
d4b6f0a4 | 5 | */ |
bcf1365c | 6 | |
d4b6f0a4 | 7 | #ifndef lint |
bcf1365c | 8 | static char sccsid[] = "@(#)bignum2.c 5.1 (Berkeley) %G%"; |
d4b6f0a4 RH |
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 |