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