Annotation of 43BSDReno/lib/libc/tahoe/stdlib/atof.s, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1988 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #if defined(LIBC_SCCS) && !defined(lint)
                     21:        .asciz "@(#)atof.s      5.3 (Berkeley) 6/1/90"
                     22: #endif /* LIBC_SCCS and not lint */
                     23: 
                     24: #include "DEFS.h"
                     25: 
                     26: /*
                     27:  *     atof: convert ascii to floating
                     28:  *
                     29:  *     C usage:
                     30:  *
                     31:  *             double atof (s)
                     32:  *             char *s;
                     33:  *
                     34:  *     Register usage:
                     35:  *
                     36:  *             r0-1:   value being developed
                     37:  *             r2:     first section: pointer to the next character
                     38:  *                     second section: binary exponent
                     39:  *             r3:     flags
                     40:  *             r4:     first section: the current character
                     41:  *                     second section: scratch
                     42:  *             r5:     the decimal exponent
                     43:  *             r6-7:   scratch
                     44:  */
                     45:        .set    msign,0         # mantissa has negative sign
                     46:        .set    esign,1         # exponent has negative sign
                     47:        .set    decpt,2         # decimal point encountered
                     48: 
                     49: ENTRY(atof, R6|R7)
                     50: /*
                     51:  *     Initialization
                     52:  */
                     53:        clrl    r3              # All flags start out false
                     54:        movl    4(fp),r2        # Address the first character
                     55:        clrl    r5              # Clear starting exponent
                     56: /*
                     57:  *     Skip leading white space
                     58:  */
                     59: sk0:   movzbl  (r2),r4         # Fetch the next (first) character
                     60:        incl    r2
                     61:        cmpb    $' ,r4          # Is it blank?
                     62:        beql    sk0             #   ...yes
                     63:        cmpb    r4,$8           # 8 is lowest of white-space group
                     64:        blss    sk1             # Jump if char too low to be white space
                     65:        cmpb    r4,$13          # 13 is highest of white-space group
                     66:        bleq    sk0             # Jump if character is white space
                     67: sk1:
                     68: /*
                     69:  *     Check for a sign
                     70:  */
                     71:        cmpb    $'+,r4          # Positive sign?
                     72:        beql    cs1             #   ... yes
                     73:        cmpb    $'-,r4          # Negative sign?
                     74:        bneq    cs2             #   ... no
                     75:        orb2    $1<msign,r3     # Indicate a negative mantissa
                     76: cs1:   movzbl  (r2),r4         # Skip the character
                     77:        incl    r2
                     78: cs2:
                     79: /*
                     80:  *     Accumulate digits, keeping track of the exponent
                     81:  */
                     82:        clrl    r1
                     83:        clrl    r0              # Clear the accumulator
                     84: ad0:   cmpb    r4,$'0          # Do we have a digit?
                     85:        blss    ad4             #   ... no, too small
                     86:        cmpb    r4,$'9
                     87:        bgtr    ad4             #   ... no, too large
                     88: /*
                     89:  *     We got a digit.  Accumulate it
                     90:  */
                     91:        cmpl    r0,$214748364   # Would this digit cause overflow?
                     92:        bgeq    ad1             #   ... yes
                     93: /*
                     94:  *     Multiply (r0,r1) by 10.  This is done by developing
                     95:  *     (r0,r1)*2 in (r6,r7), shifting (r0,r1) left three bits,
                     96:  *     and adding the two quadwords.
                     97:  */
                     98:        shlq    $1,r0,r6        # (r6,r7)=(r0,r1)*2
                     99:        shlq    $3,r0,r0        # (r0,r1)=(r0,r1)*8
                    100:        addl2   r7,r1           # Add low halves
                    101:        adwc    r6,r0           # Add high halves
                    102: /*
                    103:  *     Add in the digit
                    104:  */
                    105:        subl2   $'0,r4          # Get the digit value
                    106:        addl2   r4,r1           # Add it into the accumulator
                    107:        adwc    $0,r0           # Possible carry into high half
                    108:        brb     ad2             # Join common code
                    109: /*
                    110:  *     Here when the digit won't fit in the accumulator
                    111:  */
                    112: ad1:   incl    r5              # Ignore the digit, bump exponent
                    113: /*
                    114:  *     If we have seen a decimal point, decrease the exponent by 1
                    115:  */
                    116: ad2:   bbc     $decpt,r3,ad3   # Jump if decimal point not seen
                    117:        decl    r5              # Decrease exponent
                    118: ad3:
                    119: /*
                    120:  *     Fetch the next character, back for more
                    121:  */
                    122:        movzbl  (r2),r4         # Fetch
                    123:        incl    r2
                    124:        brb     ad0             # Try again
                    125: /*
                    126:  *     Not a digit.  Could it be a decimal point?
                    127:  */
                    128: ad4:   cmpb    r4,$'.          # If it's not a decimal point, either it's
                    129:        bneq    ad5             #   the end of the number or the start of
                    130:                                #   the exponent.
                    131:        bbs     $decpt,r3,ad5
                    132:        orb2    $1<decpt,r3     # If it IS a decimal point, we record that
                    133:        brb     ad3             #   we've seen one, and keep collecting
                    134:                                #   digits if it is the first one.
                    135:                        
                    136: /*
                    137:  *     Check for an exponent
                    138:  */
                    139: ad5:   clrl    r6              # Initialize the exponent accumulator
                    140: 
                    141:        cmpb    r4,$'e          # We allow both lower case e
                    142:        beql    ex1             #   ... and ...
                    143:        cmpb    r4,$'E          #   upper-case E
                    144:        bneq    ex7
                    145: /*
                    146:  *     Does the exponent have a sign?
                    147:  */
                    148: ex1:   movzbl  (r2),r4         # Get next character
                    149:        incl    r2
                    150:        cmpb    r4,$'+          # Positive sign?
                    151:        beql    ex2             #   ... yes ...
                    152:        cmpb    r4,$'-          # Negative sign?
                    153:        bneq    ex3             #   ... no ...
                    154:        orb2    $1<esign,r3     # Indicate exponent is negative
                    155: ex2:   movzbl  (r2),r4         # Grab the next character
                    156:        incl    r2
                    157: /*
                    158:  *     Accumulate exponent digits in r6
                    159:  */
                    160: ex3:   cmpb    r4,$'0          # A digit is within the range
                    161:        blss    ex4             # '0' through
                    162:        cmpb    r4,$'9          # '9',
                    163:        bgtr    ex4             # inclusive.
                    164:        cmpl    r6,$214748364   # Exponent outrageously large already?
                    165:        bgeq    ex2             #   ... yes
                    166:        moval   (r6)[r6],r6     # r6 *= 5
                    167:        movaw   -'0(r4)[r6],r6  # r6 = r6 * 2 + r4 - '0'
                    168:        brb     ex2             # Go 'round again
                    169: ex4:
                    170: /*
                    171:  *     Now get the final exponent and force it within a reasonable
                    172:  *     range so our scaling loops don't take forever for values
                    173:  *     that will ultimately cause overflow or underflow anyway.
                    174:  *     A tight check on over/underflow will be done by ldexp.
                    175:  */
                    176:        bbc     $esign,r3,ex5   # Jump if exponent not negative
                    177:        mnegl   r6,r6           # If sign, negate exponent
                    178: ex5:   addl2   r6,r5           # Add given exponent to calculated exponent
                    179:        cmpl    r5,$-100        # Absurdly small?
                    180:        bgtr    ex6             #   ... no
                    181:        movl    $-100,r5        #   ... yes, force within limit
                    182: ex6:   cmpl    r5,$100         # Absurdly large?
                    183:        blss    ex7             #   ... no
                    184:        movl    $100,r5         #   ... yes, force within bounds
                    185: ex7:
                    186: /*
                    187:  *     Our number has now been reduced to a mantissa and an exponent.
                    188:  *     The mantissa is a 63-bit positive binary integer in r0,r1,
                    189:  *     and the exponent is a signed power of 10 in r5.  The msign
                    190:  *     bit in r3 will be on if the mantissa should ultimately be
                    191:  *     considered negative.
                    192:  *
                    193:  *     We now have to convert it to a standard format floating point
                    194:  *     number.  This will be done by accumulating a binary exponent
                    195:  *     in r2, as we progressively get r5 closer to zero.
                    196:  *
                    197:  *     Don't bother scaling if the mantissa is zero
                    198:  */
                    199:        tstl    r1
                    200:        bneq    1f
                    201:        tstl    r0              # Mantissa zero?
                    202:        jeql    exit            #   ... yes
                    203: 
                    204: 1:     clrl    r2              # Initialize binary exponent
                    205:        tstl    r5              # Which way to scale?
                    206:        bleq    sd0             # Scale down if decimal exponent <= 0
                    207: /*
                    208:  *     Scale up by "multiplying" r0,r1 by 10 as many times as necessary,
                    209:  *     as follows:
                    210:  *
                    211:  *     Step 1: Shift r0,r1 right as necessary to ensure that no
                    212:  *     overflow can occur when multiplying.
                    213:  */
                    214: su0:   cmpl    r0,$429496729   # Compare high word to (2**31)/5
                    215:        blss    su1             # Jump out if guaranteed safe
                    216:        shrq    $1,r0,r0        # Else shift right one bit
                    217:        incl    r2              #    bump exponent to compensate
                    218:        brb     su0             #    and go back to test again.
                    219: /*
                    220:  *     Step 2: Multiply r0,r1 by 5, by appropriate shifting and
                    221:  *     double-precision addition
                    222:  */
                    223: su1:   shlq    $2,r0,r6        # (r6,r7) := (r0,r1) * 4
                    224:        addl2   r7,r1           # Add low-order halves
                    225:        adwc    r6,r0           #   and high-order halves
                    226: /*
                    227:  *     Step 3: Increment the binary exponent to take care of the final
                    228:  *     factor of 2, and go back if we still need to scale more.
                    229:  */
                    230:        incl    r2              # Increment the exponent
                    231:        decl    r5              # ...sobgtr r5,su0
                    232:        bgtr    su0             #    and back for more (maybe)
                    233: 
                    234:        brb     cm0             # Merge to build final value
                    235: 
                    236: /*
                    237:  *     Scale down.  We must "divide" r0,r1 by 10 as many times
                    238:  *     as needed, as follows:
                    239:  *
                    240:  *     Step 0: Right now, the condition codes reflect the state
                    241:  *     of r5.  If it's zero, we are done.
                    242:  */
                    243: sd0:   beql    cm0             # If finished, build final number
                    244: /*
                    245:  *     Step 1: Shift r0,r1 left until the high-order bit (not counting
                    246:  *     the sign bit) is nonzero, so that the division will preserve
                    247:  *     as much precision as possible.
                    248:  */
                    249:        tstl    r0              # Is the entire high-order half zero?
                    250:        bneq    sd2             #   ...no, go shift one bit at a time
                    251:        shlq    $30,r0,r0       #   ...yes, shift left 30,
                    252:        subl2   $30,r2          #   decrement the exponent to compensate,
                    253:                                #   and now it's known to be safe to shift
                    254:                                #   at least once more.
                    255: sd1:   shlq    $1,r0,r0        # Shift (r0,r1) left one, and
                    256:        decl    r2              #   decrement the exponent to compensate
                    257: sd2:   bbc     $30,r0,sd1      # If the high-order bit is off, go shift
                    258: /*
                    259:  *     Step 2: Divide the high-order part of (r0,r1) by 5,
                    260:  *     giving a quotient in r1 and a remainder in r7.
                    261:  */
                    262: sd3:   movl    r0,r7           # Copy the high-order part
                    263:        clrl    r6              # Zero-extend to 64 bits
                    264:        ediv    $5,r6,r0,r6     # Divide (cannot overflow)
                    265: /*
                    266:  *     Step 3: Divide the low-order part of (r0,r1) by 5,
                    267:  *     using the remainder from step 2 for rounding.
                    268:  *     Note that the result of this computation is unsigned,
                    269:  *     so we have to allow for the fact that an ordinary division
                    270:  *     by 5 could overflow.  We make allowance by dividing by 10,
                    271:  *     multiplying the quotient by 2, and using the remainder
                    272:  *     to adjust the modified quotient.
                    273:  */
                    274:        addl3   $2,r1,r7        # Dividend is low part of (r0,r1) plus
                    275:        adwc    $0,r6           #  2 for rounding plus
                    276:                                #  (2**32) * previous remainder
                    277:        ediv    $10,r6,r1,r7    # r1 := quotient, r7 := remainder.
                    278:        addl2   r1,r1           # Make r1 result of dividing by 5
                    279:        cmpl    r7,$5           # If remainder is 5 or greater,
                    280:        blss    sd4             #   increment the adjustted quotient.
                    281:        incl    r1
                    282: /*
                    283:  *     Step 4: Increment the decimal exponent, decrement the binary
                    284:  *     exponent (to make the division by 5 into a division by 10),
                    285:  *     and back for another iteration.
                    286:  */
                    287: sd4:   decl    r2              # Binary exponent
                    288:        aoblss  $0,r5,sd2
                    289: /*
                    290:  *     We now have the following:
                    291:  *
                    292:  *     r0:     high-order half of a 64-bit integer
                    293:  *     r1:     load-order half of the same 64-bit integer
                    294:  *     r2:     a binary exponent
                    295:  *
                    296:  *     Our final result is the integer represented by (r0,r1)
                    297:  *     multiplied by 2 to the power contained in r2.
                    298:  *     We will transform (r0,r1) into a floating-point value,
                    299:  *     set the sign appropriately, and let ldexp do the
                    300:  *     rest of the work.
                    301:  *
                    302:  *     Step 1: if the high-order bit (excluding the sign) of
                    303:  *     the high-order half (r0) is 1, then we have 63 bits of
                    304:  *     fraction, too many to convert easily.  However, we also
                    305:  *     know we won't need them all, so we will just throw the
                    306:  *     low-order bit away (and adjust the exponent appropriately).
                    307:  */
                    308: cm0:   bbc     $30,r0,cm1      # jump if no adjustment needed
                    309:        shrq    $1,r0,r0        # lose the low-order bit
                    310:        incl    r2              # increase the exponent to compensate
                    311: /*
                    312:  *     Step 2: split the 62-bit number in (r0,r1) into two
                    313:  *     31-bit positive quantities
                    314:  */
                    315: cm1:   shlq    $1,r0,r0        # put the high-order bits in r0
                    316:                                #   and a 0 in the bottom of r1
                    317:        shrl    $1,r1,r1        # right-justify the bits in r1
                    318:                                #   moving 0 into the sign bit.
                    319: /*
                    320:  *     Step 3: convert both halves to floating point
                    321:  */
                    322:        cvld    r1
                    323:        std     r6              # low-order part in r6-r7
                    324:        cvld    r0
                    325:        std     r0              # high-order part in r0-r1
                    326: /*
                    327:  *     Step 4: multiply the high order part by 2**31 and combine them
                    328:  */
                    329:        ldd     two31
                    330:        muld    r0              # multiply
                    331:        addd    r6              # combine
                    332: /*
                    333:  *     Step 5: if appropriate, negate the floating value
                    334:  */
                    335:        bbc     $msign,r3,cm2   # Jump if mantissa not signed
                    336:        negd                    # If negative, make it so
                    337: /*
                    338:  *     Step 6: call ldexp to complete the job
                    339:  */
                    340: cm2:   pushl   r2              # Put exponent in parameter list
                    341:        pushd                   #    and also mantissa
                    342:        calls   $3,_ldexp       # go combine them
                    343: 
                    344: exit:
                    345:        ret
                    346: 
                    347:        .align  2
                    348: two31: .long   0x50000000      # (=2147483648) 2 ** 31 in floating-point
                    349:        .long   0               # so atof doesn't have to convert it

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.