mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
added 'callrom' builtin function (for cx16 target) that calls a routine in banked ROM
This commit is contained in:
parent
1170aed026
commit
68f696d165
@ -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),
|
||||
|
||||
)
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user