From f773fd6b6768e7172c1b48b5f18de1ec5953e139 Mon Sep 17 00:00:00 2001 From: Rikard Nordgren Date: Fri, 21 Feb 2025 20:42:01 +0100 Subject: [PATCH] Add FCOMP --- STATUS.md | 2 +- src/basic/,stubs_math/bc5b.FCOMP.s | 30 ----- src/basic/math/FCOMP.s | 92 +++++++++++++++ src/basic/math/bc5b.FCOMP.jmp.s | 8 ++ src/basic/{,stubs_math => math}/bc5b.interop | 0 strings/2DA52C6900852E20 | 3 + strings/6085248425 | 3 + strings/B1240980C562 | 3 + strings/B124C564 | 3 + strings/C8B124C5 | 3 + strings/C8B124C563 | 3 + strings/E52BAAA538E52C20CD | 3 + testsuite/unit/math.vs | 114 +++++++++++++++++++ testsuite/unit/testresults.cc | 20 ++++ 14 files changed, 256 insertions(+), 31 deletions(-) delete mode 100644 src/basic/,stubs_math/bc5b.FCOMP.s create mode 100644 src/basic/math/FCOMP.s create mode 100644 src/basic/math/bc5b.FCOMP.jmp.s rename src/basic/{,stubs_math => math}/bc5b.interop (100%) create mode 100644 strings/2DA52C6900852E20 create mode 100644 strings/6085248425 create mode 100644 strings/B1240980C562 create mode 100644 strings/B124C564 create mode 100644 strings/C8B124C5 create mode 100644 strings/C8B124C563 create mode 100644 strings/E52BAAA538E52C20CD diff --git a/STATUS.md b/STATUS.md index a04bca38..4003050e 100644 --- a/STATUS.md +++ b/STATUS.md @@ -236,7 +236,7 @@ Floating point mathematical routines - not official, but well known and broadly | `$BC3C` | `convert_A_to_FAC1` | DONE | | | `$BC44` | `convert_i16_to_FAC1` | DONE | | | `$BC58` | `abs_FAC1` | NOT DONE | | -| `$BC5B` | `FCOMP` | NOT DONE | compare FAC1 with RAM location | +| `$BC5B` | `FCOMP` | DONE | | | `$BC9B` | `QINT` | NOT DONE | convert FAC1 to 32 bit signed integer | | `$BCCC` | `int_FAC1` | NOT DONE | | | `$BCF3` | `FIN` | NOT DONE | imports string to FAC1, ignores spaces | diff --git a/src/basic/,stubs_math/bc5b.FCOMP.s b/src/basic/,stubs_math/bc5b.FCOMP.s deleted file mode 100644 index 595c3a96..00000000 --- a/src/basic/,stubs_math/bc5b.FCOMP.s +++ /dev/null @@ -1,30 +0,0 @@ -;; #LAYOUT# STD * #TAKE -;; #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -;; #LAYOUT# * BASIC_0 #TAKE -;; #LAYOUT# * * #IGNORE - -; -; Math package - compare FAC1 with RAM location -; -; Input: -; - .A - address low byte -; - .Y - address high byte -; -; Output: -; - .A - $00 for equal, $01 for FAC1 > RAM, $FF for FAC1 < RAM -; - flags N/Z, depending on whether FAC1 is 0, positive, or negative -; -; Notes: -; - uses vector at $24, leaves FAC1 and FAC2 unchanged (Codebase64) -; -; See also: -; - [CM64] Computes Mapping the Commodore 64 - page 115 -; - https://www.c64-wiki.com/wiki/Floating_point_arithmetic -; - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics -; - -; XXX provide implementation - -FCOMP: - - +STUB_IMPLEMENTATION diff --git a/src/basic/math/FCOMP.s b/src/basic/math/FCOMP.s new file mode 100644 index 00000000..f127dd4c --- /dev/null +++ b/src/basic/math/FCOMP.s @@ -0,0 +1,92 @@ +;; #LAYOUT# STD * #TAKE +;; #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 +;; #LAYOUT# * BASIC_0 #TAKE +;; #LAYOUT# * * #IGNORE + +; +; Math package - compare FAC1 with RAM location +; +; Input: +; - .A - address low byte +; - .Y - address high byte +; +; Output: +; - .A - $00 for equal, $01 for FAC1 > RAM, $FF for FAC1 < RAM +; - flags N/Z, depending on whether FAC1 is 0, positive, or negative +; +; Notes: +; - uses vector at $24, leaves FAC1 and FAC2 unchanged (Codebase64) +; +; See also: +; - [CM64] Computes Mapping the Commodore 64 - page 115 +; - https://www.c64-wiki.com/wiki/Floating_point_arithmetic +; - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics +; + + +FCOMP: + sta INDEX+2 + sty INDEX+3 + + jsr sgn_FAC1_A ; Set N/Z flag for FAC1 and store on stack + php + + ldy #$01 + lda #$7F ; Expand sign of RAM float into A as $FF or $00 + cmp (INDEX+2),Y + adc #$80 + cmp FAC1_sign + bne FCOMP_greater_than ; FAC < or > RAM, will be swapped to correct + + dey + lda (INDEX+2),Y ; Exponent of RAM float into A + cmp FAC1_exponent + bcc FCOMP_greater_than ; FAC1 > RAM + bne FCOMP_less_than + + cmp #$00 + beq FCOMP_equal ; FAC1 = RAM = 0 + + iny + lda (INDEX+2),Y + ora #$80 ; Set highest bit of mantissa (0.5) + cmp FAC1_mantissa + bcc FCOMP_greater_than + bne FCOMP_less_than + iny + lda (INDEX+2),Y + cmp FAC1_mantissa+1 + bcc FCOMP_greater_than + bne FCOMP_less_than + iny + lda (INDEX+2),Y + cmp FAC1_mantissa+2 + bcc FCOMP_greater_than + bne FCOMP_less_than + iny + lda (INDEX+2),Y + cmp FAC1_mantissa+3 + bcc FCOMP_greater_than + bne FCOMP_less_than + +FCOMP_equal: + lda #$00 + plp + rts + + +FCOMP_less_than: + lda #$FF + cmp FAC1_sign + bne @1 + lda #$01 +@1: plp + rts + +FCOMP_greater_than: + lda #$01 + cmp FAC1_sign + bcs @1 + lda #$FF +@1: plp + rts diff --git a/src/basic/math/bc5b.FCOMP.jmp.s b/src/basic/math/bc5b.FCOMP.jmp.s new file mode 100644 index 00000000..639bf817 --- /dev/null +++ b/src/basic/math/bc5b.FCOMP.jmp.s @@ -0,0 +1,8 @@ +;; #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 + + jmp FCOMP diff --git a/src/basic/,stubs_math/bc5b.interop b/src/basic/math/bc5b.interop similarity index 100% rename from src/basic/,stubs_math/bc5b.interop rename to src/basic/math/bc5b.interop diff --git a/strings/2DA52C6900852E20 b/strings/2DA52C6900852E20 new file mode 100644 index 00000000..e8c40d24 --- /dev/null +++ b/strings/2DA52C6900852E20 @@ -0,0 +1,3 @@ +$2D + LDA $2C + ADC #$00 + STA $2E + JSR + +Fragment of updating well known pointers in the zero page diff --git a/strings/6085248425 b/strings/6085248425 new file mode 100644 index 00000000..467b0915 --- /dev/null +++ b/strings/6085248425 @@ -0,0 +1,3 @@ +$60 + STA $24 + STA $25 + +Fragment of storing to well known pointer in zero page diff --git a/strings/B1240980C562 b/strings/B1240980C562 new file mode 100644 index 00000000..193392ba --- /dev/null +++ b/strings/B1240980C562 @@ -0,0 +1,3 @@ +LDA ($24),Y + ORA $#80 + CMP $62 + +Load using well knownn pointer in zero page, set sign bit and compare with byte in FAC1 mantissa diff --git a/strings/B124C564 b/strings/B124C564 new file mode 100644 index 00000000..ffcdfa99 --- /dev/null +++ b/strings/B124C564 @@ -0,0 +1,3 @@ +LDA ($24),Y + CMP $64 + +Load using well known zero page pointer and compare with FAC1 mantissa byte in zero page diff --git a/strings/C8B124C5 b/strings/C8B124C5 new file mode 100644 index 00000000..a8dd37c5 --- /dev/null +++ b/strings/C8B124C5 @@ -0,0 +1,3 @@ +INY + LDA ($24),Y + CMP zp + +Loop fragment with well known zero page pointer address diff --git a/strings/C8B124C563 b/strings/C8B124C563 new file mode 100644 index 00000000..9d30e343 --- /dev/null +++ b/strings/C8B124C563 @@ -0,0 +1,3 @@ +INY + LDA ($24),Y + CMP $63 + +Load using well known pointer in zero page and compare with mantissa byte in FAC1 diff --git a/strings/E52BAAA538E52C20CD b/strings/E52BAAA538E52C20CD new file mode 100644 index 00000000..55d009e0 --- /dev/null +++ b/strings/E52BAAA538E52C20CD @@ -0,0 +1,3 @@ +SBC $2B + TAX + LDA $38 + SBC $2C + JSR $CD.. + +Fragment of decreasing well known pointer in zero page diff --git a/testsuite/unit/math.vs b/testsuite/unit/math.vs index 390910dc..8b0e7b23 100644 --- a/testsuite/unit/math.vs +++ b/testsuite/unit/math.vs @@ -105,4 +105,118 @@ print "COMPARE" compare $61 $67 $1001 print "END" +print "TEST: mov MEM FAC1 const 1.0" +fill $61 $67 FF FF FF FF FF AA +fill $70 $70 CD +r A=$BC +r Y=$B9 +r PC=$BBA2 +ret +fill $1001 $1006 81 80 00 00 00 00 +print "COMPARE" +compare $61 $66 $1001 +compare $70 $70 $1003 ; FACOV = 0 +print "END" + +print "TEST: mov MEM FAC1 const -0.5" +fill $61 $67 FF FF FF FF FF AA +fill $70 $70 CD +r A=$E0 +r Y=$B9 +r PC=$BBA2 +ret +fill $1001 $1006 80 80 00 00 00 FF +print "COMPARE" +compare $61 $66 $1001 +compare $70 $70 $1003 ; FACOV = 0 +print "END" + +print "TEST: FCOMP 1.0 == 1.0" +r A=$BC +r Y=$B9 +r PC=$BBA2 +ret +r A=$BC +r Y=$B9 +r PC=$BC5B +ret +print "CHECK A==0" +r + +print "TEST: FCOMP 1.0 > 0.5" +r A=$BC +r Y=$B9 +r PC=$BBA2 +ret +r A=$11 +r Y=$BF +r PC=$BC5B +ret +print "CHECK A==1" +r + +print "TEST: FCOMP 0.5 < 1.0" +r A=$11 +r Y=$BF +r PC=$BBA2 +ret +r A=$BC +r Y=$B9 +r PC=$BC5B +ret +print "CHECK A==255" +r + +print "TEST: FCOMP -0.5 < 1.0" +r A=$E0 +r Y=$B9 +r PC=$BBA2 +ret +r A=$BC +r Y=$B9 +r PC=$BC5B +ret +print "CHECK A==255" +r + +print "TEST: FCOMP 10.0 > -0.5" +r A=$F9 +r Y=$BA +r PC=$BBA2 +ret +r A=$E0 +r Y=$B9 +r PC=$BC5B +ret +print "CHECK A==1" +r + +print "TEST: FCOMP 0.9970194103661925 < 0.9970194105990231" +fill $1001 $1005 80 7F 3C AA 01 +r A=$01 +r Y=$10 +r PC=$BBA2 +ret +fill $1006 $100A 80 7F 3C AA 02 +r A=$06 +r Y=$10 +r PC=$BC5B +ret +print "CHECK A==255" +r + +print "TEST: FCOMP 0.0 = 0.0" +fill $1001 $1005 00 7F 3C AA 01 +r A=$01 +r Y=$10 +r PC=$BBA2 +ret +fill $1006 $100A 00 7F 3C AA 02 +r A=$06 +r Y=$10 +r PC=$BC5B +ret +print "CHECK A==0" +r + q diff --git a/testsuite/unit/testresults.cc b/testsuite/unit/testresults.cc index 422572fa..f42d57d7 100644 --- a/testsuite/unit/testresults.cc +++ b/testsuite/unit/testresults.cc @@ -20,6 +20,26 @@ int main() } else if (line.starts_with(" print \"COMPARE")) { getline(file, line); in_compare = true; + } else if (line.starts_with(" print \"CHECK")) { + std::string cmp = line.substr(15, line.size() - 16); + std::string reg = cmp.substr(0, 1); + std::string op = cmp.substr(1, 2); + int value = std::stoi(cmp.substr(3, line.size() - 3)); + if (op == "==") { + getline(file, line); + getline(file, line); + getline(file, line); + if (reg == "A") { + int A_val = std::stoi(line.substr(7, 2), 0, 16); + if (A_val != value) { + std::cout << "FAIL: A != " << value << " (was " << A_val << ")" << std::endl; + failed = true; + } + } + } else { + std::cout << "ERROR: Unknown operator for check" << std::endl; + failed = true; + } } else if (line.starts_with(" print \"END")) { in_compare = false; }