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