From 781ad9ee6c4ef9f78fe448c63d924feb43562f12 Mon Sep 17 00:00:00 2001 From: Rikard Nordgren Date: Sun, 3 May 2026 11:26:17 +0200 Subject: [PATCH] Add pwr_FAC2_FAC1 --- STATUS.md | 2 +- src/aliases/,aliases_ram_lowmem.s | 1 + src/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s | 26 ------- .../{,stubs_math => math_trans}/bf7b.interop | 0 src/basic/math_trans/bf7b.pwr_FAC2_FAC1.s | 74 +++++++++++++++++++ tools/similarity.c | 5 +- 6 files changed, 78 insertions(+), 30 deletions(-) delete mode 100644 src/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s rename src/basic/{,stubs_math => math_trans}/bf7b.interop (100%) create mode 100644 src/basic/math_trans/bf7b.pwr_FAC2_FAC1.s diff --git a/STATUS.md b/STATUS.md index eb32c698..48de3398 100644 --- a/STATUS.md +++ b/STATUS.md @@ -254,7 +254,7 @@ Floating point mathematical routines - not official, but well known and broadly | `$BF71` | `sqr_FAC1` | DONE | From the Microsoft BASIC, original name: SQR | | `$BF74` | `sqr_FAC2` | DONE | From the Microsoft BASIC, no label | | `$BF78` | `pwr_FAC2_MEM` | DONE | From the Microsoft BASIC, no label | -| `$BF7B` | `pwr_FAC2_FAC1` | NOT DONE | | +| `$BF7B` | `pwr_FAC2_FAC1` | DONE | From the Microsoft BASIC, original name: FPWRT | | `$BFB4` | `toggle_sign_FAC1` | DONE | From the Microsoft BASIC, original name: NEGOP | | `$BFED` | `exp_FAC1` | DONE | From the Microsoft BASIC, original name: EXP | | `$E043` | `poly1_FAC1` | DONE | From the Microsoft BASIC, original name: POLYX | diff --git a/src/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s index b8abe603..bf5511dc 100644 --- a/src/aliases/,aliases_ram_lowmem.s +++ b/src/aliases/,aliases_ram_lowmem.s @@ -15,6 +15,7 @@ !addr ADRAY1 = $03 ; $03-$04 !addr ADRAY2 = $05 ; $05-$06 !addr CHARAC = $07 ; [!] our implementation might be different XXX give more details + !addr INTEGR = CHARAC !addr ENDCHR = $08 ; [!] our implementation might be different XXX give more details !addr TRMPOS = $09 ; -- NOT IMPLEMENTED -- [!] on MEGA65 also used by DOS Wedge under MONITOR !addr VERCKB = $0A ; flag used by BASIC, 0 - LOAD, 1 - VERIFY, [!] on MEGA65 also used by DOS Wedge diff --git a/src/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s b/src/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s deleted file mode 100644 index 5ea6028a..00000000 --- a/src/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s +++ /dev/null @@ -1,26 +0,0 @@ -;; #LAYOUT# STD * #TAKE -;; #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -;; #LAYOUT# * BASIC_0 #TAKE -;; #LAYOUT# * * #IGNORE - -; -; Math package - set FAC1 as FAC2 raised to the power of FAC1 -; -; Input: -; - .A - must load FAC1 exponent ($61) beforehand to set the zero flag -; -; Note: -; - load FAC2 after FAC1, or mimic the Kernals sign comparison (XXX do we need it?) -; - uses exp(x*log(y)) formula to calculate y^x; slow and inaccurate -; -; See also: -; - [CM64] Computes Mapping the Commodore 64 - page 117 -; - https://www.c64-wiki.com/wiki/Floating_point_arithmetic -; - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics -; - -; XXX provide implementation - -pwr_FAC2_FAC1: - - +STUB_IMPLEMENTATION diff --git a/src/basic/,stubs_math/bf7b.interop b/src/basic/math_trans/bf7b.interop similarity index 100% rename from src/basic/,stubs_math/bf7b.interop rename to src/basic/math_trans/bf7b.interop diff --git a/src/basic/math_trans/bf7b.pwr_FAC2_FAC1.s b/src/basic/math_trans/bf7b.pwr_FAC2_FAC1.s new file mode 100644 index 00000000..5b3eaa26 --- /dev/null +++ b/src/basic/math_trans/bf7b.pwr_FAC2_FAC1.s @@ -0,0 +1,74 @@ +;; #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 - set FAC1 as FAC2 raised to the power of FAC1 +; +; This is verified to be almost identical to the original Microsoft implementation where it was named FPWRT. +; +; Input: +; - .A - must load FAC1 exponent ($61) beforehand to set the zero flag +; +; Note: +; - load FAC2 after FAC1, or mimic the Kernals sign comparison (XXX do we need it?) +; - uses exp(x*log(y)) formula to calculate y^x; slow and inaccurate +; +; See also: +; - [CM64] Computes Mapping the Commodore 64 - page 117 +; - https://www.c64-wiki.com/wiki/Floating_point_arithmetic +; - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics +; + +; EXPONENTIATION --- X^Y. +; N.B. 0^0=1 +; FIRST CHECK IF Y=0. IF SO, THE RESULT IS 1. +; NEXT CHECK IF X=0. IF SO THE RESULT IS 0. +; THEN CHECK IF X.GT.0. IF NOT CHECK THAT Y IS AN INTEGER. +; IF SO, NEGATE X, SO THAT LOG DOESN'T GIVE FCERR. +; IF X IS NEGATIVE AND Y IS ODD, NEGATE THE RESULT +; RETURNED BY EXP. +; TO COMPUTE THE RESULT USE X^Y=EXP((Y*LOG(X)). + +!ifdef CONFIG_TRANSCENDENTAL_FUNCTIONS { +!ifdef CONFIG_MEMORY_MODEL_38K { + +pwr_FAC2_FAC1: + + beq exp_FAC1 ; If FAC1=0, just exponentiate that + lda FAC2_exponent ; Is X=0? + bne FPWRT1 + jmp ZEROF1 ; Zero FAC1 +FPWRT1: + ldx #TEMPF3 ; Save for later in a temp + ldy #0 + jsr mov_r_FAC1_MEM + ; Y=0 already. Good in case no one calls INT + lda FAC2_sign + bpl FPWR1 ; No problems if X>0 + jsr int_FAC1 ; Integerize the FAC1 + lda #TEMPF3 ; Get addr of comperand + ldy #0 + jsr FCOMP ; Equal? + bne FPWR1 ; Leave X neg. log will blow him out. A=-1 and Y is irrelevant + tya ; Negate X. Make positive + ldy INTEGR ; Get evenness +FPWR1: + jsr mov_FAC2_FAC1_sign ; Alternate entry point + tya + pha ; Save evenness for later + jsr log_FAC1 ; Find log + lda #TEMPF3 ; Multiply FAC1 times log(x) + ldy #0 + jsr mul_MEM_FAC1 + jsr exp_FAC1 ; Exponentiate the FAC1 + pla + lsr ; Is it even= + bcc NEGRTS ; Yes. or X>0 + + ; FALLTHROUGH to toggle_sign_FAC1 +} +} diff --git a/tools/similarity.c b/tools/similarity.c index 00f349bd..964c8a0b 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 13 +#define NUM_CHUNKS 12 // 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, @@ -31,8 +31,7 @@ unsigned short microsoft_basic_chunks[NUM_CHUNKS * 2] = { 0xB849, 0xB97D, 0xB983, 0xBDC1, 0xBDDD, 0xBF51, - 0xBF71, 0xBF7A, - 0xBFB4, 0xBFFF, + 0xBF71, 0xBFFF, 0xE000, 0xE08C, 0xE264, 0xE2C2, // Two byte gap here is an optimization 0xE2C5, 0xE37A,