|
|
1.1 root 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) 4/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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.