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