|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.