m68k: implement bcd library routines

This commit is contained in:
Irmen de Jong committed 2026-10-10 15:41:32 +02:00
1 parent 55b7239553
commit 31dbbc3fe1
4 files changed
+274 -12

No files matched your search

+1 -1
View File
@@ -1 +1 @@
; no support for BCD
%import shared_amiga_bcd
+131 -1
View File
@@ -1 +1,131 @@
; no support for BCD
bcd {
%option merge, ignore_unused
asmsub addb(byte a @D0, byte b @D1) clobbers(D1) -> byte @D0 {
%asm {{
andi.b #$ef,ccr
abcd d1,d0
rts
}}
}
asmsub addub(ubyte a @D0, ubyte b @D1) clobbers(D1) -> ubyte @D0 {
%asm {{
andi.b #$ef,ccr
abcd d1,d0
rts
}}
}
asmsub addw(word a @D0, word b @D1) clobbers(D1) -> word @D0 {
%asm {{
andi.b #$ef,ccr
abcd d1,d0
ror.w #8,d0
ror.w #8,d1
abcd d1,d0
ror.w #8,d0
rts
}}
}
asmsub adduw(uword a @D0, uword b @D1) clobbers(D1) -> uword @D0 {
%asm {{
andi.b #$ef,ccr
abcd d1,d0
ror.w #8,d0
ror.w #8,d1
abcd d1,d0
ror.w #8,d0
rts
}}
}
asmsub addl(long a @D0, long b @D1) clobbers(D1) -> long @D0 {
%asm {{
andi.b #$ef,ccr
abcd d1,d0
rept 3
ror.l #8,d0
ror.l #8,d1
abcd d1,d0
endr
ror.l #8,d0
rts
}}
}
asmsub subb(byte a @D0, byte b @D1) clobbers(D1) -> byte @D0 {
%asm {{
andi.b #$ef,ccr
sbcd d1,d0
rts
}}
}
asmsub subub(ubyte a @D0, ubyte b @D1) clobbers(D1) -> ubyte @D0 {
%asm {{
andi.b #$ef,ccr
sbcd d1,d0
rts
}}
}
asmsub subuw(uword a @D0, uword b @D1) clobbers(D1) -> uword @D0 {
%asm {{
andi.b #$ef,ccr
sbcd d1,d0
ror.w #8,d0
ror.w #8,d1
sbcd d1,d0
ror.w #8,d0
rts
}}
}
asmsub subl(long a @D0, long b @D1) clobbers(D1) -> long @D0 {
%asm {{
andi.b #$ef,ccr
sbcd d1,d0
rept 3
ror.l #8,d0
ror.l #8,d1
sbcd d1,d0
endr
ror.l #8,d0
rts
}}
}
asmsub addtol(^^long a @A0, long b @D0) clobbers(D0,D1) {
%asm {{
move.l (a0),d1
andi.b #$ef,ccr
abcd d0,d1
rept 3
ror.l #8,d0
ror.l #8,d1
abcd d0,d1
endr
ror.l #8,d1
move.l d1,(a0)
rts
}}
}
asmsub subfroml(^^long a @A0, long b @D0) clobbers(D0,D1) {
%asm {{
move.l (a0),d1
andi.b #$ef,ccr
sbcd d0,d1
rept 3
ror.l #8,d0
ror.l #8,d1
sbcd d0,d1
endr
ror.l #8,d1
move.l d1,(a0)
rts
}}
}
}
+12 -7
View File
@@ -577,23 +577,28 @@ bcd
^^^
.. index:: pair: Libraries; bcd
Decimal addition and subtraction routines, so for example $0987 + $1111 = $2098 (rather than the usual hex outcome $1a98)
Utilizes the BCD mode of the CPU (note: not all 6502 variants support this mode).
This mode is useful for example for counting decimal score in a game, to avoid costly conversion to a decimal display string:
just print the hexadecimal score representation. (This gets especially noticeable with long integers)
Available routines:
Decimal addition and subtraction routines using packed BCD values. For example,
``$0987 + $1111`` produces ``$2098`` rather than the usual binary result
``$1a98``. A BCD value can be printed directly as hexadecimal because each
hexadecimal digit represents one decimal digit.
The library uses the CPU's BCD instructions. It is not available on the ``virtual`` target.
Available value-returning routines:
- ``sub addb(byte a, byte b) -> byte``
- ``sub addub(ubyte a, ubyte b) -> ubyte``
- ``sub addw(word a, word b) -> word``
- ``sub adduw(uword a, uword b) -> uword``
- ``sub addl(long a, long b) -> long``
- ``sub addtol(^^long a, long b)`` (adds b in-place to a, saves copying values)
- ``sub addtol(^^long a, long b)`` (adds ``b`` in-place to ``a``)
- ``sub subb(byte a, byte b) -> byte``
- ``sub subub(ubyte a, ubyte b) -> ubyte``
- ``sub subuw(uword a, uword b) -> uword``
- ``sub subl(long a, long b) -> long``
- ``sub subfroml(^^long a, long b)`` (subtracts b in-place from a, saves copying values)
- ``sub subfroml(^^long a, long b)`` (subtracts ``b`` in-place from ``a``)
The in-place long routines try to avoid copying values.
bmx (cx16 only)
+130 -3
View File
@@ -1,8 +1,135 @@
%encoding iso
%import textio
%import bcd
%zeropage basicsafe
main {
sub start() {
sys.die($99ea, "ik ga dood")
txt.print_ub(123)
txt.print("\nderp\n")
txt.iso()
txt.print("bcd addition (hex: each nibble is a decimal digit)\n")
check_byte_add($25, $13, $38)
check_byte_add($58, $41, $99)
txt.print("\nbcd subtraction\n")
check_byte_sub($64, $27, $37)
check_byte_sub($80, $29, $51)
txt.print("\nbcd word addition\n")
check_word_add($1234, $5678, $6912)
txt.print("\nbcd word subtraction\n")
check_word_sub($8000, $1234, $6766)
txt.print("\nbcd long addition\n")
check_long_add($12345678, $87654321, $99999999)
txt.print("\nbcd long subtraction\n")
check_long_sub($98765432, $12345678, $86419754)
txt.print("\nbcd long in-place addition\n")
check_long_add_in_place($12345678, $87654321, $99999999)
txt.print("\nbcd long in-place subtraction\n")
check_long_sub_in_place($98765432, $12345678, $86419754)
;sys.poweroff_system()
}
sub check_byte_add(ubyte a, ubyte b, ubyte expected) {
ubyte result = bcd.addub(a, b)
txt.print_ubhex(a, false)
txt.print(" + ")
txt.print_ubhex(b, false)
txt.print(" = ")
txt.print_ubhex(result, false)
txt.print(" expected ")
txt.print_ubhex(expected, false)
print_verdict(result == expected)
}
sub check_byte_sub(ubyte a, ubyte b, ubyte expected) {
ubyte result = bcd.subub(a, b)
txt.print_ubhex(a, false)
txt.print(" - ")
txt.print_ubhex(b, false)
txt.print(" = ")
txt.print_ubhex(result, false)
txt.print(" expected ")
txt.print_ubhex(expected, false)
print_verdict(result == expected)
}
sub check_word_add(uword a, uword b, uword expected) {
uword result = bcd.adduw(a, b)
txt.print_uwhex(a, false)
txt.print(" + ")
txt.print_uwhex(b, false)
txt.print(" = ")
txt.print_uwhex(result, false)
txt.print(" expected ")
txt.print_uwhex(expected, false)
print_verdict(result == expected)
}
sub check_word_sub(uword a, uword b, uword expected) {
uword result = bcd.subuw(a, b)
txt.print_uwhex(a, false)
txt.print(" - ")
txt.print_uwhex(b, false)
txt.print(" = ")
txt.print_uwhex(result, false)
txt.print(" expected ")
txt.print_uwhex(expected, false)
print_verdict(result == expected)
}
sub check_long_add(long a, long b, long expected) {
long result = bcd.addl(a, b)
txt.print_ulhex(a, false)
txt.print(" + ")
txt.print_ulhex(b, false)
txt.print(" = ")
txt.print_ulhex(result, false)
txt.print(" expected ")
txt.print_ulhex(expected, false)
print_verdict(result == expected)
}
sub check_long_sub(long a, long b, long expected) {
long result = bcd.subl(a, b)
txt.print_ulhex(a, false)
txt.print(" - ")
txt.print_ulhex(b, false)
txt.print(" = ")
txt.print_ulhex(result, false)
txt.print(" expected ")
txt.print_ulhex(expected, false)
print_verdict(result == expected)
}
sub check_long_add_in_place(long initial, long value, long expected) {
long @shared result = initial
bcd.addtol(&result, value)
txt.print_ulhex(result, false)
txt.print(" expected ")
txt.print_ulhex(expected, false)
print_verdict(result == expected)
}
sub check_long_sub_in_place(long initial, long value, long expected) {
long @shared result = initial
bcd.subfroml(&result, value)
txt.print_ulhex(result, false)
txt.print(" expected ")
txt.print_ulhex(expected, false)
print_verdict(result == expected)
}
sub print_verdict(bool ok) {
if ok
txt.print(" ok\n")
else
txt.print(" fail\n")
}
}