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