xref: /csrg-svn/old/as.vax/bignum1.c (revision 5802)
1*5802Srrh /*
2*5802Srrh  *	Copyright (c) 1982 Regents of the University of California
3*5802Srrh  */
4*5802Srrh #ifndef lint
5*5802Srrh static char sccsid[] = "@(#)bignum1.c 4.1 02/14/82";
6*5802Srrh #endif not lint
7*5802Srrh 
8*5802Srrh #include <errno.h>
9*5802Srrh #include <stdio.h>
10*5802Srrh #include "as.h"
11*5802Srrh 
12*5802Srrh /*
13*5802Srrh  *	Construct a floating point number
14*5802Srrh  */
15*5802Srrh Bignum as_atof(numbuf, radix, ovfp)
16*5802Srrh 	char	*numbuf;
17*5802Srrh 	int	radix;
18*5802Srrh 	Ovf	*ovfp;
19*5802Srrh {
20*5802Srrh 	Bignum	number;
21*5802Srrh 	extern	int	errno;
22*5802Srrh 	double	atof();
23*5802Srrh 
24*5802Srrh 	number = Znumber;
25*5802Srrh 	errno = 0;
26*5802Srrh 	switch(radix){
27*5802Srrh 	case TYPF:
28*5802Srrh 	case TYPD:
29*5802Srrh 		number.num_tag = TYPD;
30*5802Srrh 		*ovfp = 0;
31*5802Srrh 		number.num_num.numFd_float.Fd_value = atof(numbuf);
32*5802Srrh 		break;
33*5802Srrh 	case TYPG:
34*5802Srrh 	case TYPH:
35*5802Srrh 		number = bigatof(numbuf, radix);
36*5802Srrh 		break;
37*5802Srrh 	}
38*5802Srrh 	if (errno == ERANGE && passno == 2){
39*5802Srrh 		yywarning("Floating conversion over/underflowed\n");
40*5802Srrh 	}
41*5802Srrh 	return(number);
42*5802Srrh }
43*5802Srrh 
44*5802Srrh /*
45*5802Srrh  *	Construct an integer.
46*5802Srrh  */
47*5802Srrh 
48*5802Srrh Bignum as_atoi(ccp, radix, ovfp)
49*5802Srrh 	reg	char	*ccp;		/* character cp */
50*5802Srrh 		int	radix;
51*5802Srrh 		Ovf	*ovfp;
52*5802Srrh {
53*5802Srrh 	reg	chptr	bcp;
54*5802Srrh 		chptr	tcp;
55*5802Srrh 	reg	int	i;
56*5802Srrh 		int	val;
57*5802Srrh 		Bignum	n_n;
58*5802Srrh 		Bignum	t_n;
59*5802Srrh 		int	sign;
60*5802Srrh 		Ovf	ovf;
61*5802Srrh 
62*5802Srrh 	ovf = 0;
63*5802Srrh 	sign = 0;
64*5802Srrh 	for (; *ccp; ccp++){
65*5802Srrh 		switch(*ccp){
66*5802Srrh 		case '0':
67*5802Srrh 		case '+':	continue;
68*5802Srrh 		case '-':	sign ^= 1;
69*5802Srrh 				continue;
70*5802Srrh 		}
71*5802Srrh 		break;
72*5802Srrh 	}
73*5802Srrh 
74*5802Srrh 	n_n = Znumber;
75*5802Srrh 	t_n = Znumber;
76*5802Srrh 	bcp = CH_FIELD(n_n); (void)numclear(bcp);
77*5802Srrh 	tcp = CH_FIELD(t_n); (void)numclear(tcp);
78*5802Srrh 	for (; *ccp; ccp++){
79*5802Srrh 		switch(*ccp){
80*5802Srrh 		case '8': case '9':
81*5802Srrh 			if (radix < 10)
82*5802Srrh 				goto done;
83*5802Srrh 			/*FALLTHROUGH*/
84*5802Srrh 		case '0': case '1': case '2': case '3': case '4':
85*5802Srrh 		case '5': case '6': case '7':
86*5802Srrh 			val = *ccp - '0';
87*5802Srrh 			break;
88*5802Srrh 		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
89*5802Srrh 			if (radix < 16)
90*5802Srrh 				goto done;
91*5802Srrh 			val = *ccp - 'A' + 10;
92*5802Srrh 			break;
93*5802Srrh 		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
94*5802Srrh 			if (radix < 16)
95*5802Srrh 				goto done;
96*5802Srrh 			val = *ccp - 'a' + 10;
97*5802Srrh 			break;
98*5802Srrh 		default:
99*5802Srrh 			goto done;
100*5802Srrh 		}
101*5802Srrh 		switch(radix){
102*5802Srrh 		case 8:
103*5802Srrh 			ovf |= numshift(3, bcp, bcp);
104*5802Srrh 			break;
105*5802Srrh 		case 16:
106*5802Srrh 			ovf |= numshift(4, bcp, bcp);
107*5802Srrh 			break;
108*5802Srrh 		case 10:
109*5802Srrh 			ovf |= numshift(1, tcp, bcp);
110*5802Srrh 			ovf |= numshift(3, bcp, bcp);
111*5802Srrh 			ovf |= numaddv(bcp, tcp, bcp);
112*5802Srrh 			break;
113*5802Srrh 		}
114*5802Srrh 		ovf |= numaddd(bcp, bcp, val);
115*5802Srrh 	}
116*5802Srrh   done: ;
117*5802Srrh 	ovf |= posovf(bcp);
118*5802Srrh 	if (sign){
119*5802Srrh 		if (ovf & OVF_MAXINT) {
120*5802Srrh 			ovf &= ~(OVF_MAXINT | OVF_POSOVF);
121*5802Srrh 		} else {
122*5802Srrh 			ovf |= numnegate(bcp, bcp);
123*5802Srrh 		}
124*5802Srrh 	}
125*5802Srrh 	/*
126*5802Srrh 	 *	find the highest set unit of the number
127*5802Srrh 	 */
128*5802Srrh 	val = sign ? -1 : 0;
129*5802Srrh 	for (i = 0; i < CH_N; i++){
130*5802Srrh 		if (bcp[i] == val)
131*5802Srrh 			break;
132*5802Srrh 	}
133*5802Srrh 	{
134*5802Srrh 		static u_char tagtab[4][16] = {
135*5802Srrh 		{	TYPB,
136*5802Srrh 			TYPW,
137*5802Srrh 			TYPL, TYPL,
138*5802Srrh 			TYPQ, TYPQ, TYPQ, TYPQ,
139*5802Srrh 			TYPO, TYPO, TYPO, TYPO, TYPO, TYPO, TYPO, TYPO},
140*5802Srrh 		{	TYPW,
141*5802Srrh 			TYPL,
142*5802Srrh 			TYPQ, TYPQ,
143*5802Srrh 			TYPO, TYPO, TYPO, TYPO},
144*5802Srrh 		{   0   },
145*5802Srrh 		{	TYPL,
146*5802Srrh 			TYPQ,
147*5802Srrh 			TYPO, TYPO }
148*5802Srrh 		};
149*5802Srrh 		/*
150*5802Srrh 		 *	i indexes to the null chunk; make it point to the
151*5802Srrh 		 *	last non null chunk
152*5802Srrh 		 */
153*5802Srrh 		i -= 1;
154*5802Srrh 		if (i < 0)
155*5802Srrh 			i = 0;
156*5802Srrh 		n_n.num_tag = tagtab[HOC][i];
157*5802Srrh 		assert(n_n.num_tag != 0, "Botch width computation");
158*5802Srrh 	}
159*5802Srrh 	*ovfp = ovf;
160*5802Srrh 	return(n_n);
161*5802Srrh }
162*5802Srrh 
163*5802Srrh Ovf posovf(src)
164*5802Srrh 	reg	chptr	src;
165*5802Srrh {
166*5802Srrh 	reg	int	i;
167*5802Srrh 	Ovf	overflow = 0;
168*5802Srrh 
169*5802Srrh 	if (src[HOC] & SIGNBIT)
170*5802Srrh 		overflow = OVF_POSOVF;
171*5802Srrh 	if (src[HOC] == SIGNBIT){
172*5802Srrh 		for (i = HOC - 1; i >= 0; --i){
173*5802Srrh 			if (src[i] != 0)
174*5802Srrh 				return(overflow);
175*5802Srrh 		}
176*5802Srrh 		overflow |= OVF_MAXINT;
177*5802Srrh 	}
178*5802Srrh 	return(overflow);
179*5802Srrh }
180*5802Srrh 
181*5802Srrh /*
182*5802Srrh  *	check if the number is clear
183*5802Srrh  */
184*5802Srrh int isclear(dst)
185*5802Srrh 	reg	chptr	dst;
186*5802Srrh {
187*5802Srrh 	return(!isunequal(dst, CH_FIELD(Znumber)));
188*5802Srrh }
189*5802Srrh 
190*5802Srrh int isunequal(src1, src2)
191*5802Srrh 	reg	chptr	src1, src2;
192*5802Srrh {
193*5802Srrh 	reg	int	i;
194*5802Srrh 
195*5802Srrh 	i = CH_N;
196*5802Srrh 	do{
197*5802Srrh 		if (*src1++ != *src2++)
198*5802Srrh 			return(i);
199*5802Srrh 	}while(--i);
200*5802Srrh 	return(0);
201*5802Srrh }
202*5802Srrh 
203*5802Srrh Ovf numclear(dst)
204*5802Srrh 	reg	chptr	dst;
205*5802Srrh {
206*5802Srrh 	reg	int	i;
207*5802Srrh 	i = CH_N;
208*5802Srrh 	do{
209*5802Srrh 		*dst++ = 0;
210*5802Srrh 	}while(--i);
211*5802Srrh 	return(0);
212*5802Srrh }
213*5802Srrh 
214*5802Srrh Ovf numshift(n, dst, src)
215*5802Srrh 		int	n;
216*5802Srrh 	reg	chptr	dst, src;
217*5802Srrh {
218*5802Srrh 	reg	int	i;
219*5802Srrh 	reg	u_int	carryi, carryo;
220*5802Srrh 	reg	u_int	mask;
221*5802Srrh 	reg	u_int	value;
222*5802Srrh 
223*5802Srrh 	i = CH_N;
224*5802Srrh 	if (n == 0){
225*5802Srrh 		do{
226*5802Srrh 			*dst++ = *src++;
227*5802Srrh 		} while(--i);
228*5802Srrh 		return(0);
229*5802Srrh 	}
230*5802Srrh 
231*5802Srrh 	carryi = 0;
232*5802Srrh 	mask = ONES(n);
233*5802Srrh 
234*5802Srrh 	if (n > 0){
235*5802Srrh 		do{
236*5802Srrh 			value = *src++;
237*5802Srrh 			carryo = (value >> (CH_BITS - n)) & mask;
238*5802Srrh 			value <<= n;
239*5802Srrh 			value &= ~mask;
240*5802Srrh 			*dst++ = value | carryi;
241*5802Srrh 			carryi = carryo;
242*5802Srrh 		} while (--i);
243*5802Srrh 		return(carryi ? OVF_LSHIFT : 0);
244*5802Srrh 	} else {
245*5802Srrh 		n = -n;
246*5802Srrh 		src += CH_N;
247*5802Srrh 		dst += CH_N;
248*5802Srrh 		do{
249*5802Srrh 			value = *--src;
250*5802Srrh 			carryo = value & mask;
251*5802Srrh 			value >>= n;
252*5802Srrh 			value &= ONES(CH_BITS - n);
253*5802Srrh 			*--dst = value | carryi;
254*5802Srrh 			carryi = carryo << (CH_BITS - n);
255*5802Srrh 		} while (--i);
256*5802Srrh 		return(carryi ? OVF_LSHIFT : 0);
257*5802Srrh 	}
258*5802Srrh }
259*5802Srrh 
260*5802Srrh Ovf numaddd(dst, src1, val)
261*5802Srrh 	chptr	dst, src1;
262*5802Srrh 	int	val;
263*5802Srrh {
264*5802Srrh 	static	Bignum	work;
265*5802Srrh 
266*5802Srrh 	work.num_uchar[0] = val;
267*5802Srrh 	return (numaddv(dst, src1, CH_FIELD(work)));
268*5802Srrh }
269*5802Srrh 
270*5802Srrh Ovf numaddv(dst, src1, src2)
271*5802Srrh 	reg	chptr	dst, src1, src2;
272*5802Srrh {
273*5802Srrh 	reg	int	i;
274*5802Srrh 	reg	int	carry;
275*5802Srrh 	reg	u_int	A,B,value;
276*5802Srrh 
277*5802Srrh 	carry = 0;
278*5802Srrh 	i = CH_N;
279*5802Srrh 	do{
280*5802Srrh 		A = *src1++;
281*5802Srrh 		B = *src2++;
282*5802Srrh 		value = A + B + carry;
283*5802Srrh 		*dst++ = value;
284*5802Srrh 		carry = 0;
285*5802Srrh 		if (value < A || value < B)
286*5802Srrh 			carry = 1;
287*5802Srrh 	} while (--i);
288*5802Srrh 	return(carry ? OVF_ADDV : 0);
289*5802Srrh }
290*5802Srrh 
291*5802Srrh Ovf numnegate(dst, src)
292*5802Srrh 	chptr	dst, src;
293*5802Srrh {
294*5802Srrh 	Ovf	ovf;
295*5802Srrh 
296*5802Srrh 	ovf = num1comp(dst, src) ;
297*5802Srrh 	ovf |= numaddd(dst, dst, 1);
298*5802Srrh 	return(ovf);
299*5802Srrh }
300*5802Srrh 
301*5802Srrh Ovf num1comp(dst, src)
302*5802Srrh 	reg	chptr	dst, src;
303*5802Srrh {
304*5802Srrh 	reg	int	i;
305*5802Srrh 	i = CH_N;
306*5802Srrh 	do{
307*5802Srrh 		*dst++ = ~ *src++;
308*5802Srrh 	}while (--i);
309*5802Srrh 	return(0);
310*5802Srrh }
311*5802Srrh 
312*5802Srrh /*
313*5802Srrh  *	Determine if floating point numbers are
314*5802Srrh  *	capable of being represented as a one byte immediate literal constant
315*5802Srrh  *	If it is, then stuff the value into *valuep.
316*5802Srrh  *	argtype is how the instruction will interpret the number.
317*5802Srrh  */
318*5802Srrh int slitflt(number, argtype, valuep)
319*5802Srrh 	Bignum	number;		/* number presented */
320*5802Srrh 	int	argtype;	/* what the instruction expects */
321*5802Srrh 	int	*valuep;
322*5802Srrh {
323*5802Srrh #define	EXPPREC 3
324*5802Srrh #define	MANTPREC 3
325*5802Srrh 
326*5802Srrh 		int	mask;
327*5802Srrh 	reg	int	i;
328*5802Srrh 		Bignum	unpacked;
329*5802Srrh 		Ovf	ovf;
330*5802Srrh 
331*5802Srrh 	*valuep = 0;
332*5802Srrh 	if (!ty_float[argtype])
333*5802Srrh 		return(0);
334*5802Srrh 	unpacked = bignumunpack(number, &ovf);
335*5802Srrh 	assert(ovf == 0, "overflow in unpacking floating #!?");
336*5802Srrh 	if (unpacked.num_sign)
337*5802Srrh 		return(0);
338*5802Srrh 	if (unpacked.num_exponent < 0)
339*5802Srrh 		return(0);
340*5802Srrh 	if (unpacked.num_exponent > ONES(EXPPREC))
341*5802Srrh 		return(0);
342*5802Srrh 	for (i = 0; i < HOC; i++){
343*5802Srrh 		if (CH_FIELD(unpacked)[i])
344*5802Srrh 			return(0);
345*5802Srrh 	}
346*5802Srrh 	if ((CH_FIELD(unpacked)[HOC]) & ONES(CH_BITS - MANTPREC))
347*5802Srrh 		return(0);
348*5802Srrh 	*valuep = (unpacked.num_exponent & ONES(EXPPREC)) << MANTPREC;
349*5802Srrh 	mask = (CH_FIELD(unpacked)[HOC]) >> (CH_BITS - MANTPREC);
350*5802Srrh 	mask &= ONES(MANTPREC);
351*5802Srrh 	*valuep |= mask;
352*5802Srrh 	*valuep &= ONES(MANTPREC + EXPPREC);
353*5802Srrh 	return(1);
354*5802Srrh }
355*5802Srrh 
356*5802Srrh #ifndef STANDALONE
357*5802Srrh /*
358*5802Srrh  *	Output a big number to txtfil
359*5802Srrh  *	Called only when passno == 2
360*5802Srrh  *
361*5802Srrh  *	The conversion specifies the width of the number to be written out.
362*5802Srrh  *	The width is supplied from either an initialized data directive
363*5802Srrh  *	(for example .float, .double), or from the operand size
364*5802Srrh  *	defined by an operator.
365*5802Srrh  *	If the number is of type quad or octal,
366*5802Srrh  *	we just write it out; this allows one to specify bit
367*5802Srrh  *	patterns for floating point numbers.
368*5802Srrh  *	If the number is one of the floating types and the conversion
369*5802Srrh  *	is not the same type, then we complain, but do the conversion anyway.
370*5802Srrh  *	The conversion is strict.
371*5802Srrh  */
372*5802Srrh bignumwrite(number, toconv)
373*5802Srrh 	Bignum	number;
374*5802Srrh 	int	toconv;		/* one of TYP[QO FDGH] */
375*5802Srrh {
376*5802Srrh 	reg	u_int	*bp;
377*5802Srrh #ifdef VMS
378*5802Srrh 		int	nints;
379*5802Srrh 	reg	int	i;
380*5802Srrh #endif VMS
381*5802Srrh 
382*5802Srrh 	if (passno != 2)
383*5802Srrh 		return;
384*5802Srrh 
385*5802Srrh 	bp = &number.num_uint[0];
386*5802Srrh 	switch(number.num_tag){
387*5802Srrh 	case TYPB:
388*5802Srrh 	case TYPW:
389*5802Srrh 	case TYPL:
390*5802Srrh 	case TYPQ:
391*5802Srrh 	case TYPO:
392*5802Srrh 		number = intconvert(number, toconv);
393*5802Srrh 		break;
394*5802Srrh 	default:
395*5802Srrh 		number = floatconvert(number, toconv);
396*5802Srrh 		break;
397*5802Srrh 	}
398*5802Srrh #ifdef UNIX
399*5802Srrh 	bwrite((char *)bp, ty_nbyte[toconv], txtfil);
400*5802Srrh #endif UNIX
401*5802Srrh #ifdef VMS
402*5802Srrh 	/*
403*5802Srrh 	 *	rrh did not check this code when the new floating point
404*5802Srrh 	 *	numbers were put into the assembler, as he didn't
405*5802Srrh 	 *	have access to a vms system.
406*5802Srrh 	 */
407*5802Srrh 	nints = ty_nbyte[toconv] / 4;
408*5802Srrh 	for (i = 0; i < nints; i++){
409*5802Srrh 		puchar(vms_obj_ptr,-4);
410*5802Srrh 		pulong(vms_obj_ptr, bp[i]);
411*5802Srrh 	}
412*5802Srrh 	if((vms_obj_ptr-sobuf) > 400) {
413*5802Srrh 		write(objfil,sobuf,vms_obj_ptr-sobuf);
414*5802Srrh 		vms_obj_ptr = sobuf + 1;
415*5802Srrh 	}
416*5802Srrh 	return;
417*5802Srrh #endif VMS
418*5802Srrh }
419*5802Srrh #endif STANDALONE
420