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