date and time created 83/08/11 20:49:31 by sam
[unix-history] / usr / src / old / as.vax / bignum1.c
CommitLineData
7c2b5c8d
RH
1/*
2 * Copyright (c) 1982 Regents of the University of California
3 */
4#ifndef lint
e40ffc5c 5static char sccsid[] = "@(#)bignum1.c 4.4 %G%";
7c2b5c8d
RH
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 */
15Bignum 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
48Bignum 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
163Ovf 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 */
184int isclear(dst)
185 reg chptr dst;
186{
187 return(!isunequal(dst, CH_FIELD(Znumber)));
188}
189
190int 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
203Ovf 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
214Ovf 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
260Ovf 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
270Ovf 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
291Ovf 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
301Ovf 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 */
318int 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 */
372bignumwrite(number, toconv)
373 Bignum number;
374 int toconv; /* one of TYP[QO FDGH] */
375{
376 reg u_int *bp;
7c2b5c8d
RH
377
378 if (passno != 2)
379 return;
380
381 bp = &number.num_uint[0];
382 switch(number.num_tag){
383 case TYPB:
384 case TYPW:
385 case TYPL:
386 case TYPQ:
387 case TYPO:
388 number = intconvert(number, toconv);
389 break;
390 default:
391 number = floatconvert(number, toconv);
392 break;
393 }
7c2b5c8d 394 bwrite((char *)bp, ty_nbyte[toconv], txtfil);
7c2b5c8d
RH
395}
396#endif STANDALONE