xref: /original-bsd/old/as.vax/bignum2.c (revision eb814dd3)
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) 04/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 
intconvert(number,convto)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 
floatconvert(number,convto)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  */
bignumconvert(number,toconv,ovfp)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 
bignumunpack(Packed,ovfp)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 
bignumpack(Unpacked,toconv,ovfp)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 
mapnumber(chp1,chp2,nbytes,themap)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  */
upround(numberp,p,exponent)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
bignumprint(number)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 
numprintovf(ovf)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
549