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