From b0d01771145464b3666d47f1f775d9ca48ed89b4 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Mon, 3 Feb 2020 21:37:27 +0100 Subject: [PATCH] added exponent alignment routine, fix for FAC1 normalization --- STATUS.md | 95 +++++------ c64/basic/math/add_align_exponents.s | 169 +++++++++++++++++++ c64/basic/math/b862.add_align_exponent.jmp.s | 8 + c64/basic/math/b862.interop | 3 + c64/basic/math/mov_FAC1_MEM.s | 7 +- c64/basic/math/mov_MEM_FAC1.s | 7 +- c64/basic/math/mov_MEM_FAC2.s | 7 +- c64/basic/math/normal_FAC1.s | 48 +++--- 8 files changed, 259 insertions(+), 85 deletions(-) create mode 100644 c64/basic/math/add_align_exponents.s create mode 100644 c64/basic/math/b862.add_align_exponent.jmp.s create mode 100644 c64/basic/math/b862.interop diff --git a/STATUS.md b/STATUS.md index 98646059..328b8215 100644 --- a/STATUS.md +++ b/STATUS.md @@ -174,53 +174,54 @@ Floating point mathematical routines - not official, but well known and broadly
-| Address | Name | Status | Remarks | -| :-------: | :----------------- | :------: | :------------------------------------------------: | -| `$B1AA` | `FACINX` | NOT DONE | convert FAC1 to 16-bit signed integer | -| `$B391` | `GIVAYF` | NOT DONE | 16-bit signed integer to FAC1 | -| `$B7B5` | `STRVAL` | NOT DONE | imports string to FAC1 | -| `$B850` | `sub_MEM_FAC1` | PARTIAL | needs `add_FAC2_FAC1` | -| `$B853` | `sub_FAC2_FAC1` | PARTIAL | needs `add_FAC2_FAC1` | -| `$B867` | `add_MEM_FAC1` | PARTIAL | needs `add_FAC2_FAC1` | -| `$B86A` | `add_FAC2_FAC1` | NOT DONE | | -| `$B8FE` | `normal_FAC1` | PARTIAL | not tested yet | -| `$B9EA` | `log_FAC1` | NOT DONE | | -| `$BA28` | `mul_MEM_FAC1` | PARTIAL | needs `mul_FAC2_FAC1` | -| `$BA2B` | `mul_FAC2_FAC1` | NOT DONE | | -| `$BA8C` | `mov_MEM_FAC2` | PARTIAL | not fully tested yet | -| `$BAE2` | `mul10_FAC1` | NOT DONE | | -| `$BAFE` | `div10_FAC1_p` | NOT DONE | | -| `$BB0F` | `div_MEM_FAC1` | PARTIAL | needs `div_FAC2_FAC1` | -| `$BB12` | `div_FAC2_FAC1` | NOT DONE | | -| `$BBA2` | `mov_MEM_FAC1` | PARTIAL | not fully tested yet | -| `$BBC7` | `mov_r_FAC1_TMP2` | PARTIAL | not fully tested yet | -| `$BBCA` | `mov_r_FAC1_TMP1` | PARTIAL | not fully tested yet | -| `$BBD0` | `mov_r_FAC1_VAR` | PARTIAL | not fully tested yet | -| `$BBD4` | `mov_r_FAC1_MEM` | PARTIAL | not fully tested yet | -| `$BBFC` | `mov_FAC2_FAC1` | PARTIAL | not fully tested yet | -| `$BC0C` | `mov_r_FAC1_FAC2` | PARTIAL | not fully tested yet | -| `$BC0F` | `mov_FAC1_FAC2` | DONE | | -| `$BC1B` | `round_FAC1` | PARTIAL | not fully tested yet | -| `$BC2B` | `sgn_FAC1_A` | NOT DONE | | -| `$BC39` | `sgn_FAC1` | NOT DONE | | -| `$BC58` | `abs_FAC1` | NOT DONE | | -| `$BC5B` | `FCOMP` | NOT DONE | compare FAC1 with RAM location | -| `$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 | -| `$BDDD` | `FOUT` | NOT DONE | outputs FAC1 to string at $0100 | -| `$BF71` | `sqr_FAC1` | NOT DONE | | -| `$BF74` | `sqr_FAC2` | NOT DONE | | -| `$BF78` | `FPWR` | NOT DONE | set FAC1 as RAM raised to the power of FAC1 | -| `$BF7B` | `FPWRT` | NOT DONE | set FAC1 as FAC2 raised to the power of FAC1 | -| `$BFB4` | `toggle_sign_FAC1` | DONE | | -| `$BFED` | `exp_FAC1` | NOT DONE | | -| `$E043` | `poly1_FAC1` | NOT DONE | | -| `$E059` | `poly2_FAC1` | NOT DONE | | -| `$E264` | `cos_FAC1` | NOT DONE | | -| `$E26B` | `sin_FAC1` | NOT DONE | | -| `$E2B4` | `tan_FAC1` | NOT DONE | | -| `$E30E` | `atn_FAC1` | NOT DONE | | +| Address | Name | Status | Remarks | +| :-------: | :-------------------- | :------: | :------------------------------------------------: | +| `$B1AA` | `FACINX` | NOT DONE | convert FAC1 to 16-bit signed integer | +| `$B391` | `GIVAYF` | NOT DONE | 16-bit signed integer to FAC1 | +| `$B7B5` | `STRVAL` | NOT DONE | imports string to FAC1 | +| `$B850` | `sub_MEM_FAC1` | PARTIAL | needs `add_FAC2_FAC1` | +| `$B853` | `sub_FAC2_FAC1` | PARTIAL | needs `add_FAC2_FAC1` | +| `$B862` | `add_align_exponents` | PARTIAL | not tested yet | +| `$B867` | `add_MEM_FAC1` | PARTIAL | needs `add_FAC2_FAC1` | +| `$B86A` | `add_FAC2_FAC1` | NOT DONE | | +| `$B8FE` | `normal_FAC1` | PARTIAL | not tested yet | +| `$B9EA` | `log_FAC1` | NOT DONE | | +| `$BA28` | `mul_MEM_FAC1` | PARTIAL | needs `mul_FAC2_FAC1` | +| `$BA2B` | `mul_FAC2_FAC1` | NOT DONE | | +| `$BA8C` | `mov_MEM_FAC2` | PARTIAL | not fully tested yet | +| `$BAE2` | `mul10_FAC1` | NOT DONE | | +| `$BAFE` | `div10_FAC1_p` | NOT DONE | | +| `$BB0F` | `div_MEM_FAC1` | PARTIAL | needs `div_FAC2_FAC1` | +| `$BB12` | `div_FAC2_FAC1` | NOT DONE | | +| `$BBA2` | `mov_MEM_FAC1` | PARTIAL | not fully tested yet | +| `$BBC7` | `mov_r_FAC1_TMP2` | PARTIAL | not fully tested yet | +| `$BBCA` | `mov_r_FAC1_TMP1` | PARTIAL | not fully tested yet | +| `$BBD0` | `mov_r_FAC1_VAR` | PARTIAL | not fully tested yet | +| `$BBD4` | `mov_r_FAC1_MEM` | PARTIAL | not fully tested yet | +| `$BBFC` | `mov_FAC2_FAC1` | PARTIAL | not fully tested yet | +| `$BC0C` | `mov_r_FAC1_FAC2` | PARTIAL | not fully tested yet | +| `$BC0F` | `mov_FAC1_FAC2` | DONE | | +| `$BC1B` | `round_FAC1` | PARTIAL | not fully tested yet | +| `$BC2B` | `sgn_FAC1_A` | NOT DONE | | +| `$BC39` | `sgn_FAC1` | NOT DONE | | +| `$BC58` | `abs_FAC1` | NOT DONE | | +| `$BC5B` | `FCOMP` | NOT DONE | compare FAC1 with RAM location | +| `$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 | +| `$BDDD` | `FOUT` | NOT DONE | outputs FAC1 to string at $0100 | +| `$BF71` | `sqr_FAC1` | NOT DONE | | +| `$BF74` | `sqr_FAC2` | NOT DONE | | +| `$BF78` | `FPWR` | NOT DONE | set FAC1 as RAM raised to the power of FAC1 | +| `$BF7B` | `FPWRT` | NOT DONE | set FAC1 as FAC2 raised to the power of FAC1 | +| `$BFB4` | `toggle_sign_FAC1` | DONE | | +| `$BFED` | `exp_FAC1` | NOT DONE | | +| `$E043` | `poly1_FAC1` | NOT DONE | | +| `$E059` | `poly2_FAC1` | NOT DONE | | +| `$E264` | `cos_FAC1` | NOT DONE | | +| `$E26B` | `sin_FAC1` | NOT DONE | | +| `$E2B4` | `tan_FAC1` | NOT DONE | | +| `$E30E` | `atn_FAC1` | NOT DONE | |
diff --git a/c64/basic/math/add_align_exponents.s b/c64/basic/math/add_align_exponents.s new file mode 100644 index 00000000..3956ed9c --- /dev/null +++ b/c64/basic/math/add_align_exponents.s @@ -0,0 +1,169 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Math package - align FAC1 and FAC2 exponents for addition +// +// See also: +// - [CM64] Computes Mapping the Commodore 64 - page 115 +// - https://www.c64-wiki.com/wiki/BASIC-ROM + +// XXX finish and test this + +add_align_exponents: + + // XXX assume here none of the exponents is 0, check if this is true for orignal ROMs + + lda FAC1_exponent + cmp FAC2_exponent + beq add_align_exponents_done // branch if exponents the same + bcs add_align_exponent_FAC2 + + // FALLTROUGH + +add_align_exponent_FAC1: + + // First check the exponent difference + + lda FAC2_exponent + sec + sbc FAC1_exponent + + cmp #$28 + bcs add_align_exponent_FAC1_zero // branch if difference is very high + + cmp #$08 + bcc add_align_exponent_FAC1_bit + + // FALLTROUGH + +add_align_exponent_FAC1_byte: + + // Add 8 to exponent, divide mantissa by 256 + + lda FAC1_exponent + clc + adc #$08 + sta FAC1_exponent + + lda FAC1_mantissa+3 + sta FACOV + lda FAC1_mantissa+2 + sta FAC1_mantissa+3 + lda FAC1_mantissa+1 + sta FAC1_mantissa+2 + lda FAC1_mantissa+0 + sta FAC1_mantissa+1 + lda #$00 + sta FAC1_mantissa+0 + + beq add_align_exponent_FAC1 // branch always - next iteration + +add_align_exponent_FAC1_bit: + + // Increment exponent, divide mantissa by 2 + + inc FAC1_exponent + + clc + ror FAC1_mantissa+0 + ror FAC1_mantissa+1 + ror FAC1_mantissa+2 + ror FAC1_mantissa+3 + ror FACOV + + lda FAC1_exponent + cmp FAC2_exponent + bne add_align_exponent_FAC1_bit // branch if next iteration needed + + rts + +add_align_exponent_FAC1_zero: + + lda #$00 + + sta FAC1_mantissa+0 + sta FAC1_mantissa+1 + sta FAC1_mantissa+2 + sta FAC1_mantissa+3 + sta FACOV + + lda FAC2_exponent + sta FAC1_exponent + + // FALLTROUGH + +add_align_exponents_done: + + rts + + + +add_align_exponent_FAC2: + + // First check the exponent difference, Carry already set here + + lda FAC1_exponent + sbc FAC2_exponent + + cmp #$20 + bcs add_align_exponent_FAC2_zero // branch if difference is very high + + cmp #$08 + bcc add_align_exponent_FAC2_bit + + // FALLTROUGH + +add_align_exponent_FAC2_byte: + + // Add 8 to exponent, divide mantissa by 256 + + lda FAC2_exponent + clc + adc #$08 + sta FAC2_exponent + + lda FAC2_mantissa+2 + sta FAC2_mantissa+3 + lda FAC2_mantissa+1 + sta FAC2_mantissa+2 + lda FAC2_mantissa+0 + sta FAC2_mantissa+1 + lda #$00 + sta FAC2_mantissa+0 + + beq add_align_exponent_FAC2 // branch always - next iteration + +add_align_exponent_FAC2_bit: + + // Increment exponent, divide mantissa by 2 + + inc FAC2_exponent + + clc + ror FAC2_mantissa+0 + ror FAC2_mantissa+1 + ror FAC2_mantissa+2 + ror FAC2_mantissa+3 + + lda FAC1_exponent + cmp FAC2_exponent + bne add_align_exponent_FAC2_bit // branch if next iteration needed + + rts + + +add_align_exponent_FAC2_zero: + + lda #$00 + + sta FAC2_mantissa+0 + sta FAC2_mantissa+1 + sta FAC2_mantissa+2 + sta FAC2_mantissa+3 + + lda FAC1_exponent + sta FAC2_exponent + + rts diff --git a/c64/basic/math/b862.add_align_exponent.jmp.s b/c64/basic/math/b862.add_align_exponent.jmp.s new file mode 100644 index 00000000..bcddf0ba --- /dev/null +++ b/c64/basic/math/b862.add_align_exponent.jmp.s @@ -0,0 +1,8 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// Just a compatibility jump - our routine is longer than original one + + + jmp add_align_exponents diff --git a/c64/basic/math/b862.interop b/c64/basic/math/b862.interop new file mode 100644 index 00000000..0d18777c --- /dev/null +++ b/c64/basic/math/b862.interop @@ -0,0 +1,3 @@ +This is an important floating point math routine, documented in many places. + +XXX - try to find real-life example diff --git a/c64/basic/math/mov_FAC1_MEM.s b/c64/basic/math/mov_FAC1_MEM.s index 9a8621fb..84d49903 100644 --- a/c64/basic/math/mov_FAC1_MEM.s +++ b/c64/basic/math/mov_FAC1_MEM.s @@ -19,11 +19,8 @@ mov_FAC1_MEM: - // Checked in the available documentation: - // - https://www.c64-wiki.com/wiki/Floating_point_arithmetic - // - https://www.lemon64.com/forum/viewtopic.php?t=67576&sid=d41e77cdddd28d6f9c9d52ce5b4e8dc3 - // that $22/$23 (INDEX+0 and INDEX+1) are at least sometimes used for pointer storage. - // Confirmed by experimenting with original ROM that this is the case here too. + // Original routines use $22/$23 location for a vector too, see here: + // - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics sty INDEX+1 stx INDEX+0 diff --git a/c64/basic/math/mov_MEM_FAC1.s b/c64/basic/math/mov_MEM_FAC1.s index 14ceb648..39296f87 100644 --- a/c64/basic/math/mov_MEM_FAC1.s +++ b/c64/basic/math/mov_MEM_FAC1.s @@ -23,11 +23,8 @@ mov_MEM_FAC1: - // Checked in the available documentation: - // - https://www.c64-wiki.com/wiki/Floating_point_arithmetic - // - https://www.lemon64.com/forum/viewtopic.php?t=67576&sid=d41e77cdddd28d6f9c9d52ce5b4e8dc3 - // that $22/$23 (INDEX+0 and INDEX+1) are at least sometimes used for pointer storage. - // Confirmed by experimenting with original ROM that this is the case here too. + // Original routines use $22/$23 location for a vector too, see here: + // - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics sty INDEX+1 sta INDEX+0 diff --git a/c64/basic/math/mov_MEM_FAC2.s b/c64/basic/math/mov_MEM_FAC2.s index 0258c041..8102794d 100644 --- a/c64/basic/math/mov_MEM_FAC2.s +++ b/c64/basic/math/mov_MEM_FAC2.s @@ -26,11 +26,8 @@ mov_MEM_FAC2: - // Checked in the available documentation: - // - https://www.c64-wiki.com/wiki/Floating_point_arithmetic - // - https://www.lemon64.com/forum/viewtopic.php?t=67576&sid=d41e77cdddd28d6f9c9d52ce5b4e8dc3 - // that $22/$23 (INDEX+0 and INDEX+1) are at least sometimes used for pointer storage. - // Confirmed by experimenting with original ROM that this is the case here too. + // Original routines use $22/$23 location for a vector too, see here: + // - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics sty INDEX+1 sta INDEX+0 diff --git a/c64/basic/math/normal_FAC1.s b/c64/basic/math/normal_FAC1.s index 0dda7581..5dc96fa5 100644 --- a/c64/basic/math/normal_FAC1.s +++ b/c64/basic/math/normal_FAC1.s @@ -16,30 +16,32 @@ normal_FAC1: lda FAC1_exponent - beq normal_FAC1_end // branch if our float is 0 + beq normal_FAC1_end // branch if our float is 0 - lda FAC1_mantissa+3 - beq normal_FAC1_by_byte // branch if we can move the whole byte + // FALLTROUGH + +normal_FAC1_check_mantissa_byte: + + lda FAC1_mantissa+0 + beq normal_FAC1_by_byte // branch if we can move the whole byte + // FALLTROUGH + +normal_FAC1_check_mantissa_bit: + + lda FAC1_mantissa+0 // XXX optimize for 65CE02? and #$80 - bne normal_FAC1_end // branch if already normalized + bne normal_FAC1_end // branch if already normalized // FALLTROUGH normal_FAC1_by_bit: - // First check the current exponent + // Decrement the exponent - lda FAC1_exponent - cmp #$01 - bne !+ - - // Exponent is 1 - just mark the whole number as 0 and finish - - lda #$00 - sta FAC1_exponent - rts -!: + dec FAC1_exponent + beq normal_FAC1_end // exponent reached 0, nothing more to do + // Multiply the mantissa by 2 clc @@ -49,7 +51,7 @@ normal_FAC1_by_bit: rol FAC1_mantissa+1 rol FAC1_mantissa+0 - bcc normal_FAC1 // branch if next iteration needed + bcc normal_FAC1_check_mantissa_bit // branch if next iteration needed rts normal_FAC1_by_byte: @@ -63,19 +65,19 @@ normal_FAC1_by_byte: lda #$00 !: sta FAC1_exponent - beq normal_FAC1_end // branch if our float reached 0 + beq normal_FAC1_end // branch if our float reached 0 // Now multiply the mantissa by 8 by moving the whole bytes - lda FAC1_mantissa+2 - sta FAC1_mantissa+3 lda FAC1_mantissa+1 - sta FAC1_mantissa+2 - lda FAC1_mantissa+0 + sta FAC1_mantissa+0 + lda FAC1_mantissa+2 sta FAC1_mantissa+1 + lda FAC1_mantissa+3 + sta FAC1_mantissa+2 lda FACOV - sta FAC1_mantissa+0 + sta FAC1_mantissa+3 lda #$00 sta FACOV @@ -87,7 +89,7 @@ normal_FAC1_by_byte: ora FAC1_mantissa+2 ora FAC1_mantissa+3 - bne normal_FAC1 // not 0 - branch to next iteration + bne normal_FAC1_check_mantissa_byte // not 0 - branch to next iteration // Our mantissa reached 0 - mark exponent as 0 and finish