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[] = "@(#)natof.c 5.1 (Berkeley) 04/30/85"; 9 #endif not lint 10 11 #include <stdio.h> 12 #include <ctype.h> 13 #include <errno.h> 14 15 #include "as.h" 16 17 Bignum bigatof(str, radix) 18 reg char *str; /* r11 */ 19 int radix; /* TYPF ... TYPH */ 20 { 21 int msign; 22 int esign; 23 int decpt; 24 reg chptr temp; /* r10 */ 25 reg u_int quotient; /* r9 */ /* must be here */ 26 reg u_int remainder; /* r8 */ /* must be here */ 27 reg chptr acc; 28 reg int dividend; /* for doing division */ 29 reg u_int i; 30 short *sptr; /* for doing division */ 31 int ch; 32 int dexponent; /* decimal exponent */ 33 int bexponent; /* binary exponent */ 34 Bignum Acc; 35 Bignum Temp; 36 static Bignum znumber; 37 Ovf ovf; 38 u_int j; 39 extern int errno; 40 u_int ediv(); 41 42 #ifdef lint 43 quotient = 0; 44 remainder = 0; 45 #endif lint 46 msign = 0; 47 esign = 0; 48 decpt = 0; 49 dexponent = 0; 50 Acc = znumber; 51 Acc.num_tag = radix; 52 acc = CH_FIELD(Acc); 53 temp = CH_FIELD(Temp); 54 55 do{ 56 ch = *str++; 57 } while(isspace(ch)); 58 59 switch(ch){ 60 case '-': 61 msign = -1; 62 /* FALLTHROUGH */ 63 case '+': 64 ch = *str++; 65 break; 66 } 67 dofract: 68 for(; isdigit(ch); ch = *str++){ 69 assert(((acc[HOC] & SIGNBIT) == 0), "Negative HOC"); 70 if (acc[HOC] < MAXINT_10){ 71 ovf = numshift(3, temp, acc); 72 ovf |= numshift(1, acc, acc); 73 ovf |= numaddv(acc, temp, acc); 74 ovf |= numaddd(acc, acc, ch - '0'); 75 assert(ovf == 0, "Overflow building mantissa"); 76 } else { 77 /* 78 * Then, the number is too large anyway 79 */ 80 dexponent++; 81 } 82 if (decpt) 83 dexponent--; 84 } 85 switch(ch){ 86 case '.': 87 if (decpt == 0){ 88 decpt++; 89 ch = *str++; 90 goto dofract; 91 } 92 break; 93 /* 94 * only 'e' and 'E' are recognized by atof() 95 */ 96 case 'e': 97 case 'E': 98 /* 99 * we include the remainder for compatability with as formats 100 * in as, the radix actual paramater agrees with the character 101 * we expect; consequently, no checking is done. 102 */ 103 case 'd': 104 case 'D': 105 case 'g': 106 case 'G': 107 case 'h': 108 case 'H': 109 j = 0; 110 ch = *str++; 111 esign = 0; 112 switch(ch){ 113 case '-': 114 esign = 1; 115 /* FALLTHROUGH */ 116 case '+': 117 ch = *str++; 118 } 119 for(; isdigit(ch); ch = *str++){ 120 if (j < MAXINT_10){ 121 j *= 10; 122 j += ch - '0'; 123 } else { 124 /* 125 * outrageously large exponent 126 */ 127 /*VOID*/ 128 } 129 } 130 if (esign) 131 dexponent -= j; 132 else 133 dexponent += j; 134 /* 135 * There should be a range check on dexponent here 136 */ 137 } 138 /* 139 * The number has now been reduced to a mantissa 140 * and an exponent. 141 * The mantissa is an n bit number (to the precision 142 * of the extended words) in the acc. 143 * The exponent is a signed power of 10 in dexponent. 144 * msign is on if the resulting number will eventually 145 * be negative. 146 * 147 * We now must convert the number to standard format floating 148 * number, which will be done by accumulating 149 * a binary exponent in bexponent, as we gradually 150 * drive dexponent towards zero, one count at a time. 151 */ 152 if (isclear(acc)){ 153 return(Acc); 154 } 155 bexponent = 0; 156 157 /* 158 * Scale the number down. 159 * We must divide acc by 10 as many times as needed. 160 */ 161 for (; dexponent < 0; dexponent++){ 162 /* 163 * Align the number so that the most significant 164 * bits are aligned in the most significant 165 * bits of the accumulator, adjusting the 166 * binary exponent as we shift. 167 * The goal is to get the high order bit (NOT the 168 * sign bit) set. 169 */ 170 assert(((acc[HOC] & SIGNBIT) == 0), "Negative HOC"); 171 ovf = 0; 172 173 for (j = 5; j >= 1; --j){ 174 i = 1 << (j - 1); /* 16, 8, 4, 2, 1 */ 175 quotient = ONES(i); 176 quotient <<= (CH_BITS - 1) - i; 177 while((acc[HOC] & quotient) == 0){ 178 ovf |= numshift((int)i, acc, acc); 179 bexponent -= i; 180 } 181 } 182 /* 183 * Add 2 to the accumulator to effect rounding, 184 * and get set up to divide by 5. 185 */ 186 ovf = numaddd(acc, acc, 2); 187 assert(ovf == 0, "Carry out of left rounding up by 2"); 188 /* 189 * Divide the high order chunks by 5; 190 * The last chunk will be divided by 10, 191 * (to see what the remainder is, also to effect rounding) 192 * and then multipiled by 2 to effect division by 5. 193 */ 194 remainder = 0; 195 #if DEBUGNATOF 196 printf("Dividing: "); 197 bignumprint(Acc); 198 printf("\n"); 199 #endif DEBUGNATOF 200 sptr = (short *)acc; 201 for (i = (CH_N * 2 - 1); i >= 1; --i){ 202 /* 203 * Divide (remainder:16).(acc[i]:16) 204 * by 5, putting the quotient back 205 * into acc[i]:16, and save the remainder 206 * for the next iteration. 207 */ 208 dividend = (remainder << 16) | (sptr[i] & ONES(16)); 209 assert(dividend >= 0, "dividend < 0"); 210 quotient = dividend / 5; 211 remainder = dividend - (quotient * 5); 212 sptr[i] = quotient; 213 remainder = remainder; 214 } 215 /* 216 * Divide the lowest order chunk by 10, 217 * saving the remainder to decide how to round. 218 * Then, multiply by 2, making it look as 219 * if we divided by 10. 220 * This multiply fills in a 0 on the least sig bit. 221 */ 222 dividend = (remainder << 16) | (sptr[0] & ONES(16)); 223 assert(dividend >= 0, "dividend < 0"); 224 quotient = dividend / 10; 225 remainder = dividend - (quotient * 10); 226 sptr[0] = quotient + quotient; 227 228 if (remainder >= 5) 229 ovf = numaddd(acc, acc, 1); 230 /* 231 * Now, divide by 2, effecting division by 10, 232 * merely by adjusting the binary exponent. 233 */ 234 bexponent--; 235 } 236 /* 237 * Scale the number up by multiplying by 10 as 238 * many times as necessary 239 */ 240 for (; dexponent > 0; dexponent--){ 241 /* 242 * Compare high word to (2**31)/5, 243 * and scale accordingly 244 */ 245 while ( ((unsigned)acc[HOC]) > MAXINT_5){ 246 (void)numshift(-1, acc, acc); 247 bexponent++; 248 } 249 /* 250 * multiply the mantissa by 5, 251 * and scale the binary exponent by 2 252 */ 253 ovf = numshift(2, temp, acc); 254 ovf |= numaddv(acc, acc, temp); 255 assert(ovf == 0, "Scaling * 10 of manitissa"); 256 bexponent++; 257 } 258 /* 259 * We now have: 260 * a CH_N chunk length binary integer, right 261 * justified (in native format). 262 * a binary exponent. 263 * 264 * Now, we treat this large integer as an octa word 265 * number, and unpack it into standard unpacked 266 * format. That unpacking will give us yet 267 * another binary exponent, which we adjust with 268 * the accumulated binary exponent. 269 */ 270 Acc.num_tag = TYPO; 271 #if DEBUGNATOF 272 printf("Octal number: "); 273 bignumprint(Acc); 274 printf("\n"); 275 #endif DEBUGNATOF 276 Acc = bignumunpack(Acc, &ovf); 277 278 if (ovf) 279 errno = ERANGE; 280 #if DEBUGNATOF 281 printf("Unpacked octal number: "); 282 bignumprint(Acc); 283 printf("bexponent == %d\n", bexponent); 284 #endif DEBUGNATOF 285 Acc.num_exponent += bexponent; 286 assert(Acc.num_sign == 0, "unpacked integer is < 0"); 287 Acc.num_sign = msign; 288 /* 289 * We now pack the number back into a radix format number. 290 * This checks for overflow, underflow, 291 * and rounds by 1/2 ulp. 292 */ 293 ovf = 0; 294 Acc = bignumpack(Acc, radix, &ovf); 295 if (ovf) 296 errno = ERANGE; 297 #if DEBUGNATOF 298 printf("packed number: "); 299 bignumprint(Acc); 300 printf("\n"); 301 #endif DEBUGNATOF 302 return(Acc); 303 } 304 #if 0 305 /* 306 * Unfortunately, one can't use the ediv instruction to do 307 * division on numbers with > 64 bits. 308 * This is because ediv returns signed quantities; 309 * if the quotient is an unsigned number > 2^31, 310 * ediv sets integer overflow. 311 */ 312 unsigned int ediv(high, low, divisor, qp, i) 313 register unsigned int high; /* r11 */ 314 register unsigned int low; /* r10 */ 315 register unsigned int divisor; /* r9 */ 316 unsigned int *qp; 317 { 318 register unsigned int remainder; /* r8 */ 319 register unsigned int quotient; /* r7 */ 320 321 asm("ediv r9, r10, r7, r8 # Divide. q->r7, r->r8 (discarded)"); 322 *qp = quotient; 323 return(remainder); 324 } 325 #endif 0 326