mirror of
https://github.com/irmen/prog8.git
synced 2026-10-22 05:02:58 +00:00
m68k: implement bcd library routines
This commit is contained in:
1 parent
55b7239553
commit
31dbbc3fe1
4 files changed
+274
-12
No files matched your search
@@ -1 +1 @@
|
||||
; no support for BCD
|
||||
%import shared_amiga_bcd
|
||||
@@ -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
|
||||
}}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user