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