15805Srrh /*
2*19839Sdist * Copyright (c) 1982 Regents of the University of California.
3*19839Sdist * All rights reserved. The Berkeley software License Agreement
4*19839Sdist * specifies the terms and conditions for redistribution.
55805Srrh */
6*19839Sdist
75805Srrh #ifndef lint
8*19839Sdist static char sccsid[] = "@(#)natof.c 5.1 (Berkeley) 04/30/85";
95805Srrh #endif not lint
105805Srrh
115805Srrh #include <stdio.h>
125805Srrh #include <ctype.h>
135805Srrh #include <errno.h>
145805Srrh
155805Srrh #include "as.h"
165805Srrh
bigatof(str,radix)175805Srrh Bignum bigatof(str, radix)
185805Srrh reg char *str; /* r11 */
195805Srrh int radix; /* TYPF ... TYPH */
205805Srrh {
215805Srrh int msign;
225805Srrh int esign;
235805Srrh int decpt;
245805Srrh reg chptr temp; /* r10 */
255805Srrh reg u_int quotient; /* r9 */ /* must be here */
265805Srrh reg u_int remainder; /* r8 */ /* must be here */
275805Srrh reg chptr acc;
285805Srrh reg int dividend; /* for doing division */
295805Srrh reg u_int i;
305805Srrh short *sptr; /* for doing division */
315805Srrh int ch;
325805Srrh int dexponent; /* decimal exponent */
335805Srrh int bexponent; /* binary exponent */
345805Srrh Bignum Acc;
355805Srrh Bignum Temp;
365805Srrh static Bignum znumber;
375805Srrh Ovf ovf;
385805Srrh u_int j;
395805Srrh extern int errno;
405805Srrh u_int ediv();
415805Srrh
425805Srrh #ifdef lint
435805Srrh quotient = 0;
445805Srrh remainder = 0;
455805Srrh #endif lint
465805Srrh msign = 0;
475805Srrh esign = 0;
485805Srrh decpt = 0;
495805Srrh dexponent = 0;
505805Srrh Acc = znumber;
515805Srrh Acc.num_tag = radix;
525805Srrh acc = CH_FIELD(Acc);
535805Srrh temp = CH_FIELD(Temp);
545805Srrh
555805Srrh do{
565805Srrh ch = *str++;
575805Srrh } while(isspace(ch));
585805Srrh
595805Srrh switch(ch){
605805Srrh case '-':
615805Srrh msign = -1;
625805Srrh /* FALLTHROUGH */
635805Srrh case '+':
645805Srrh ch = *str++;
655805Srrh break;
665805Srrh }
675805Srrh dofract:
685805Srrh for(; isdigit(ch); ch = *str++){
695805Srrh assert(((acc[HOC] & SIGNBIT) == 0), "Negative HOC");
705805Srrh if (acc[HOC] < MAXINT_10){
715805Srrh ovf = numshift(3, temp, acc);
725805Srrh ovf |= numshift(1, acc, acc);
735805Srrh ovf |= numaddv(acc, temp, acc);
745805Srrh ovf |= numaddd(acc, acc, ch - '0');
755805Srrh assert(ovf == 0, "Overflow building mantissa");
765805Srrh } else {
775805Srrh /*
785805Srrh * Then, the number is too large anyway
795805Srrh */
805805Srrh dexponent++;
815805Srrh }
825805Srrh if (decpt)
835805Srrh dexponent--;
845805Srrh }
855805Srrh switch(ch){
865805Srrh case '.':
875805Srrh if (decpt == 0){
885805Srrh decpt++;
895805Srrh ch = *str++;
905805Srrh goto dofract;
915805Srrh }
925805Srrh break;
935805Srrh /*
945805Srrh * only 'e' and 'E' are recognized by atof()
955805Srrh */
965805Srrh case 'e':
975805Srrh case 'E':
985805Srrh /*
995805Srrh * we include the remainder for compatability with as formats
1005805Srrh * in as, the radix actual paramater agrees with the character
1015805Srrh * we expect; consequently, no checking is done.
1025805Srrh */
1035805Srrh case 'd':
1045805Srrh case 'D':
1055805Srrh case 'g':
1065805Srrh case 'G':
1075805Srrh case 'h':
1085805Srrh case 'H':
1095805Srrh j = 0;
1105805Srrh ch = *str++;
1115805Srrh esign = 0;
1125805Srrh switch(ch){
1135805Srrh case '-':
1145805Srrh esign = 1;
1155805Srrh /* FALLTHROUGH */
1165805Srrh case '+':
1175805Srrh ch = *str++;
1185805Srrh }
1195805Srrh for(; isdigit(ch); ch = *str++){
1205805Srrh if (j < MAXINT_10){
1215805Srrh j *= 10;
1225805Srrh j += ch - '0';
1235805Srrh } else {
1245805Srrh /*
1255805Srrh * outrageously large exponent
1265805Srrh */
1275805Srrh /*VOID*/
1285805Srrh }
1295805Srrh }
1305805Srrh if (esign)
1315805Srrh dexponent -= j;
1325805Srrh else
1335805Srrh dexponent += j;
1345805Srrh /*
1355805Srrh * There should be a range check on dexponent here
1365805Srrh */
1375805Srrh }
1385805Srrh /*
1395805Srrh * The number has now been reduced to a mantissa
1405805Srrh * and an exponent.
1415805Srrh * The mantissa is an n bit number (to the precision
1425805Srrh * of the extended words) in the acc.
1435805Srrh * The exponent is a signed power of 10 in dexponent.
1445805Srrh * msign is on if the resulting number will eventually
1455805Srrh * be negative.
1465805Srrh *
1475805Srrh * We now must convert the number to standard format floating
1485805Srrh * number, which will be done by accumulating
1495805Srrh * a binary exponent in bexponent, as we gradually
1505805Srrh * drive dexponent towards zero, one count at a time.
1515805Srrh */
1525805Srrh if (isclear(acc)){
1535805Srrh return(Acc);
1545805Srrh }
1555805Srrh bexponent = 0;
1565805Srrh
1575805Srrh /*
1585805Srrh * Scale the number down.
1595805Srrh * We must divide acc by 10 as many times as needed.
1605805Srrh */
1615805Srrh for (; dexponent < 0; dexponent++){
1625805Srrh /*
1635805Srrh * Align the number so that the most significant
1645805Srrh * bits are aligned in the most significant
1655805Srrh * bits of the accumulator, adjusting the
1665805Srrh * binary exponent as we shift.
1675805Srrh * The goal is to get the high order bit (NOT the
1685805Srrh * sign bit) set.
1695805Srrh */
1705805Srrh assert(((acc[HOC] & SIGNBIT) == 0), "Negative HOC");
1715805Srrh ovf = 0;
1725805Srrh
1735805Srrh for (j = 5; j >= 1; --j){
1745805Srrh i = 1 << (j - 1); /* 16, 8, 4, 2, 1 */
1755805Srrh quotient = ONES(i);
1765805Srrh quotient <<= (CH_BITS - 1) - i;
1775805Srrh while((acc[HOC] & quotient) == 0){
1785805Srrh ovf |= numshift((int)i, acc, acc);
1795805Srrh bexponent -= i;
1805805Srrh }
1815805Srrh }
1825805Srrh /*
1835805Srrh * Add 2 to the accumulator to effect rounding,
1845805Srrh * and get set up to divide by 5.
1855805Srrh */
1865805Srrh ovf = numaddd(acc, acc, 2);
1875805Srrh assert(ovf == 0, "Carry out of left rounding up by 2");
1885805Srrh /*
1895805Srrh * Divide the high order chunks by 5;
1905805Srrh * The last chunk will be divided by 10,
1915805Srrh * (to see what the remainder is, also to effect rounding)
1925805Srrh * and then multipiled by 2 to effect division by 5.
1935805Srrh */
1945805Srrh remainder = 0;
1955805Srrh #if DEBUGNATOF
1965805Srrh printf("Dividing: ");
1975805Srrh bignumprint(Acc);
1985805Srrh printf("\n");
1995805Srrh #endif DEBUGNATOF
2005805Srrh sptr = (short *)acc;
2015805Srrh for (i = (CH_N * 2 - 1); i >= 1; --i){
2025805Srrh /*
2035805Srrh * Divide (remainder:16).(acc[i]:16)
2045805Srrh * by 5, putting the quotient back
2055805Srrh * into acc[i]:16, and save the remainder
2065805Srrh * for the next iteration.
2075805Srrh */
2085805Srrh dividend = (remainder << 16) | (sptr[i] & ONES(16));
2095805Srrh assert(dividend >= 0, "dividend < 0");
2105805Srrh quotient = dividend / 5;
2115805Srrh remainder = dividend - (quotient * 5);
2125805Srrh sptr[i] = quotient;
2135805Srrh remainder = remainder;
2145805Srrh }
2155805Srrh /*
2165805Srrh * Divide the lowest order chunk by 10,
2175805Srrh * saving the remainder to decide how to round.
2185805Srrh * Then, multiply by 2, making it look as
2195805Srrh * if we divided by 10.
2205805Srrh * This multiply fills in a 0 on the least sig bit.
2215805Srrh */
2225805Srrh dividend = (remainder << 16) | (sptr[0] & ONES(16));
2235805Srrh assert(dividend >= 0, "dividend < 0");
2245805Srrh quotient = dividend / 10;
2255805Srrh remainder = dividend - (quotient * 10);
2265805Srrh sptr[0] = quotient + quotient;
2275805Srrh
2285805Srrh if (remainder >= 5)
2295805Srrh ovf = numaddd(acc, acc, 1);
2305805Srrh /*
2315805Srrh * Now, divide by 2, effecting division by 10,
2325805Srrh * merely by adjusting the binary exponent.
2335805Srrh */
2345805Srrh bexponent--;
2355805Srrh }
2365805Srrh /*
2375805Srrh * Scale the number up by multiplying by 10 as
2385805Srrh * many times as necessary
2395805Srrh */
2405805Srrh for (; dexponent > 0; dexponent--){
2415805Srrh /*
2425805Srrh * Compare high word to (2**31)/5,
2435805Srrh * and scale accordingly
2445805Srrh */
2455805Srrh while ( ((unsigned)acc[HOC]) > MAXINT_5){
2465805Srrh (void)numshift(-1, acc, acc);
2475805Srrh bexponent++;
2485805Srrh }
2495805Srrh /*
2505805Srrh * multiply the mantissa by 5,
2515805Srrh * and scale the binary exponent by 2
2525805Srrh */
2535805Srrh ovf = numshift(2, temp, acc);
2545805Srrh ovf |= numaddv(acc, acc, temp);
2555805Srrh assert(ovf == 0, "Scaling * 10 of manitissa");
2565805Srrh bexponent++;
2575805Srrh }
2585805Srrh /*
2595805Srrh * We now have:
2605805Srrh * a CH_N chunk length binary integer, right
2615805Srrh * justified (in native format).
2625805Srrh * a binary exponent.
2635805Srrh *
2645805Srrh * Now, we treat this large integer as an octa word
2655805Srrh * number, and unpack it into standard unpacked
2665805Srrh * format. That unpacking will give us yet
2675805Srrh * another binary exponent, which we adjust with
2685805Srrh * the accumulated binary exponent.
2695805Srrh */
2705805Srrh Acc.num_tag = TYPO;
2715805Srrh #if DEBUGNATOF
2725805Srrh printf("Octal number: ");
2735805Srrh bignumprint(Acc);
2745805Srrh printf("\n");
2755805Srrh #endif DEBUGNATOF
2765805Srrh Acc = bignumunpack(Acc, &ovf);
2775805Srrh
2785805Srrh if (ovf)
2795805Srrh errno = ERANGE;
2805805Srrh #if DEBUGNATOF
2815805Srrh printf("Unpacked octal number: ");
2825805Srrh bignumprint(Acc);
2835805Srrh printf("bexponent == %d\n", bexponent);
2845805Srrh #endif DEBUGNATOF
2855805Srrh Acc.num_exponent += bexponent;
2865805Srrh assert(Acc.num_sign == 0, "unpacked integer is < 0");
2875805Srrh Acc.num_sign = msign;
2885805Srrh /*
2895805Srrh * We now pack the number back into a radix format number.
2905805Srrh * This checks for overflow, underflow,
2915805Srrh * and rounds by 1/2 ulp.
2925805Srrh */
2935805Srrh ovf = 0;
2945805Srrh Acc = bignumpack(Acc, radix, &ovf);
2955805Srrh if (ovf)
2965805Srrh errno = ERANGE;
2975805Srrh #if DEBUGNATOF
2985805Srrh printf("packed number: ");
2995805Srrh bignumprint(Acc);
3005805Srrh printf("\n");
3015805Srrh #endif DEBUGNATOF
3025805Srrh return(Acc);
3035805Srrh }
3045805Srrh #if 0
3055805Srrh /*
3065805Srrh * Unfortunately, one can't use the ediv instruction to do
3075805Srrh * division on numbers with > 64 bits.
3085805Srrh * This is because ediv returns signed quantities;
3095805Srrh * if the quotient is an unsigned number > 2^31,
3105805Srrh * ediv sets integer overflow.
3115805Srrh */
3125805Srrh unsigned int ediv(high, low, divisor, qp, i)
3135805Srrh register unsigned int high; /* r11 */
3145805Srrh register unsigned int low; /* r10 */
3155805Srrh register unsigned int divisor; /* r9 */
3165805Srrh unsigned int *qp;
3175805Srrh {
3185805Srrh register unsigned int remainder; /* r8 */
3195805Srrh register unsigned int quotient; /* r7 */
3205805Srrh
3215805Srrh asm("ediv r9, r10, r7, r8 # Divide. q->r7, r->r8 (discarded)");
3225805Srrh *qp = quotient;
3235805Srrh return(remainder);
3245805Srrh }
3255805Srrh #endif 0
326