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"))) {
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) {
val index = node.parent.children.indexOf(node)
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 $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 $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; (via 808 ($328)) check the STOP key (and some others in A)
romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; (via 810 ($32A)) get a character
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 also see GETIN2
romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files
romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock
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 -----
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 {
; -- like RDTIM() but only returning the lower 16 bits in AY for convenience
%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 $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 $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; (via 808 ($328)) check the STOP key (and some others in A)
romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; (via 810 ($32A)) get a character
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 also see GETIN2
romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files
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 $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
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 {
; -- like RDTIM() but only returning the lower 16 bits in AY for convenience
%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 $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 $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; (via 808 ($328)) check the STOP key (and some others in A)
romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; (via 810 ($32A)) get a character
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 also see GETIN2
romsub $FFE7 = CLALL() clobbers(A,X) ; (via 812 ($32C)) close all files
romsub $FFEA = UDTIM() clobbers(A,X) ; update the software clock
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
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 {
; -- read the software clock (in little endian order: A=lo,X=mid,Y=high)
; 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 $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 $FFE1 = STOP() clobbers(X) -> bool @ Pz, ubyte @ A ; check the STOP key (and some others in A)
romsub $FFE4 = GETIN() clobbers(X,Y) -> bool @Pc, ubyte @ A ; get a character
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 also see GETIN2
romsub $FFE7 = CLALL() clobbers(A,X) ; close all files
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) {
; PET stub to set the software clock
%asm {{

View File

@ -12,6 +12,9 @@ import prog8.ast.ParentSentinel
import prog8.ast.Program
import prog8.ast.expressions.*
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.Position
import prog8.code.target.C64Target
@ -972,4 +975,59 @@ main {
(right2.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
====
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)