mirror of
https://github.com/irmen/prog8.git
synced 2025-08-14 22:27:48 +00:00
added 'callrom' builtin function (for cx16 target) that calls a routine in banked ROM
This commit is contained in:
@@ -145,6 +145,7 @@ private val functionSignatures: List<FSignature> = listOf(
|
|||||||
FSignature("memory" , true, listOf(FParam("name", setOf(DataType.STR)), FParam("size", setOf(DataType.UWORD))), DataType.UWORD),
|
FSignature("memory" , true, listOf(FParam("name", setOf(DataType.STR)), FParam("size", setOf(DataType.UWORD))), DataType.UWORD),
|
||||||
FSignature("swap" , false, listOf(FParam("first", NumericDatatypes), FParam("second", NumericDatatypes)), null),
|
FSignature("swap" , false, listOf(FParam("first", NumericDatatypes), FParam("second", NumericDatatypes)), null),
|
||||||
FSignature("callfar" , false, listOf(FParam("bank", setOf(DataType.UBYTE)), FParam("address", setOf(DataType.UWORD)), FParam("arg", setOf(DataType.UWORD))), null),
|
FSignature("callfar" , false, listOf(FParam("bank", setOf(DataType.UBYTE)), FParam("address", setOf(DataType.UWORD)), FParam("arg", setOf(DataType.UWORD))), null),
|
||||||
|
FSignature("callrom" , false, listOf(FParam("bank", setOf(DataType.UBYTE)), FParam("address", setOf(DataType.UWORD)), FParam("arg", setOf(DataType.UWORD))), null),
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -67,6 +67,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
"poke" -> throw AssemblyError("poke() should have been replaced by @()")
|
"poke" -> throw AssemblyError("poke() should have been replaced by @()")
|
||||||
"cmp" -> funcCmp(fcall)
|
"cmp" -> funcCmp(fcall)
|
||||||
"callfar" -> funcCallFar(fcall)
|
"callfar" -> funcCallFar(fcall)
|
||||||
|
"callrom" -> funcCallRom(fcall)
|
||||||
else -> throw AssemblyError("missing asmgen for builtin func ${func.name}")
|
else -> throw AssemblyError("missing asmgen for builtin func ${func.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,6 +117,63 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun funcCallRom(fcall: IFunctionCall) {
|
||||||
|
if(asmgen.options.compTarget !is Cx16Target)
|
||||||
|
throw AssemblyError("callrom only works on cx16 target at this time")
|
||||||
|
|
||||||
|
val bank = fcall.args[0].constValue(program)?.number?.toInt()
|
||||||
|
val address = fcall.args[1].constValue(program)?.number?.toInt()
|
||||||
|
if(bank==null || address==null)
|
||||||
|
throw AssemblyError("callrom requires constant arguments")
|
||||||
|
|
||||||
|
if(address !in 0xc000..0xffff)
|
||||||
|
throw AssemblyError("callrom done on address outside of cx16 banked rom")
|
||||||
|
if(bank>=32)
|
||||||
|
throw AssemblyError("callrom bank must be <32")
|
||||||
|
|
||||||
|
val argAddrArg = fcall.args[2]
|
||||||
|
if(argAddrArg.constValue(program)?.number == 0) {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $01
|
||||||
|
pha
|
||||||
|
lda #${bank}
|
||||||
|
sta $01
|
||||||
|
jsr ${address.toHex()}
|
||||||
|
pla
|
||||||
|
sta $01""")
|
||||||
|
} else {
|
||||||
|
when(argAddrArg) {
|
||||||
|
is AddressOf -> {
|
||||||
|
if(argAddrArg.identifier.targetVarDecl(program)?.datatype != DataType.UBYTE)
|
||||||
|
throw AssemblyError("callrom done with 'arg' pointer to variable that's not UBYTE")
|
||||||
|
asmgen.out("""
|
||||||
|
lda $01
|
||||||
|
pha
|
||||||
|
lda #${bank}
|
||||||
|
sta $01
|
||||||
|
lda ${asmgen.asmVariableName(argAddrArg.identifier)}
|
||||||
|
jsr ${address.toHex()}
|
||||||
|
sta ${asmgen.asmVariableName(argAddrArg.identifier)}
|
||||||
|
pla
|
||||||
|
sta $01""")
|
||||||
|
}
|
||||||
|
is NumericLiteralValue -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda $01
|
||||||
|
pha
|
||||||
|
lda #${bank}
|
||||||
|
sta $01
|
||||||
|
lda ${argAddrArg.number.toHex()}
|
||||||
|
jsr ${address.toHex()}
|
||||||
|
sta ${argAddrArg.number.toHex()}
|
||||||
|
pla
|
||||||
|
sta $01""")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("callrom only accepts pointer-of a (ubyte) variable or constant memory address for the 'arg' parameter")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun funcCmp(fcall: IFunctionCall) {
|
private fun funcCmp(fcall: IFunctionCall) {
|
||||||
val arg1 = fcall.args[0]
|
val arg1 = fcall.args[0]
|
||||||
val arg2 = fcall.args[1]
|
val arg2 = fcall.args[1]
|
||||||
|
@@ -905,6 +905,20 @@ callfar(bank, address, argumentaddress) ; NOTE: specific to cx16 compiler t
|
|||||||
of an argument for the routine; it will be loaded into the A register and will
|
of an argument for the routine; it will be loaded into the A register and will
|
||||||
receive the result value returned by the routine in the A register. If you leave this at zero,
|
receive the result value returned by the routine in the A register. If you leave this at zero,
|
||||||
no argument passing will be done.
|
no argument passing will be done.
|
||||||
|
If the routine requires different arguments or return values, ``callfar`` cannot be used
|
||||||
|
and you'll have to set up a call to ``jsrfar`` yourself to process this.
|
||||||
|
|
||||||
|
callrom(bank, address, argumentaddress) ; NOTE: specific to cx16 compiler target for now
|
||||||
|
Calls an assembly routine in another rom-bank on the CommanderX16
|
||||||
|
The banked ROM is located in the address range $C000-$FFFF (16 kilobyte).
|
||||||
|
There are 32 banks (0 to 31).
|
||||||
|
The third argument can be used to designate the memory address
|
||||||
|
of an argument for the routine; it will be loaded into the A register and will
|
||||||
|
receive the result value returned by the routine in the A register. If you leave this at zero,
|
||||||
|
no argument passing will be done.
|
||||||
|
If the routine requires different arguments or return values, ``callrom`` cannot be used
|
||||||
|
and you'll have to set up a call in assembly code yourself that handles the banking and
|
||||||
|
argument/returnvalues.
|
||||||
|
|
||||||
|
|
||||||
Library routines
|
Library routines
|
||||||
|
@@ -16,6 +16,26 @@ main {
|
|||||||
txt.nl()
|
txt.nl()
|
||||||
callfar($01, $a000, &uu)
|
callfar($01, $a000, &uu)
|
||||||
txt.print_ub(uu)
|
txt.print_ub(uu)
|
||||||
|
|
||||||
|
uu = '\n'
|
||||||
|
callrom($00, $ffd2, &uu)
|
||||||
|
uu = 'a'
|
||||||
|
callrom($00, $ffd2, &uu)
|
||||||
|
uu = '!'
|
||||||
|
callrom($00, $ffd2, &uu)
|
||||||
|
uu = '\n'
|
||||||
|
callrom($00, $ffd2, &uu)
|
||||||
|
|
||||||
|
; cx16.rombank(0)
|
||||||
|
; %asm{{
|
||||||
|
; lda #13
|
||||||
|
; jsr $ffd2
|
||||||
|
; lda #'a'
|
||||||
|
; jsr $ffd2
|
||||||
|
; lda #13
|
||||||
|
; jsr $ffd2
|
||||||
|
; }}
|
||||||
|
; cx16.rombank(4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,7 @@ syn keyword prog8BuiltInFunc any all len max min reverse sum sort
|
|||||||
" Miscellaneous functions
|
" Miscellaneous functions
|
||||||
syn keyword prog8BuiltInFunc cmp lsb msb mkword peek peekw poke pokew rnd rndw
|
syn keyword prog8BuiltInFunc cmp lsb msb mkword peek peekw poke pokew rnd rndw
|
||||||
syn keyword prog8BuiltInFunc rndf fastrnd8 rol rol2 ror ror2 sizeof offsetof
|
syn keyword prog8BuiltInFunc rndf fastrnd8 rol rol2 ror ror2 sizeof offsetof
|
||||||
syn keyword prog8BuiltInFunc swap memory callfar
|
syn keyword prog8BuiltInFunc swap memory callfar callrom
|
||||||
|
|
||||||
|
|
||||||
" c64/floats.p8
|
" c64/floats.p8
|
||||||
|
Reference in New Issue
Block a user