Annotation of 43BSDTahoe/lib/libc/gen/gen.vax/atof.s, revision 1.1

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