date and time created 88/12/12 20:54:43 by kfall
[unix-history] / usr / src / old / as.vax / bignum1.c
CommitLineData
7c2b5c8d 1/*
bcf1365c
DF
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.
7c2b5c8d 5 */
bcf1365c 6
7c2b5c8d 7#ifndef lint
bcf1365c 8static char sccsid[] = "@(#)bignum1.c 5.1 (Berkeley) %G%";
7c2b5c8d
RH
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 */
18Bignum 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
51Bignum 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
166Ovf 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 */
187int isclear(dst)
188 reg chptr dst;
189{
190 return(!isunequal(dst, CH_FIELD(Znumber)));
191}
192
193int 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
206Ovf 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
217Ovf 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
263Ovf 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
273Ovf 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
294Ovf 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
304Ovf 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 */
321int 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 */
375bignumwrite(number, toconv)
376 Bignum number;
377 int toconv; /* one of TYP[QO FDGH] */
378{
379 reg u_int *bp;
7c2b5c8d
RH
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 }
7c2b5c8d 397 bwrite((char *)bp, ty_nbyte[toconv], txtfil);
7c2b5c8d
RH
398}
399#endif STANDALONE