diff --git a/c64/basic/,aliases.s b/c64/basic/,aliases.s index c2e3bf27..9ca68d2d 100644 --- a/c64/basic/,aliases.s +++ b/c64/basic/,aliases.s @@ -8,6 +8,26 @@ .alias tokenise_work4 $F .alias temp_string_ptr $35 .alias load_or_verify_or_tokenise_work5 $C + .alias basic_work22 $22 + .alias basic_work23 $23 + .alias basic_work24 $24 + .alias basic_work25 $25 + + .alias basic_numeric_work_area $57 ; $57 - $60 inclusive = 10 bytes + + ;; Floating point accumulator 1 $61 - $68 + .alias basic_fac1_exponent $61 + .alias basic_fac1_mantissa $62 ; $62 - $65 + .alias basic_fac1_sign $66 + .alias basic_fac1_overflow $68 + .alias basic_fac1_mantissa_lob $70 + + .alias basic_fac2_exponent $69 + .alias basic_fac2_mantissa $6A ; $6A - $6D + .alias basic_fac2_sign $6E + + + .alias TXTTAB $2B .alias IOSTATUS $90 diff --git a/c64/basic/fac1_mul.s b/c64/basic/fac1_mul.s new file mode 100644 index 00000000..0a5ea84b --- /dev/null +++ b/c64/basic/fac1_mul.s @@ -0,0 +1,98 @@ + ;; Multiply Floating Point Accumulator by 10 + ;; = 8x + 2x + ;; Implement by shifting MAC left one bit, + ;; and then keeping that value to add on after + ;; shifting two more bits left. + ;; This should be done using basic_fac1_overflow to + ;; hold the overflow bits, so that the result can + ;; be exponent adjusted after, if required. + +fac1_mul10: + lda #$00 + sta basic_fac1_overflow + + ;; Multiply mantissa by 2 + jsr fac1_mantissa_mul2 + + ;; copy down to BASIC numeric work area at $57 + ;; (basic_numeric_work_area) + ;; (We copy all 7 bytes off the FAC1, so that we have + ;; the overflow bits, and the copy is as small as possible) + ldx #7 +f1m10_l1: + lda basic_fac1_mantissa,x + sta basic_numeric_work_area,x + dex + bpl f1m10_l1 + + ;; Multiply mantissa by 4, so it is now 8x original + jsr fac1_mantissa_mul2 + jsr fac1_mantissa_mul2 + + ;; Now add stored value of 2x to it, to get the total x10 + ldy #3 + ldx #0 + clc +f1m10_l2: + lda basic_fac1_mantissa,x + adc basic_numeric_work_area,x + sta basic_fac1_mantissa,x + inx + dey + bpl f1m10_l2 + lda basic_fac1_overflow + adc basic_numeric_work_area+7 + sta basic_fac1_overflow + + ;; Now shift right and increase exponent until overflow + ;; bits = $00 +f1m10_l3: + lda basic_fac1_overflow + bne + + ;; All done, return + clc + rts + + ;; Divide mantissa by two, and increment exponent + jsr fac1_mantissa_div2 + inc basic_fac1_exponent + lda basic_fac1_exponent + bpl f1m10_l3 + ;; Exponent has bit 7 set, so has wrapped. + ;; = OVERFLOW ERROR + lda #14 + jmp do_basic_error + +fac1_mantissa_mul2: + ldy #3 + ldx #0 + clc +f1m1_l1: + ;; Multiply mantissa by 2, and store overflow + ;; in basic_fac1_bits + lda basic_fac1_mantissa,x + rol + sta basic_fac1_mantissa,x + inx + dey + bpl f1m1_l1 + lda basic_fac1_overflow + rol + sta basic_fac1_overflow + + rts + +fac1_mantissa_div2: + ;; Divide mantissa by 2, including using overflow bits + clc + lda basic_fac1_overflow + ror + sta basic_fac1_overflow + ldy #3 +f1md2_l1: + lda basic_fac1_mantissa,y + ror + sta basic_fac1_mantissa,y + dey + bpl f1md2_l1 + rts diff --git a/c64/basic/inject_number.s b/c64/basic/inject_number.s new file mode 100644 index 00000000..79081596 --- /dev/null +++ b/c64/basic/inject_number.s @@ -0,0 +1,111 @@ + ;; Parse a number from the input buffer at $0200+tokenise_work1 + ;; Result is put into FAC1. + ;; tokenise_work1 is updated with first position after the number. + + ;; XXX - Remember decimal position and exponent, and apply them + ;; after to produce normalised floating point number. + +ij_not_a_digit: + ;; XXX check for ".", "E", "+" and "-" + ;; Other chars terminate the accumulation. + CLC + RTS + +inject_number: + ;; Clear FAC1 + jsr erase_fac1 + + ;; Clear decimal position flag + lda #$ff + sta tokenise_work2 + + ;; Check if leading char is a - sign + ;; Note: the - will have been tokenised to $AB + ;; XXX - implement + +ij_loop1: + ldx tokenise_work1 + lda $0200,x + cmp #$30 + bcc ij_not_a_digit + cmp #$39 + bcs ij_not_a_digit + + ;; It is a digit + + ;; Only add digit if we have not overflowed the accuracy of + ;; the mantissa + lda basic_fac1_exponent + beq ij_accept_precision + + ;; We have an extra digit after saturating our precision. + ;; Thus we should ignore the digit, and just multiply the FAC + ;; by 10, but only if we have not seen a decimal point. + ;; If we have seen a decimal point, then we can completely ignore + ;; the digit, as it is contributing not recordable information + + lda tokenise_work2 + cmp #$ff + bne ij_seen_decimal_point + + jsr fac1_mul10 + ;; Fall through +ij_seen_decimal_point: + jmp ij_consider_next_digit + +ij_accept_precision: + ;; We can accept more precision, so multiply the mantissa by 10, so that + ;; we can add the new digit in + jsr fac1_mul10 + + lda basic_fac1_exponent + bne ij_consider_next_digit + + ;; Get digit + ldx tokenise_work1 + lda $0200,x + sec + sbc #$30 + + ;; Add to FAC1 mantissa + clc + adc basic_fac1_mantissa+0 + sta basic_fac1_mantissa+0 + ldx #1 + ldy #3 +ij_loop2: + lda basic_fac1_mantissa,x + adc #$00 + sta basic_fac1_mantissa+1,x + inx + dey + bne ij_loop2 + + bcc + + ;; Carry set, so we have overflowed. + ;; We should shift everything right one digit, and increase + ;; the exponent by one. The non-zero exponent tells us that we + ;; can't fit any more precision in. + jsr fac1_mantissa_div2 +* + +ij_consider_next_digit: + ;; Consider next digit + inc tokenise_work1 + jmp ij_loop1 + + rts + + +erase_fac1: + lda #$00 + ldx #7 +* + sta basic_fac1_exponent,x + dex + bpl - + sta basic_fac1_mantissa_lob + + rts + +