diff --git a/STATUS.md b/STATUS.md index 4c0b23c7..50e67779 100644 --- a/STATUS.md +++ b/STATUS.md @@ -248,7 +248,7 @@ Floating point mathematical routines - not official, but well known and broadly | `$BC9B` | `QINT` | DONE | From the Microsoft BASIC, original name: QINT | | `$BCCC` | `int_FAC1` | DONE | From the Microsoft BASIC, original name: INT | | `$BCE9` | `clear_FAC1` | DONE | From the Microsoft BASIC, original name: CLRFAC | -| `$BCF3` | `FIN` | PARTIAL | Only for 38k memory model + not fully tested yet | +| `$BCF3` | `FIN` | DOME | From the Microsoft BASIC Only for 38k memory model | | `$BD7E` | `FINLOG` | DONE | From the Microsoft BASIC, original name: FINLOG | | `$BDDD` | `FOUT` | DONE | From the Microsoft BASIC, original name: FOUT | | `$BF71` | `sqr_FAC1` | DONE | From the Microsoft BASIC, original name: SQR | diff --git a/src/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s index c1a01b9e..b8abe603 100644 --- a/src/aliases/,aliases_ram_lowmem.s +++ b/src/aliases/,aliases_ram_lowmem.s @@ -63,6 +63,8 @@ !addr TEMPF2 = $5C ; $5C-$60 BASIC numeric work area !addr DECCNT = $5D ; Number of digits after decimal point !addr TENEXP = $5E ; Exponent count + !addr DPTFLG = $5F ; Decimal point flag for FIN + !addr EXPSGN = $60 ; Exponent sign for FIN !addr __FAC1 = $61 ; $61-$66 floating point accumulator 1 !addr FAC1_exponent = $61 !addr FAC1_mantissa = $62 ; $62 - $65 diff --git a/src/basic/math/FIN.s b/src/basic/math/FIN.s deleted file mode 100644 index baf3a2dd..00000000 --- a/src/basic/math/FIN.s +++ /dev/null @@ -1,152 +0,0 @@ -;; #LAYOUT# STD * #TAKE -;; #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -;; #LAYOUT# * BASIC_0 #TAKE -;; #LAYOUT# * * #IGNORE - -; -; Math package - imports string to FAC1, ignores spaces -; -; -; Input: -; - .A needs to be loaded with first char of the string -; - Carry flag must be clear -; - string address in $7A/$7B -; -; See also: -; - [CM64] Computes Mapping the Commodore 64 - page 116 -; - https://www.c64-wiki.com/wiki/Floating_point_arithmetic -; - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics -; - -!ifdef CONFIG_MEMORY_MODEL_38K { -; NOTE: Currently CHRGET is only available for the 38K model and the equivalent function -; does not test for digits to set carry - -FIN_NUMDEC = TEMPF2 -FIN_DIGIT = TEMPF2 + 1 -FIN_DECFOUND = TEMPF2 + 2 -FIN_EXPSIGN = TEMPF2 + 3 -FIN_EXP = TEMPF2 + 4 - - -FIN: - ldx #$00 - stx SGNFLG ; Sign is positive - stx FIN_DECFOUND ; Decimal point not found - stx FIN_EXP ; Exponent - stx FAC1_exponent ; FAC1 <- 0 - bcc FIN_loop ; Starting with digit - cmp #$2D ; Is minus? - bne @1 - dec SGNFLG - bne FIN_next ; Will always branch - -@1: cmp #$2B ; Is plus? - beq FIN_next - -FIN_loop: - bcs FIN_nonnumeric - sec - sbc #48 ; Convert to number - sta FIN_DIGIT - jsr mul10_FAC1 - lda FIN_DIGIT - jsr FINLOG - lda FIN_DECFOUND ; Have we passed the decimal sign? - bpl FIN_next - inc FIN_NUMDEC - -FIN_next: - jsr CHRGET - +bra FIN_loop - -FIN_nonnumeric: - cmp #$2E ; decimal point - beq FIN_decimal - cmp #$45 ; E - beq FIN_exponent -FIN_finalize: - lda FIN_EXP - sec - sbc FIN_NUMDEC - sta FIN_EXP - bmi FIN_div_loop - -FIN_mul_loop: - dec FIN_EXP - bmi FIN_out - jsr mul10_FAC1 - +bra FIN_mul_loop - -FIN_div_loop: - jsr div10_FAC1_p - inc FIN_EXP - bne FIN_div_loop - -FIN_out: - lda SGNFLG - sta FAC1_sign - rts - -FIN_decimal: - lda FIN_DECFOUND - bmi FIN_finalize - dec FIN_DECFOUND ; Indicate found decimal point - sta FIN_NUMDEC ; Number of decimal places = 0 - +bra FIN_next - -FIN_exponent: - ldx #0 - stx FIN_EXPSIGN - jsr CHRGET - bcc FIN_exp_loop - cmp #$2D ; Is minus? - bne @1 - dec FIN_EXPSIGN - bne FIN_exp_next ; Always branches -@1: cmp #$2B ; Is plus? - beq FIN_exp_next - bne FIN_done_exp - -FIN_exp_loop: - tax - lda FIN_EXP - cmp #10 - bcs FIN_exp_limit - asl ; Multiply by 10 - sta FIN_EXP - asl - asl - clc - adc FIN_EXP - sta FIN_EXP - txa - sec - sbc #48 ; Convert to number - clc - adc FIN_EXP - sta FIN_EXP - -FIN_exp_next: - jsr CHRGET - bcc FIN_exp_loop - -FIN_done_exp: - lda FIN_EXP - bpl FIN_finalize - eor #$FF - tax - inx - stx FIN_EXP - +bra FIN_finalize - -FIN_exp_limit: - ldx FIN_EXPSIGN - bmi FIN_zero - jmp do_OVERFLOW_error - -FIN_zero: - ldx #0 - stx FAC1_exponent - rts - } diff --git a/src/basic/math/bcf3.FIN.jmp.s b/src/basic/math/bcf3.FIN.jmp.s deleted file mode 100644 index 1a4b9147..00000000 --- a/src/basic/math/bcf3.FIN.jmp.s +++ /dev/null @@ -1,12 +0,0 @@ -;; #LAYOUT# STD * #TAKE -;; #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -;; #LAYOUT# * BASIC_0 #TAKE -;; #LAYOUT# * * #IGNORE - -; Just a compatibility jump - our routine is longer than original one - -!ifdef CONFIG_MEMORY_MODEL_38K { - jmp FIN -} else { - +STUB_IMPLEMENTATION -} diff --git a/src/basic/math/bcf3.FIN.s b/src/basic/math/bcf3.FIN.s new file mode 100644 index 00000000..a3409280 --- /dev/null +++ b/src/basic/math/bcf3.FIN.s @@ -0,0 +1,130 @@ +;; #LAYOUT# STD * #TAKE +;; #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 +;; #LAYOUT# * BASIC_0 #TAKE +;; #LAYOUT# * * #IGNORE + +; This file is under the MIT license, it contains code released by Microsoft Corporation. +; See LICENSE for more information. + +; Math package - imports string to FAC1, ignores spaces +; +; This is verified to be identical to the original Microsoft implementation where it was named FIN. +; +; Input: +; - .A needs to be loaded with first char of the string +; - Carry flag must be clear +; - string address in $7A/$7B +; +; See also: +; - [CM64] Computes Mapping the Commodore 64 - page 116 +; - https://www.c64-wiki.com/wiki/Floating_point_arithmetic +; - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics +; + +; NUMBER INPUT IS LEFT IN FAC. +; AT ENTRY [TXTPTR] POINTS TO THE FIRST CHARACTER IN A TEXT BUFFER. +; THE FIRST CHARACTER IS ALSO IN ACCA. FIN PACKS THE DIGITS +; INTO THE FAC AS AN INTEGER AND KEEPS TRACK OF WHERE THE +; DECIMAL POINT IS. [DPTFLG] TELL WHETHER A DP HAS BEEN +; SEEN. [DECCNT] IS THE NUMBER OF DIGITS AFTER THE DP. +; AT THE END [DECCNT] AND THE EXPONENT ARE USED TO +; DETERMINE HOW MANY TIMES TO MULTIPLY OR DIVIDE BY TEN +; TO GET THE CORRECT NUMBER. + + +!ifdef CONFIG_MEMORY_MODEL_38K { + +FIN: + ldy #0 ; Zero FAC1_sign and SGNFLG + ldx #10 ; Zero exp and hi bytes +FINZLP: + sty DECCNT,X ; Zero low bytes + dex ; Zero TENEXP and EXPSGN + bpl FINZLP ; Zero DECCNT, DPTFLG + bcc FINDGQ ; Flags still set from CHRGET + cmp #'-' ; A negative sign? + bne QPLUS ; No, try plus sign + stx SGNFLG ; It's negative + beq FINC ; Always branches +QPLUS: + cmp #'+' ; Plus sign? + bne FIN1 ; Yes, skip it +FINC: + jsr CHRGET +FINDGQ: + bcc FINDIG +FIN1: + cmp #'.' ; The decimal point? + beq FINDP ; No kidding + cmp #'E' ; Exponent follows + bne FINE ; No + ;HERE TO CHECK FOR SIGN OF EXP. + jsr CHRGET ; Yes, Get another + bcc FNEDG1 ; It is a digit. (Easier than backing up pointer) + cmp #$AB ; Minus with sign set (from table) + beq FINEC1 ; Negate + cmp #'-' ; Minus sign? + beq FINEC1 + cmp #$AA ; Plus with sign set (from table) + beq FINEC + cmp #'+' ; Plus sign? + beq FINEC + bne FINEC2 +FINEC1: + ror EXPSGN ; Turn it on +FINEC: + jsr CHRGET ; Get another +FNEDG1: + bcc FINEDG ; It is a digit +FINEC2: + bit EXPSGN + bpl FINE + lda #0 + sec + sbc TENEXP + jmp FINE1 +FINDP: + ror DPTFLG + bit DPTFLG + bvc FINC +FINE: + lda TENEXP +FINE1: + sec + sbc DECCNT ; Get number of places to shift + sta TENEXP + beq FINQNG ; Negate? + bpl FINMUL ; Positive so multiply +FINDIV: + jsr div10_FAC1_p + inc TENEXP ; Done? + bne FINDIV ; No + beq FINQNG ; Yes +FINMUL: + jsr mul10_FAC1 + dec TENEXP ; Done + bne FINMUL ; No +FINQNG: + lda SGNFLG + bmi NEGXQS ; If positive, Return + rts +NEGXQS: + jmp toggle_sign_FAC1 ; Otherwise, negate and return + +FINDIG: + pha + bit DPTFLG + bpl FINDG1 + inc DECCNT +FINDG1: + jsr mul10_FAC1 + pla ; Get it back + sec + sbc #'0' + jsr FINLOG ; Add it in + jmp FINC + + +} else { + +STUB_IMPLEMENTATION +} diff --git a/src/basic/math/bd91.FINEDG.s b/src/basic/math/bd91.FINEDG.s new file mode 100644 index 00000000..54920029 --- /dev/null +++ b/src/basic/math/bd91.FINEDG.s @@ -0,0 +1,43 @@ +;; #LAYOUT# STD * #TAKE +;; #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 +;; #LAYOUT# * BASIC_0 #TAKE +;; #LAYOUT# * * #IGNORE + +; This file is under the MIT license, it contains code released by Microsoft Corporation. +; See LICENSE for more information. + +; Math package - add an ASCII digit in A that has been converted to a signed integer to FAC1 +; +; This is verified to be identical to the original Microsoft implementation where it was named FINEDG. +; + +; HERE PACK IN THE NEXT DIGIT OF THE EXPONENT. +; MULTIPLY THE OLD EXP BY 10 AND ADD IN THE NEXT +; DIGIT. NOTE: EXP OVERFLOW IS NOT CHECKED FOR. + +!ifdef CONFIG_MEMORY_MODEL_38K { + +FINEDG: + lda TENEXP ; Get exp so far + cmp #10 ; Will result be >= 100 + bcc MLEX10 + lda #100 ; Get 100 + bit EXPSGN + bmi MLEXMI ; If neg exp, no check for overflow + jmp overflow_error +MLEX10: + asl ; Mult by 2 twice + asl + clc ; Possible shift out of high + adc TENEXP ; Like multiplying by five + asl ; And now by ten + clc + ldy #0 + adc (TXTPTR),Y + sec + sbc #'0' +MLEXMI: + sta TENEXP ; Save result + jmp FINEC + +} diff --git a/tools/similarity.c b/tools/similarity.c index f2081fb4..8b785db9 100644 --- a/tools/similarity.c +++ b/tools/similarity.c @@ -20,7 +20,7 @@ int matches[MAX_SIZE]; int phase_mask[MAX_SIZE+MAX_SIZE]; -#define NUM_CHUNKS 15 +#define NUM_CHUNKS 13 // Pairs of start, end memory addresses of known exact similarity with the open source Microsoft BASIC unsigned short microsoft_basic_chunks[NUM_CHUNKS * 2] = { 0xAEA8, 0xAEAC, @@ -29,9 +29,7 @@ unsigned short microsoft_basic_chunks[NUM_CHUNKS * 2] = { 0xB391, 0xB39D, 0xB3A2, 0xB3A5, 0xB849, 0xB97D, - 0xB983, 0xBCF2, - 0xBD7E, 0xBD90, - 0xBDB3, 0xBDC1, + 0xB983, 0xBDC1, 0xBDDD, 0xBF51, 0xBF71, 0xBF7A, 0xBFB4, 0xBFEC,