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

Defined functions

_atof defined in line 36; used 80 times
ad0 defined in line 68; used 1 times
ad1 defined in line 96; used 1 times
  • in line 76
ad2 defined in line 100; used 1 times
  • in line 92
ad3 defined in line 102; used 2 times
ad4 defined in line 111; used 2 times
ad5 defined in line 120; used 1 times
cm0 defined in line 284; used 2 times
cm1 defined in line 291; used 1 times
cm2 defined in line 314; used 1 times
cs1 defined in line 62; used 1 times
  • in line 58
cs2 defined in line 63; used 1 times
  • in line 60
ex1 defined in line 129; used 1 times
ex2 defined in line 135; used 3 times
ex3 defined in line 139; used 1 times
ex4 defined in line 148; used 2 times
ex5 defined in line 157; used 1 times
ex6 defined in line 161; used 1 times
ex7 defined in line 164; used 2 times
exit defined in line 318; used 1 times
sd0 defined in line 219; used 1 times
sd1 defined in line 231; used 1 times
sd2 defined in line 233; used 2 times
sd3 defined in line 238; never used
sd4 defined in line 263; used 1 times
sk0 defined in line 46; used 2 times
sk1 defined in line 53; used 1 times
  • in line 50
su0 defined in line 191; used 2 times
su1 defined in line 200; used 1 times
two31 defined in line 322; used 1 times
Last modified: 1986-03-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1527
Valid CSS Valid XHTML 1.0 Strict