Mercurial > hg > index.cgi
comparison src/number.s @ 86:de42b8f77bc2
Fix problems related to parsing numbers (exponent, integers)
author | William Astle <lost@l-w.ca> |
---|---|
date | Mon, 16 Oct 2023 00:52:50 -0600 |
parents | 663d8e77b579 |
children | 3bfd978ddb39 |
comparison
equal
deleted
inserted
replaced
85:663d8e77b579 | 86:de42b8f77bc2 |
---|---|
125 ; 4b. If the number is an integer in the range of -0x80000000 to 0x7fffffff, it is converted to a signed binary integer | 125 ; 4b. If the number is an integer in the range of -0x80000000 to 0x7fffffff, it is converted to a signed binary integer |
126 ; and the result is returned | 126 ; and the result is returned |
127 ; 4b. Set the exponent correctly then normalize the result to val0 | 127 ; 4b. Set the exponent correctly then normalize the result to val0 |
128 val_parsenum lbeq SNERROR ; brif no numberr to parse | 128 val_parsenum lbeq SNERROR ; brif no numberr to parse |
129 ldd zero ; zero out digit accumulator | 129 ldd zero ; zero out digit accumulator |
130 stx fpa0+fpa.sig | 130 std fpa0+fpa.sig |
131 stx fpa0+fpa.sig+2 | 131 std fpa0+fpa.sig+2 |
132 stx fpa0+fpa.sig+4 | 132 std fpa0+fpa.sig+4 |
133 stx fpa0+fpa.sig+6 | 133 std fpa0+fpa.sig+6 |
134 stx fpa0+fpa.sig+8 | 134 std fpa0+fpa.sig+8 |
135 sta fpa0+fpa.sign ; set number sign to positive | 135 sta fpa0+fpa.sign ; set number sign to positive |
136 std fpaextra+4 ; clear out decimal exponent and sign | 136 std fpaextra+4 ; clear out decimal exponent and sign |
137 std fpaextra ; set digit count and decimal flag to zero and no decimal | 137 std fpaextra ; set digit count and decimal flag to zero and no decimal |
138 sta fpaextra+2 ; set decimal position to 0 - unused if decimal not seen | 138 sta fpaextra+2 ; set decimal position to 0 - unused if decimal not seen |
139 ldx #fpa0+fpa.sig ; point to digit storage location | 139 ldx #fpa0+fpa.sig ; point to digit storage location |
171 ldb fpaextra+2 ; get decimal position counter | 171 ldb fpaextra+2 ; get decimal position counter |
172 subb fpaextra+1 ; subtract decimal flag (will be 0xff or -1 if decimal seen) | 172 subb fpaextra+1 ; subtract decimal flag (will be 0xff or -1 if decimal seen) |
173 stb fpaextra+2 | 173 stb fpaextra+2 |
174 bra val_parsenum2 ; go handle another digit or whatever | 174 bra val_parsenum2 ; go handle another digit or whatever |
175 val_parsenum5 cmpa #'. ; decimal? | 175 val_parsenum5 cmpa #'. ; decimal? |
176 bne val_parsenum3 ; brif not | 176 bne val_parsenum6 ; brif not |
177 com fpaextra ; flag decimal seen | 177 com fpaextra ; flag decimal seen |
178 lbeq SNERROR ; brif already seen a decimal point - syntax error | 178 lbeq SNERROR ; brif already seen a decimal point - syntax error |
179 bra val_parsenum2 ; go parse more digits | 179 bra val_parsenum2 ; go parse more digits |
180 val_parsenum6 cmpa #'E ; decimal exponent? | 180 val_parsenum6 cmpa #'E ; decimal exponent? |
181 beq val_parsenum7 ; brif so | 181 beq val_parsenum7 ; brif so |
209 stb fpa0+fpa.exp ; set result exponent | 209 stb fpa0+fpa.exp ; set result exponent |
210 ; Normalization is not required here though rounding might be. Rounding will be handled during floating point return. | 210 ; Normalization is not required here though rounding might be. Rounding will be handled during floating point return. |
211 ; By ensuring there were no leading zeroes converted, the result is already pre-normalized without losing precision due | 211 ; By ensuring there were no leading zeroes converted, the result is already pre-normalized without losing precision due |
212 ; to an aribtrary number of leading zeroes. | 212 ; to an aribtrary number of leading zeroes. |
213 cmpb fpaextra ; is the exponent less than the number of digits? | 213 cmpb fpaextra ; is the exponent less than the number of digits? |
214 blt val_parsenum13 ; brif so - return floating point (signed comparison!) | 214 bgt val_parsenum13 ; brif so - return floating point (signed comparison!) |
215 cmpb #10 ; is exponent in the range for a binary integer? | 215 cmpb #10 ; is exponent in the range for a binary integer? |
216 bgt val_parsenum13 ; brif not - return floating point | 216 bgt val_parsenum13 ; brif not - return floating point |
217 ; Compare with 2147483648, the maximum *negative* value; note that this is a floating point comparison because we | 217 ; Compare with 2147483648, the maximum *negative* value; note that this is a floating point comparison because we |
218 ; already normalized everything above and it handles exponents properly | 218 ; already normalized everything above and it handles exponents properly |
219 lda fpa0+fpa.exp ; compare exponents (unbiased) | 219 lda fpa0+fpa.exp ; compare exponents (unbiased), exponent adjusted for above code |
220 cmpa #9 | 220 cmpa #10 |
221 bne val_parsenum12 | 221 bne val_parsenum12 |
222 ldx fpa0+fpa.sig ; compare top of significand | 222 ldx fpa0+fpa.sig ; compare top of significand |
223 cmpx #0x2147 | 223 cmpx #0x2147 |
224 bne val_parsenum12 | 224 bne val_parsenum12 |
225 ldx fpa0+fpa.sig+2 ; compare middle of significand | 225 ldx fpa0+fpa.sig+2 ; compare middle of significand |
231 blt val_parsenum14 ; brif it fits in a positive integer | 231 blt val_parsenum14 ; brif it fits in a positive integer |
232 ldb fpa0+fpa.sign ; negative? | 232 ldb fpa0+fpa.sign ; negative? |
233 bpl val_parsenum14 ; brif not - doesn't fit in integer | 233 bpl val_parsenum14 ; brif not - doesn't fit in integer |
234 val_parsenum13 lda #valtype_float ; set return value to floating point | 234 val_parsenum13 lda #valtype_float ; set return value to floating point |
235 sta val0+val.type | 235 sta val0+val.type |
236 lda fpa0+fpa.exp ; put the bias into the exponent | 236 lda fpa0+fpa.exp ; put the bias into the exponent but subtract one for leading digit |
237 adda #64 | 237 adda #63 |
238 sta fpa0+fpa.exp | 238 sta fpa0+fpa.exp |
239 ldy #val0+val.value ; normalize/round and return the result | 239 ldy #val0+val.value ; normalize/round and return the result |
240 jmp fps_normalize | 240 jmp fps_normalize |
241 val_parsenum14 lda #valtype_int ; set value type to integer | 241 val_parsenum14 lda #valtype_int ; set value type to integer |
242 sta val0+val.type | 242 sta val0+val.type |
243 ldb #9 ; exponent needed for decimal point to the right of significand | 243 ldb #10 ; exponent needed for decimal point to the right of significand |
244 subb fpa0+fpa.exp ; number of digit shifts needed to denormalize | 244 subb fpa0+fpa.exp ; number of digit shifts needed to denormalize |
245 beq val_parsenum16 ; brif already denormalized | 245 beq val_parsenum16 ; brif already denormalized |
246 lslb ; do 4 shifts per digit | 246 lslb ; do 4 shifts per digit |
247 lslb | 247 lslb |
248 val_parsenum15 lsr fpa0+fpa.sig ; shift a digit right | 248 val_parsenum15 lsr fpa0+fpa.sig ; shift a digit right |
251 ror fpa0+fpa.sig+3 | 251 ror fpa0+fpa.sig+3 |
252 ror fpa0+fpa.sig+4 | 252 ror fpa0+fpa.sig+4 |
253 decb ; done all shifts? | 253 decb ; done all shifts? |
254 bne val_parsenum15 | 254 bne val_parsenum15 |
255 ; Now convert BCD digit sequence in fpa0 significand to binary value in val0 | 255 ; Now convert BCD digit sequence in fpa0 significand to binary value in val0 |
256 val_parsenum16 ldb #40 ; 40 bit shifts needed for whole significand | 256 val_parsenum16 ldb #32 ; 40 bit shifts needed for whole significand |
257 stb fpa0+fpa.extra ; use extra precision byte as counter | 257 stb fpa0+fpa.extra ; use extra precision byte as counter |
258 val_parsenum17 lsl fpa0+fpa.sig+4 ; shift a bit into the binary result | 258 val_parsenum17 lsr fpa0+fpa.sig ; shift a bit into the binary result |
259 rol fpa0+fpa.sig+3 | 259 ror fpa0+fpa.sig+1 |
260 rol fpa0+fpa.sig+2 | 260 ror fpa0+fpa.sig+2 |
261 rol fpa0+fpa.sig+1 | 261 ror fpa0+fpa.sig+3 |
262 rol fpa0+fpa.sig | 262 ror fpa0+fpa.sig+4 |
263 rol val0+val.int+3 | 263 ror val0+val.int |
264 rol val0+val.int+2 | 264 ror val0+val.int+1 |
265 rol val0+val.int+1 | 265 ror val0+val.int+2 |
266 rol val0+val.int | 266 ror val0+val.int+3 |
267 ldx #fpa0+fpa.sig ; point to BCD digits | 267 ldx #fpa0+fpa.sig ; point to BCD digits |
268 val_parsenum18 lda ,x ; get byte to check | 268 val_parsenum18 lda ,x ; get byte to check |
269 beq val_parsenum20 ; short circuit check if digits are 0 | 269 beq val_parsenum20 ; short circuit check if digits are 0 |
270 anda #0x88 ; keep bit 3 of each digit; adjustment on >= 8 | 270 anda #0x88 ; keep bit 3 of each digit; adjustment on >= 8 |
271 lsra ; shift over and mulply by adjustment factor | 271 lsra ; shift over and mulply by adjustment factor |