|
|
1.1 root 1: /*
2: * Copyright (c) 1982 Regents of the University of California
3: */
4: #ifndef lint
5: static char sccsid[] = "@(#)bignum2.c 4.3 2/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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.