consolidate @rombank and @rambank into just @bank

This commit is contained in:
Irmen de Jong 2024-11-03 21:00:39 +01:00
parent cb47e2c149
commit 85e87dfe2e
22 changed files with 105 additions and 130 deletions

View File

@ -1,6 +1,5 @@
package prog8.code
import prog8.code.ast.PtAsmSub
import prog8.code.ast.PtNode
import prog8.code.ast.PtProgram
import prog8.code.core.*
@ -258,7 +257,7 @@ class StSub(name: String, val parameters: List<StSubroutineParameter>, val retur
class StRomSub(name: String,
val address: PtAsmSub.Address?, // null in case of asmsub, specified in case of romsub
val address: Pair<UByte?, UInt>?, // null in case of asmsub, specified in case of romsub. bank, address.
val parameters: List<StRomSubParameter>,
val returns: List<StRomSubParameter>,
astNode: PtNode) :

View File

@ -92,9 +92,8 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni
if(node.address == null) {
str + "asmsub ${node.name}($params) $clobbers $returns"
} else {
val rombank = if(node.address.rombank!=null) "@rombank ${node.address.rombank}" else ""
val rambank = if(node.address.rambank!=null) "@rambank ${node.address.rambank}" else ""
str + "romsub $rombank $rambank ${node.address.address.toHex()} = ${node.name}($params) $clobbers $returns"
val bank = if(node.address.first!=null) "@bank ${node.address.first}" else ""
str + "romsub $bank ${node.address.second.toHex()} = ${node.name}($params) $clobbers $returns"
}
}
is PtBlock -> {

View File

@ -10,16 +10,13 @@ sealed interface IPtSubroutine {
class PtAsmSub(
name: String,
val address: Address?,
val address: Pair<UByte?, UInt>?, // bank, address
val clobbers: Set<CpuRegister>,
val parameters: List<Pair<RegisterOrStatusflag, PtSubroutineParameter>>,
val returns: List<Pair<RegisterOrStatusflag, DataType>>,
val inline: Boolean,
position: Position
) : PtNamedNode(name, position), IPtSubroutine {
class Address(val rombank: UByte?, val rambank: UByte?, val address: UInt)
}
) : PtNamedNode(name, position), IPtSubroutine
class PtSub(

View File

@ -40,30 +40,20 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
sub.children.forEach { asmgen.translate(it as PtInlineAssembly) }
asmgen.out(" \t; inlined routine end: ${sub.name}")
} else {
val rombank = sub.address?.rombank
val rambank = sub.address?.rambank
if(rombank==null && rambank==null)
val bank = sub.address?.first
if(bank==null)
asmgen.out(" jsr $subAsmName")
else {
when(asmgen.options.compTarget.name) {
"cx16" -> {
if(rambank!=null) {
// JSRFAR can jump to a banked RAM address as well!
asmgen.out("""
jsr cx16.JSRFAR
.word $subAsmName ; ${sub.address!!.address.toHex()}
.byte $rambank"""
)
} else {
asmgen.out("""
jsr cx16.JSRFAR
.word $subAsmName ; ${sub.address!!.address.toHex()}
.byte $rombank"""
)
}
// JSRFAR can jump to a banked RAM address as well!
asmgen.out("""
jsr cx16.JSRFAR
.word $subAsmName ; ${sub.address!!.second.toHex()}
.byte $bank"""
)
}
"c128" -> {
val bank = rambank ?: rombank!!
// see https://cx16.dk/c128-kernal-routines/jsrfar.html
asmgen.out("""
sty $08

View File

@ -781,8 +781,8 @@ internal class ProgramAndVarsGen(
.forEach { asmsub ->
asmsub as PtAsmSub
val address = asmsub.address!!
val bank = if(address.rombank!=null) "; @rombank ${address.rombank}" else if(address.rambank!=null) "; @rambank ${address.rambank}" else ""
asmgen.out(" ${asmsub.name} = ${address.address.toHex()} $bank")
val bank = if(address.first!=null) "; @bank ${address.first}" else ""
asmgen.out(" ${asmsub.name} = ${address.second.toHex()} $bank")
}
}

View File

@ -645,10 +645,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
IRInstruction(Opcode.CALL, labelSymbol = fcall.name, fcallArgs = FunctionCallArgs(argRegisters, returnRegs))
else {
val address = callTarget.address!!
if(address.rombank==null && address.rambank==null) {
if(address.first==null) {
IRInstruction(
Opcode.CALL,
address = address.address.toInt(),
address = address.second.toInt(),
fcallArgs = FunctionCallArgs(argRegisters, returnRegs))
}
else {
@ -767,10 +767,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
IRInstruction(Opcode.CALL, labelSymbol = fcall.name, fcallArgs = FunctionCallArgs(argRegisters, returnRegisters))
else {
val address = callTarget.address!!
if(address.rombank==null && address.rambank==null) {
if(address.first==null) {
IRInstruction(
Opcode.CALL,
address = address.address.toInt(),
address = address.second.toInt(),
fcallArgs = FunctionCallArgs(argRegisters, returnRegisters)
)
}

View File

@ -534,7 +534,7 @@ class TestVmCodeGen: FunSpec({
val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY)
val romsub = PtAsmSub("routine", PtAsmSub.Address(null, null, 0x5000u), setOf(CpuRegister.Y), emptyList(), emptyList(), false, Position.DUMMY)
val romsub = PtAsmSub("routine", null to 0x5000u, setOf(CpuRegister.Y), emptyList(), emptyList(), false, Position.DUMMY)
block.add(romsub)
val sub = PtSub("start", emptyList(), null, Position.DUMMY)
val call = PtFunctionCall("main.routine", true, DataType.UNDEFINED, Position.DUMMY)

View File

@ -484,62 +484,62 @@ romsub $C006 = x16edit_loadfile_options(ubyte firstbank @X, ubyte lastbank @Y, s
uword disknumberAndColors @R3, uword headerAndStatusColors @R4) clobbers(A,X,Y)
; Audio (rom bank 10)
romsub @rombank 10 $C09F = audio_init() clobbers(A,X,Y) -> bool @Pc ; (re)initialize both vera PSG and YM audio chips
romsub @rombank 10 $C000 = bas_fmfreq(ubyte channel @A, uword freq @XY, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C003 = bas_fmnote(ubyte channel @A, ubyte note @X, ubyte fracsemitone @Y, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C006 = bas_fmplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y)
romsub @rombank 10 $C009 = bas_fmvib(ubyte speed @A, ubyte depth @X) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C00C = bas_playstringvoice(ubyte channel @A) clobbers(Y)
romsub @rombank 10 $C00F = bas_psgfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C012 = bas_psgnote(ubyte voice @A, ubyte note @X, ubyte fracsemitone @Y) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C015 = bas_psgwav(ubyte voice @A, ubyte waveform @X) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C018 = bas_psgplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y)
romsub @rombank 10 $C08D = bas_fmchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y)
romsub @rombank 10 $C090 = bas_psgchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y)
romsub @rombank 10 $C01B = notecon_bas2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @rombank 10 $C01E = notecon_bas2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @rombank 10 $C021 = notecon_bas2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
romsub @rombank 10 $C024 = notecon_fm2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @rombank 10 $C027 = notecon_fm2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @rombank 10 $C02A = notecon_fm2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
romsub @rombank 10 $C02D = notecon_freq2bas(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @rombank 10 $C030 = notecon_freq2fm(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @rombank 10 $C033 = notecon_freq2midi(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @rombank 10 $C036 = notecon_freq2psg(uword freqHz @XY) clobbers(A) -> uword @XY, bool @Pc
romsub @rombank 10 $C039 = notecon_midi2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @rombank 10 $C03C = notecon_midi2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @rombank 10 $C03F = notecon_midi2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
romsub @rombank 10 $C042 = notecon_psg2bas(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @rombank 10 $C045 = notecon_psg2fm(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @rombank 10 $C048 = notecon_psg2midi(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @rombank 10 $C04B = psg_init() clobbers(A,X,Y) ; (re)init Vera PSG
romsub @rombank 10 $C04E = psg_playfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y)
romsub @rombank 10 $C051 = psg_read(ubyte offset @X, bool cookedVol @Pc) clobbers(Y) -> ubyte @A
romsub @rombank 10 $C054 = psg_setatten(ubyte voice @A, ubyte attenuation @X) clobbers(A,X,Y)
romsub @rombank 10 $C057 = psg_setfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y)
romsub @rombank 10 $C05A = psg_setpan(ubyte voice @A, ubyte panning @X) clobbers(A,X,Y)
romsub @rombank 10 $C05D = psg_setvol(ubyte voice @A, ubyte volume @X) clobbers(A,X,Y)
romsub @rombank 10 $C060 = psg_write(ubyte value @A, ubyte offset @X) clobbers(Y)
romsub @rombank 10 $C0A2 = psg_write_fast(ubyte value @A, ubyte offset @X) clobbers(Y)
romsub @rombank 10 $C093 = psg_getatten(ubyte voice @A) clobbers(Y) -> ubyte @X
romsub @rombank 10 $C096 = psg_getpan(ubyte voice @A) clobbers(Y) -> ubyte @X
romsub @rombank 10 $C063 = ym_init() clobbers(A,X,Y) -> bool @Pc ; (re)init YM chip
romsub @rombank 10 $C066 = ym_loaddefpatches() clobbers(A,X,Y) -> bool @Pc ; load default YM patches
romsub @rombank 10 $C069 = ym_loadpatch(ubyte channel @A, uword patchOrAddress @XY, bool what @Pc) clobbers(A,X,Y)
romsub @rombank 10 $C06C = ym_loadpatchlfn(ubyte channel @A, ubyte lfn @X) clobbers(X,Y) -> ubyte @A, bool @Pc
romsub @rombank 10 $C06F = ym_playdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C072 = ym_playnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y, bool notrigger @Pc) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C075 = ym_setatten(ubyte channel @A, ubyte attenuation @X) clobbers(Y) -> bool @Pc
romsub @rombank 10 $C078 = ym_setdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C07B = ym_setnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C07E = ym_setpan(ubyte channel @A, ubyte panning @X) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C081 = ym_read(ubyte register @X, bool cooked @Pc) clobbers(Y) -> ubyte @A, bool @Pc
romsub @rombank 10 $C084 = ym_release(ubyte channel @A) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C087 = ym_trigger(ubyte channel @A, bool noRelease @Pc) clobbers(A,X,Y) -> bool @Pc
romsub @rombank 10 $C08A = ym_write(ubyte value @A, ubyte register @X) clobbers(Y) -> bool @Pc
romsub @rombank 10 $C099 = ym_getatten(ubyte channel @A) clobbers(Y) -> ubyte @X
romsub @rombank 10 $C09C = ym_getpan(ubyte channel @A) clobbers(Y) -> ubyte @X
romsub @rombank 10 $C0A5 = ym_get_chip_type() clobbers(X) -> ubyte @A
romsub @bank 10 $C09F = audio_init() clobbers(A,X,Y) -> bool @Pc ; (re)initialize both vera PSG and YM audio chips
romsub @bank 10 $C000 = bas_fmfreq(ubyte channel @A, uword freq @XY, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C003 = bas_fmnote(ubyte channel @A, ubyte note @X, ubyte fracsemitone @Y, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C006 = bas_fmplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y)
romsub @bank 10 $C009 = bas_fmvib(ubyte speed @A, ubyte depth @X) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C00C = bas_playstringvoice(ubyte channel @A) clobbers(Y)
romsub @bank 10 $C00F = bas_psgfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C012 = bas_psgnote(ubyte voice @A, ubyte note @X, ubyte fracsemitone @Y) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C015 = bas_psgwav(ubyte voice @A, ubyte waveform @X) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C018 = bas_psgplaystring(ubyte length @A, str string @XY) clobbers(A,X,Y)
romsub @bank 10 $C08D = bas_fmchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y)
romsub @bank 10 $C090 = bas_psgchordstring(ubyte length @A, str string @XY) clobbers(A,X,Y)
romsub @bank 10 $C01B = notecon_bas2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @bank 10 $C01E = notecon_bas2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @bank 10 $C021 = notecon_bas2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
romsub @bank 10 $C024 = notecon_fm2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @bank 10 $C027 = notecon_fm2midi(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @bank 10 $C02A = notecon_fm2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
romsub @bank 10 $C02D = notecon_freq2bas(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @bank 10 $C030 = notecon_freq2fm(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @bank 10 $C033 = notecon_freq2midi(uword freqHz @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @bank 10 $C036 = notecon_freq2psg(uword freqHz @XY) clobbers(A) -> uword @XY, bool @Pc
romsub @bank 10 $C039 = notecon_midi2bas(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @bank 10 $C03C = notecon_midi2fm(ubyte note @X) clobbers(A) -> ubyte @X, bool @Pc
romsub @bank 10 $C03F = notecon_midi2psg(ubyte note @X, ubyte fracsemitone @Y) clobbers(A) -> uword @XY, bool @Pc
romsub @bank 10 $C042 = notecon_psg2bas(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @bank 10 $C045 = notecon_psg2fm(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @bank 10 $C048 = notecon_psg2midi(uword freq @XY) clobbers(A) -> ubyte @X, ubyte @Y, bool @Pc
romsub @bank 10 $C04B = psg_init() clobbers(A,X,Y) ; (re)init Vera PSG
romsub @bank 10 $C04E = psg_playfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y)
romsub @bank 10 $C051 = psg_read(ubyte offset @X, bool cookedVol @Pc) clobbers(Y) -> ubyte @A
romsub @bank 10 $C054 = psg_setatten(ubyte voice @A, ubyte attenuation @X) clobbers(A,X,Y)
romsub @bank 10 $C057 = psg_setfreq(ubyte voice @A, uword freq @XY) clobbers(A,X,Y)
romsub @bank 10 $C05A = psg_setpan(ubyte voice @A, ubyte panning @X) clobbers(A,X,Y)
romsub @bank 10 $C05D = psg_setvol(ubyte voice @A, ubyte volume @X) clobbers(A,X,Y)
romsub @bank 10 $C060 = psg_write(ubyte value @A, ubyte offset @X) clobbers(Y)
romsub @bank 10 $C0A2 = psg_write_fast(ubyte value @A, ubyte offset @X) clobbers(Y)
romsub @bank 10 $C093 = psg_getatten(ubyte voice @A) clobbers(Y) -> ubyte @X
romsub @bank 10 $C096 = psg_getpan(ubyte voice @A) clobbers(Y) -> ubyte @X
romsub @bank 10 $C063 = ym_init() clobbers(A,X,Y) -> bool @Pc ; (re)init YM chip
romsub @bank 10 $C066 = ym_loaddefpatches() clobbers(A,X,Y) -> bool @Pc ; load default YM patches
romsub @bank 10 $C069 = ym_loadpatch(ubyte channel @A, uword patchOrAddress @XY, bool what @Pc) clobbers(A,X,Y)
romsub @bank 10 $C06C = ym_loadpatchlfn(ubyte channel @A, ubyte lfn @X) clobbers(X,Y) -> ubyte @A, bool @Pc
romsub @bank 10 $C06F = ym_playdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C072 = ym_playnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y, bool notrigger @Pc) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C075 = ym_setatten(ubyte channel @A, ubyte attenuation @X) clobbers(Y) -> bool @Pc
romsub @bank 10 $C078 = ym_setdrum(ubyte channel @A, ubyte note @X) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C07B = ym_setnote(ubyte channel @A, ubyte kc @X, ubyte kf @Y) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C07E = ym_setpan(ubyte channel @A, ubyte panning @X) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C081 = ym_read(ubyte register @X, bool cooked @Pc) clobbers(Y) -> ubyte @A, bool @Pc
romsub @bank 10 $C084 = ym_release(ubyte channel @A) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C087 = ym_trigger(ubyte channel @A, bool noRelease @Pc) clobbers(A,X,Y) -> bool @Pc
romsub @bank 10 $C08A = ym_write(ubyte value @A, ubyte register @X) clobbers(Y) -> bool @Pc
romsub @bank 10 $C099 = ym_getatten(ubyte channel @A) clobbers(Y) -> ubyte @X
romsub @bank 10 $C09C = ym_getpan(ubyte channel @A) clobbers(Y) -> ubyte @X
romsub @bank 10 $C0A5 = ym_get_chip_type() clobbers(X) -> ubyte @A
; extapi call numbers
const ubyte EXTAPI_clear_status = $01

View File

@ -377,11 +377,8 @@ internal class AstChecker(private val program: Program,
if(uniqueNames.size!=subroutine.parameters.size)
err("parameter names must be unique")
val rambank = subroutine.asmAddress?.rambank
val rombank = subroutine.asmAddress?.rombank
if(rambank!=null && rambank>255u)
err("bank must be 0 to 255")
if(rombank!=null && rombank>255u)
val bank = subroutine.asmAddress?.first
if(bank!=null && bank>255u)
err("bank must be 0 to 255")
if(subroutine.inline && subroutine.asmAddress!=null)
throw FatalAstException("romsub cannot be inline")

View File

@ -466,7 +466,7 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
private fun transformAsmSub(srcSub: Subroutine): PtAsmSub {
val params = srcSub.asmParameterRegisters.zip(srcSub.parameters.map { PtSubroutineParameter(it.name, it.type, it.position) })
val asmAddr = if(srcSub.asmAddress==null) null else PtAsmSub.Address(srcSub.asmAddress!!.rombank?.toUByte(), srcSub.asmAddress!!.rambank?.toUByte(), srcSub.asmAddress!!.address)
val asmAddr = if(srcSub.asmAddress==null) null else srcSub.asmAddress!!.first to srcSub.asmAddress!!.second
val sub = PtAsmSub(srcSub.name,
asmAddr,
srcSub.asmClobbers,

View File

@ -181,9 +181,8 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
output("inline ")
if(subroutine.isAsmSubroutine) {
if(subroutine.asmAddress!=null) {
val rombank = if(subroutine.asmAddress.rombank!=null) "@rombank ${subroutine.asmAddress.rombank}" else ""
val rambank = if(subroutine.asmAddress.rambank!=null) "@rambank ${subroutine.asmAddress.rambank}" else ""
output("romsub $rombank $rambank ${subroutine.asmAddress.address.toHex()} = ${subroutine.name} (")
val bank = if(subroutine.asmAddress.first!=null) "@bank ${subroutine.asmAddress.first}" else ""
output("romsub $bank ${subroutine.asmAddress.second.toHex()} = ${subroutine.name} (")
}
else
output("asmsub ${subroutine.name} (")

View File

@ -173,9 +173,8 @@ private class SymbolDumper(val skipLibraries: Boolean): IAstVisitor {
}
}
if(subroutine.asmAddress!=null) {
val rombank = if(subroutine.asmAddress.rombank!=null) "@rombank ${subroutine.asmAddress.rombank}" else ""
val rambank = if(subroutine.asmAddress.rambank!=null) "@rambank ${subroutine.asmAddress.rambank}" else ""
output("$rombank $rambank = ${subroutine.asmAddress.address.toHex()}")
val bank = if(subroutine.asmAddress.first!=null) "@bank ${subroutine.asmAddress.first}" else ""
output("$bank = ${subroutine.asmAddress.second.toHex()}")
}
output("\n")

View File

@ -177,13 +177,11 @@ private fun AsmsubroutineContext.toAst(): Subroutine {
private fun RomsubroutineContext.toAst(): Subroutine {
val subdecl = asmsub_decl().toAst()
val rombank = rombankspec()?.integerliteral()?.toAst()?.number?.toUInt()
val rambank = rambankspec()?.integerliteral()?.toAst()?.number?.toUInt()
val addr = integerliteral().toAst().number.toUInt()
val address = Subroutine.Address(rombank, rambank, addr)
val bank = bank?.toAst()?.number?.toUInt()?.toUByte()
val addr = address.toAst().number.toUInt()
return Subroutine(subdecl.name, subdecl.parameters.toMutableList(), subdecl.returntypes.toMutableList(),
subdecl.asmParameterRegisters, subdecl.asmReturnvaluesRegisters,
subdecl.asmClobbers, address, true, inline = false, statements = mutableListOf(), position = toPosition()
subdecl.asmClobbers, bank to addr, true, inline = false, statements = mutableListOf(), position = toPosition()
)
}

View File

@ -442,8 +442,7 @@ data class AddressOf(var identifier: IdentifierReference, var arrayIndex: ArrayI
}
val targetAsmAddress = (target as? Subroutine)?.asmAddress
if(targetAsmAddress!=null) {
if(targetAsmAddress.rombank==null && targetAsmAddress.rambank==null)
return NumericLiteral(DataType.UWORD, targetAsmAddress.address.toDouble(), position)
return NumericLiteral(DataType.UWORD, targetAsmAddress.second.toDouble(), position)
}
return null
}

View File

@ -806,7 +806,7 @@ class Subroutine(override val name: String,
val asmParameterRegisters: List<RegisterOrStatusflag>,
val asmReturnvaluesRegisters: List<RegisterOrStatusflag>,
val asmClobbers: Set<CpuRegister>,
val asmAddress: Address?,
val asmAddress: Pair<UByte?, UInt>?, // bank, address
val isAsmSubroutine: Boolean,
var inline: Boolean,
var hasBeenInlined: Boolean=false,
@ -846,8 +846,6 @@ class Subroutine(override val name: String,
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString() =
"Subroutine(name=$name, parameters=$parameters, returntypes=$returntypes, ${statements.size} statements, address=$asmAddress)"
class Address(val rombank: UInt?, val rambank: UInt?, val address: UInt)
}
open class SubroutineParameter(val name: String,

View File

@ -793,8 +793,8 @@ This defines the ``LOAD`` subroutine at memory address $FFD5, taking arguments i
and returning stuff in several registers as well. The ``clobbers`` clause is used to signify to the compiler
what CPU registers are clobbered by the call instead of being unchanged or returning a meaningful result value.
**Banks:** it is possible to declare a non-standard ROM or RAM bank that the routine is living in, with ``@rombank`` or ``@rambank`` like this:
``romsub @rombank 10 $C09F = audio_init()`` to define a routine at $C09F in ROM bank 10.
**Banks:** it is possible to declare a non-standard ROM or RAM bank that the routine is living in, with ``@bank`` like this:
``romsub @bank 10 $C09F = audio_init()`` to define a routine at $C09F in bank 10.
See :ref:`banking` for more information.
.. note::

View File

@ -41,10 +41,10 @@ External subroutines defined with ``romsub`` can have a non-standard ROM or RAM
The compiler will then transparently change a call to this routine so that the correct bank is activated
automatically before the normal jump to the subroutine (and switched back on return). The programmer doesn't
have to bother anymore with setting/resetting the banks manually, or having the program crash because
the routine is called in the wrong bank! You define such a routine by adding ``@rombank <bank>`` or ``@rambank <bank>``
the routine is called in the wrong bank! You define such a routine by adding ``@bank <bank>``
to the romsub subroutine definition. This specifies the bank number where the subroutine is located in::
romsub @rombank 10 $C09F = audio_init()
romsub @bank 10 $C09F = audio_init()
When you then call this routine in your program as usual, the compiler will no longer generate a simple JSR instruction to the
routine. Instead it will generate a piece of code that automatically switches the ROM or RAM bank to the
@ -56,7 +56,7 @@ Other compilation targets don't have banking or prog8 doesn't yet support automa
Notice that the symbol for this routine in the assembly source code will still be defined as usual.
The bank number is not translated into assembly (only as a comment)::
p8s_audio_init = $c09f ; @rombank 10
p8s_audio_init = $c09f ; @bank 10
.. caution::
Calls with automatic bank switching like this are not safe to use from IRQ handlers. Don't use them there.

View File

@ -1,16 +1,14 @@
TODO
====
consolidate @rombank and @rambank into just @bank
add example for cx16 that compiles and loads libraries in different ram banks and calls romsub from rom and ram banks automatically
for releasenotes: gfx2.width and gfx2.height got renamed as gfx_lores.WIDTH/HEIGHT or gfx_hires4.WIDTH/HEIGTH constants. Screen mode routines also renamed.
add support for banked romsubs on the C64 as well (banks basic/kernal rom in/out)
rename 'romsub' to 'extsub' ? keep romsub as alias?
for releasenotes: gfx2.width and gfx2.height got renamed as gfx_lores.WIDTH/HEIGHT or gfx_hires4.WIDTH/HEIGTH constants. Screen mode routines also renamed.
regenerate symbol dump files
Improve register load order in subroutine call args assignments:

View File

@ -3,10 +3,15 @@
%zeropage basicsafe
main {
romsub @rombank 10 $C09F = audio_init()
romsub @rambank 22 $A000 = hiram_routine()
romsub @bank 10 $C09F = audio_init()
romsub @bank 5 $A000 = hiram_routine()
sub start() {
; put an rts in hiram bank 5 to not crash
cx16.rambank(5)
@($a000) = $60
cx16.rambank(0)
audio_init()
hiram_routine()
}

View File

@ -294,12 +294,9 @@ asmsubroutine :
;
romsubroutine :
'romsub' (rombankspec | rambankspec)? integerliteral '=' asmsub_decl
'romsub' ('@bank' bank=integerliteral)? address=integerliteral '=' asmsub_decl
;
rombankspec : '@rombank' integerliteral;
rambankspec : '@rambank' integerliteral;
asmsub_decl : identifier '(' asmsub_params? ')' asmsub_clobbers? asmsub_returns? ;
asmsub_params : asmsub_param (',' EOL? asmsub_param)* ;

View File

@ -12,7 +12,7 @@
<option name="HAS_STRING_ESCAPES" value="true" />
</options>
<keywords keywords="&amp;;-&gt;;@;and;as;asmsub;break;clobbers;continue;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;unroll;until;when;while;xor;~" ignore_case="false" />
<keywords2 keywords="%address;%align;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%launcher;%memtop;%option;%output;%zeropage;%zpallowed;%zpreserved;@align64;@alignpage;@alignword;@nozp;@requirezp;@shared;@split;@zp;atascii:;cp437:;default:;iso16:;iso5:;iso:;kata:;petscii:;sc:" />
<keywords2 keywords="%address;%align;%asm;%asmbinary;%asminclude;%breakpoint;%encoding;%import;%ir;%launcher;%memtop;%option;%output;%zeropage;%zpallowed;%zpreserved;@align64;@alignpage;@alignword;@bank;@nozp;@requirezp;@shared;@split;@zp;atascii:;cp437:;default:;iso16:;iso5:;iso:;kata:;petscii:;sc:" />
<keywords3 keywords="bool;byte;const;float;str;ubyte;uword;void;word" />
<keywords4 keywords="abs;call;callfar;callfar2;clamp;cmp;defer;divmod;len;lsb;max;memory;min;mkword;msb;peek;peekf;peekw;poke;pokef;pokew;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;setlsb;setmsb;sgn;sizeof;sqrt" />
</highlighting>

View File

@ -43,7 +43,7 @@ syn region prog8ArrayType matchgroup=prog8Type
\ start="\<\%(u\?byte\|u\?word\|float\|str\|bool\)\[" end="\]"
\ transparent
syn keyword prog8StorageClass const
syn match prog8StorageClass "\(^\|\s\)\(@zp\|@shared\|@split\|@nozp\|@requirezp\|@align64\|@alignword\|@alignpage\)\>"
syn match prog8StorageClass "\(^\|\s\)\(@zp\|@bank\|@shared\|@split\|@nozp\|@requirezp\|@align64\|@alignword\|@alignpage\)\>"
syn region prog8Block start="{" end="}" transparent
syn region prog8Expression start="(" end=")" transparent