added 'callrom' builtin function (for cx16 target) that calls a routine in banked ROM

This commit is contained in:
Irmen de Jong 2021-04-25 18:04:56 +02:00
parent 1170aed026
commit 68f696d165
5 changed files with 94 additions and 1 deletions

View File

@ -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("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("callrom" , false, listOf(FParam("bank", setOf(DataType.UBYTE)), FParam("address", setOf(DataType.UWORD)), FParam("arg", setOf(DataType.UWORD))), null),
)

View File

@ -67,6 +67,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
"poke" -> throw AssemblyError("poke() should have been replaced by @()")
"cmp" -> funcCmp(fcall)
"callfar" -> funcCallFar(fcall)
"callrom" -> funcCallRom(fcall)
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) {
val arg1 = fcall.args[0]
val arg2 = fcall.args[1]

View File

@ -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
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, ``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

View File

@ -16,6 +16,26 @@ main {
txt.nl()
callfar($01, $a000, &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)
}
}

View File

@ -17,7 +17,7 @@ syn keyword prog8BuiltInFunc any all len max min reverse sum sort
" Miscellaneous functions
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 swap memory callfar
syn keyword prog8BuiltInFunc swap memory callfar callrom
" c64/floats.p8