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