cbm.STOP2() and cbm.GETIN2() convenience routines

This commit is contained in:
Irmen de Jong 2024-04-06 02:16:21 +02:00
parent 88ae3daa42
commit 66a6659a6e
7 changed files with 141 additions and 10 deletions

View File

@ -66,7 +66,7 @@ class AsmGen6502(val prefixSymbols: Boolean): ICodeGeneratorBackend {
if(node.type in SplitWordArrayTypes && (lookupName.endsWith("_lsb") || lookupName.endsWith("_msb"))) { if(node.type in SplitWordArrayTypes && (lookupName.endsWith("_lsb") || lookupName.endsWith("_msb"))) {
lookupName = lookupName.dropLast(4) lookupName = lookupName.dropLast(4)
} }
val stNode = st.lookup(lookupName)!! val stNode = st.lookup(lookupName) ?: throw AssemblyError("unknown identifier $node")
if(stNode.astNode.definingBlock()?.options?.noSymbolPrefixing!=true) { if(stNode.astNode.definingBlock()?.options?.noSymbolPrefixing!=true) {
val index = node.parent.children.indexOf(node) val index = node.parent.children.indexOf(node)
nodesToPrefix += node.parent to index nodesToPrefix += node.parent to index

View File

@ -93,8 +93,8 @@ romsub $FFD5 = LOAD(ubyte verify @ A, uword address @ XY) -> bool @Pc, ubyte @ A
romsub $FFD8 = SAVE(ubyte zp_startaddr @ A, uword endaddr @ XY) -> bool @ Pc, ubyte @ A ; (via 818 ($332)) save to a device romsub $FFD8 = SAVE(ubyte zp_startaddr @ A, uword endaddr @ XY) -> bool @ Pc, ubyte @ A ; (via 818 ($332)) save to a device
romsub $FFDB = SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) ; set the software clock romsub $FFDB = SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) ; set the software clock
romsub $FFDE = RDTIM() -> ubyte @ A, ubyte @ X, ubyte @ Y ; read the software clock (A=lo,X=mid,Y=high) romsub $FFDE = RDTIM() -> ubyte @ A, ubyte @ X, ubyte @ Y ; read the software clock (A=lo,X=mid,Y=high)
romsub $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; (via 808 ($328)) check the STOP key (and some others in A) romsub $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; (via 808 ($328)) check the STOP key (and some others in A) also see STOP2
romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; (via 810 ($32A)) get a character romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; (via 810 ($32A)) get a character also see GETIN2
romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files
romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock
romsub $FFED = SCREEN() -> ubyte @ X, ubyte @ Y ; read number of screen rows and columns romsub $FFED = SCREEN() -> ubyte @ X, ubyte @ Y ; read number of screen rows and columns
@ -105,6 +105,23 @@ romsub $FFF3 = IOBASE() -> uword @ XY ; read base addr
; ---- utilities ----- ; ---- utilities -----
inline asmsub STOP2() clobbers(X,A) -> bool @Pz {
; -- just like STOP, but omits the special keys result value in A.
; just for convenience because most of the times you're only interested in the stop pressed or not status.
%asm {{
jsr cbm.STOP
}}
}
inline asmsub GETIN2() clobbers(X,Y) -> ubyte @A {
; -- just like GETIN, but omits the carry flag result value.
; just for convenience because GETIN is so often used to just read keyboard input,
; where you don't have to deal with a potential error status
%asm {{
jsr cbm.GETIN
}}
}
asmsub RDTIM16() clobbers(X) -> uword @AY { asmsub RDTIM16() clobbers(X) -> uword @AY {
; -- like RDTIM() but only returning the lower 16 bits in AY for convenience ; -- like RDTIM() but only returning the lower 16 bits in AY for convenience
%asm {{ %asm {{

View File

@ -94,14 +94,32 @@ romsub $FFD5 = LOAD(ubyte verify @ A, uword address @ XY) -> bool @Pc, ubyte @ A
romsub $FFD8 = SAVE(ubyte zp_startaddr @ A, uword endaddr @ XY) -> bool @ Pc, ubyte @ A ; (via 818 ($332)) save to a device romsub $FFD8 = SAVE(ubyte zp_startaddr @ A, uword endaddr @ XY) -> bool @ Pc, ubyte @ A ; (via 818 ($332)) save to a device
romsub $FFDB = SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) ; set the software clock romsub $FFDB = SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) ; set the software clock
romsub $FFDE = RDTIM() -> ubyte @ A, ubyte @ X, ubyte @ Y ; read the software clock (A=lo,X=mid,Y=high) romsub $FFDE = RDTIM() -> ubyte @ A, ubyte @ X, ubyte @ Y ; read the software clock (A=lo,X=mid,Y=high)
romsub $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; (via 808 ($328)) check the STOP key (and some others in A) romsub $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; (via 808 ($328)) check the STOP key (and some others in A) also see STOP2
romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; (via 810 ($32A)) get a character romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; (via 810 ($32A)) get a character also see GETIN2
romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files
romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock
romsub $FFED = SCREEN() -> ubyte @ X, ubyte @ Y ; read number of screen rows and columns romsub $FFED = SCREEN() -> ubyte @ X, ubyte @ Y ; read number of screen rows and columns
romsub $FFF0 = PLOT(ubyte col @ Y, ubyte row @ X, bool dir @ Pc) clobbers(A) -> ubyte @ X, ubyte @ Y ; read/set position of cursor on screen. Use txt.plot for a 'safe' wrapper that preserves X. romsub $FFF0 = PLOT(ubyte col @ Y, ubyte row @ X, bool dir @ Pc) clobbers(A) -> ubyte @ X, ubyte @ Y ; read/set position of cursor on screen. Use txt.plot for a 'safe' wrapper that preserves X.
romsub $FFF3 = IOBASE() -> uword @ XY ; read base address of I/O devices romsub $FFF3 = IOBASE() -> uword @ XY ; read base address of I/O devices
inline asmsub STOP2() clobbers(X,A) -> bool @Pz {
; -- just like STOP, but omits the special keys result value in A.
; just for convenience because most of the times you're only interested in the stop pressed or not status.
%asm {{
jsr cbm.STOP
}}
}
inline asmsub GETIN2() clobbers(X,Y) -> ubyte @A {
; -- just like GETIN, but omits the carry flag result value.
; just for convenience because GETIN is so often used to just read keyboard input,
; where you don't have to deal with a potential error status
%asm {{
jsr cbm.GETIN
}}
}
asmsub RDTIM16() clobbers(X) -> uword @AY { asmsub RDTIM16() clobbers(X) -> uword @AY {
; -- like RDTIM() but only returning the lower 16 bits in AY for convenience ; -- like RDTIM() but only returning the lower 16 bits in AY for convenience
%asm {{ %asm {{

View File

@ -43,8 +43,8 @@ romsub $FFD5 = LOAD(ubyte verify @ A, uword address @ XY) -> bool @Pc, ubyte @ A
romsub $FFD8 = SAVE(ubyte zp_startaddr @ A, uword endaddr @ XY) clobbers (X, Y) -> bool @ Pc, ubyte @ A ; (via 818 ($332)) save to a device. See also BSAVE romsub $FFD8 = SAVE(ubyte zp_startaddr @ A, uword endaddr @ XY) clobbers (X, Y) -> bool @ Pc, ubyte @ A ; (via 818 ($332)) save to a device. See also BSAVE
romsub $FFDB = SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) ; set the software clock romsub $FFDB = SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) ; set the software clock
romsub $FFDE = RDTIM() -> ubyte @ A, ubyte @ X, ubyte @ Y ; read the software clock (in little endian order: A=lo,X=mid,Y=high) , however use RDTIM_safe() instead romsub $FFDE = RDTIM() -> ubyte @ A, ubyte @ X, ubyte @ Y ; read the software clock (in little endian order: A=lo,X=mid,Y=high) , however use RDTIM_safe() instead
romsub $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; (via 808 ($328)) check the STOP key (and some others in A) romsub $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; (via 808 ($328)) check the STOP key (and some others in A) also see STOP2
romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; (via 810 ($32A)) get a character romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; (via 810 ($32A)) get a character also see GETIN2
romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files
romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock
romsub $FFED = SCREEN() -> ubyte @ X, ubyte @ Y ; read number of screen rows and columns romsub $FFED = SCREEN() -> ubyte @ X, ubyte @ Y ; read number of screen rows and columns
@ -53,6 +53,23 @@ romsub $FFF3 = IOBASE() -> uword @ XY ; read base addr
; ---- utility ; ---- utility
inline asmsub STOP2() clobbers(X,A) -> bool @Pz {
; -- just like STOP, but omits the special keys result value in A.
; just for convenience because most of the times you're only interested in the stop pressed or not status.
%asm {{
jsr cbm.STOP
}}
}
inline asmsub GETIN2() clobbers(X,Y) -> ubyte @A {
; -- just like GETIN, but omits the carry flag result value.
; just for convenience because GETIN is so often used to just read keyboard input,
; where you don't have to deal with a potential error status
%asm {{
jsr cbm.GETIN
}}
}
asmsub RDTIM_safe() -> ubyte @ A, ubyte @ X, ubyte @ Y { asmsub RDTIM_safe() -> ubyte @ A, ubyte @ X, ubyte @ Y {
; -- read the software clock (in little endian order: A=lo,X=mid,Y=high) ; -- read the software clock (in little endian order: A=lo,X=mid,Y=high)
; with safeguard for ram bank issue for irqs. ; with safeguard for ram bank issue for irqs.

View File

@ -29,11 +29,29 @@ romsub $FFC9 = CHKOUT(ubyte logical @ X) clobbers(A,X) ; define an outp
romsub $FFCC = CLRCHN() clobbers(A,X) ; restore default devices romsub $FFCC = CLRCHN() clobbers(A,X) ; restore default devices
romsub $FFCF = CHRIN() clobbers(X, Y) -> ubyte @ A ; input a character (for keyboard, read a whole line from the screen) A=byte read. romsub $FFCF = CHRIN() clobbers(X, Y) -> ubyte @ A ; input a character (for keyboard, read a whole line from the screen) A=byte read.
romsub $FFD2 = CHROUT(ubyte character @ A) ; output a character romsub $FFD2 = CHROUT(ubyte character @ A) ; output a character
romsub $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; check the STOP key (and some others in A) romsub $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; check the STOP key (and some others in A) also see STOP2
romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; get a character romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; get a character also see GETIN2
romsub $FFE7 = CLALL() clobbers(A,X) ; close all files romsub $FFE7 = CLALL() clobbers(A,X) ; close all files
romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock
inline asmsub STOP2() clobbers(X,A) -> bool @Pz {
; -- just like STOP, but omits the special keys result value in A.
; just for convenience because most of the times you're only interested in the stop pressed or not status.
%asm {{
jsr cbm.STOP
}}
}
inline asmsub GETIN2() clobbers(X,Y) -> ubyte @A {
; -- just like GETIN, but omits the carry flag result value.
; just for convenience because GETIN is so often used to just read keyboard input,
; where you don't have to deal with a potential error status
%asm {{
jsr cbm.GETIN
}}
}
asmsub SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) { asmsub SETTIM(ubyte low @ A, ubyte middle @ X, ubyte high @ Y) {
; PET stub to set the software clock ; PET stub to set the software clock
%asm {{ %asm {{

View File

@ -12,6 +12,9 @@ import prog8.ast.ParentSentinel
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.expressions.* import prog8.ast.expressions.*
import prog8.ast.statements.* import prog8.ast.statements.*
import prog8.code.ast.PtAssignTarget
import prog8.code.ast.PtAssignment
import prog8.code.ast.PtFunctionCall
import prog8.code.core.DataType import prog8.code.core.DataType
import prog8.code.core.Position import prog8.code.core.Position
import prog8.code.target.C64Target import prog8.code.target.C64Target
@ -972,4 +975,59 @@ main {
(right2.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read") (right2.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read")
(right3.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read") (right3.left as FunctionCallExpression).target.nameInSource shouldBe listOf("diskio", "f_read")
} }
test("eliminate same target register assignments") {
val src="""
%zeropage basicsafe
%option no_sysinit
main {
romsub ${'$'}2000 = func1() clobbers(X) -> ubyte @A, word @R0, byte @R1
romsub ${'$'}3000 = func2() clobbers(X) -> ubyte @A, uword @R0, uword @R1
romsub ${'$'}4000 = func3() clobbers(X) -> ubyte @R0
sub start() {
bool flag
void cbm.GETIN()
flag, cx16.r1L = cbm.GETIN()
void, cx16.r0s, cx16.r1sL = func1()
void, cx16.r2, cx16.r1 = func2()
cx16.r0L = func3()
cx16.r0H = func3()
}
}"""
val result = compileText(C64Target(), true, src, writeAssembly = true)!!
val st = result.codegenAst!!.entrypoint()!!.children
st.size shouldBe 9
(st[2] as PtFunctionCall).name shouldBe "cbm.GETIN"
(st[2] as PtFunctionCall).void shouldBe true
val a1 = st[3] as PtAssignment
(a1.value as PtFunctionCall).name shouldBe "cbm.GETIN"
a1.multiTarget shouldBe true
a1.children.size shouldBe 3
(a1.children[0] as PtAssignTarget).void shouldBe false
(a1.children[0] as PtAssignTarget).identifier!!.name shouldBe "p8b_main.p8s_start.p8v_flag"
(a1.children[1] as PtAssignTarget).void shouldBe false
(a1.children[1] as PtAssignTarget).identifier!!.name shouldBe "cx16.r1L"
(st[4] as PtFunctionCall).name shouldBe "p8b_main.p8s_func1"
(st[4] as PtFunctionCall).void shouldBe true
val a2 = st[5] as PtAssignment
(a2.value as PtFunctionCall).name shouldBe "p8b_main.p8s_func2"
a2.multiTarget shouldBe true
a2.children.size shouldBe 4
(a2.children[0] as PtAssignTarget).void shouldBe true
(a2.children[1] as PtAssignTarget).void shouldBe false
(a2.children[1] as PtAssignTarget).identifier!!.name shouldBe "cx16.r2"
(a2.children[2] as PtAssignTarget).void shouldBe true
(st[6] as PtFunctionCall).name shouldBe "p8b_main.p8s_func3"
(st[6] as PtFunctionCall).void shouldBe true
val a3 = st[7] as PtAssignment
(a3.value as PtFunctionCall).name shouldBe "p8b_main.p8s_func3"
a3.multiTarget shouldBe false
a3.children.size shouldBe 2
(a3.children[0] as PtAssignTarget).void shouldBe false
(a3.children[0] as PtAssignTarget).identifier!!.name shouldBe "cx16.r0H"
}
}) })

View File

@ -1,7 +1,10 @@
TODO TODO
==== ====
add unit test for what's now in test.p8 (multi assign stuff) imageviewer is a lot larger now?
fix compiler crash for assembler: unknown identifier [PtIdentifier:parser.proces_directive_str.prog8_subexprvar_1 UBYTE [src/assembler.p8: line 875 col 29-29]]
fix similar crash for petaxian
check docs on assign about status register in assignment (can no longer be ignored, use void to not assign it) check docs on assign about status register in assignment (can no longer be ignored, use void to not assign it)