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 package prog8.code
import prog8.code.ast.PtAsmSub
import prog8.code.ast.PtNode import prog8.code.ast.PtNode
import prog8.code.ast.PtProgram import prog8.code.ast.PtProgram
import prog8.code.core.* import prog8.code.core.*
@ -258,7 +257,7 @@ class StSub(name: String, val parameters: List<StSubroutineParameter>, val retur
class StRomSub(name: String, 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 parameters: List<StRomSubParameter>,
val returns: List<StRomSubParameter>, val returns: List<StRomSubParameter>,
astNode: PtNode) : astNode: PtNode) :

View File

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

View File

@ -10,16 +10,13 @@ sealed interface IPtSubroutine {
class PtAsmSub( class PtAsmSub(
name: String, name: String,
val address: Address?, val address: Pair<UByte?, UInt>?, // bank, address
val clobbers: Set<CpuRegister>, val clobbers: Set<CpuRegister>,
val parameters: List<Pair<RegisterOrStatusflag, PtSubroutineParameter>>, val parameters: List<Pair<RegisterOrStatusflag, PtSubroutineParameter>>,
val returns: List<Pair<RegisterOrStatusflag, DataType>>, val returns: List<Pair<RegisterOrStatusflag, DataType>>,
val inline: Boolean, val inline: Boolean,
position: Position position: Position
) : PtNamedNode(name, position), IPtSubroutine { ) : PtNamedNode(name, position), IPtSubroutine
class Address(val rombank: UByte?, val rambank: UByte?, val address: UInt)
}
class PtSub( 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) } sub.children.forEach { asmgen.translate(it as PtInlineAssembly) }
asmgen.out(" \t; inlined routine end: ${sub.name}") asmgen.out(" \t; inlined routine end: ${sub.name}")
} else { } else {
val rombank = sub.address?.rombank val bank = sub.address?.first
val rambank = sub.address?.rambank if(bank==null)
if(rombank==null && rambank==null)
asmgen.out(" jsr $subAsmName") asmgen.out(" jsr $subAsmName")
else { else {
when(asmgen.options.compTarget.name) { when(asmgen.options.compTarget.name) {
"cx16" -> { "cx16" -> {
if(rambank!=null) { // JSRFAR can jump to a banked RAM address as well!
// JSRFAR can jump to a banked RAM address as well! asmgen.out("""
asmgen.out(""" jsr cx16.JSRFAR
jsr cx16.JSRFAR .word $subAsmName ; ${sub.address!!.second.toHex()}
.word $subAsmName ; ${sub.address!!.address.toHex()} .byte $bank"""
.byte $rambank""" )
)
} else {
asmgen.out("""
jsr cx16.JSRFAR
.word $subAsmName ; ${sub.address!!.address.toHex()}
.byte $rombank"""
)
}
} }
"c128" -> { "c128" -> {
val bank = rambank ?: rombank!!
// see https://cx16.dk/c128-kernal-routines/jsrfar.html // see https://cx16.dk/c128-kernal-routines/jsrfar.html
asmgen.out(""" asmgen.out("""
sty $08 sty $08

View File

@ -781,8 +781,8 @@ internal class ProgramAndVarsGen(
.forEach { asmsub -> .forEach { asmsub ->
asmsub as PtAsmSub asmsub as PtAsmSub
val address = asmsub.address!! val address = asmsub.address!!
val bank = if(address.rombank!=null) "; @rombank ${address.rombank}" else if(address.rambank!=null) "; @rambank ${address.rambank}" else "" val bank = if(address.first!=null) "; @bank ${address.first}" else ""
asmgen.out(" ${asmsub.name} = ${address.address.toHex()} $bank") 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)) IRInstruction(Opcode.CALL, labelSymbol = fcall.name, fcallArgs = FunctionCallArgs(argRegisters, returnRegs))
else { else {
val address = callTarget.address!! val address = callTarget.address!!
if(address.rombank==null && address.rambank==null) { if(address.first==null) {
IRInstruction( IRInstruction(
Opcode.CALL, Opcode.CALL,
address = address.address.toInt(), address = address.second.toInt(),
fcallArgs = FunctionCallArgs(argRegisters, returnRegs)) fcallArgs = FunctionCallArgs(argRegisters, returnRegs))
} }
else { else {
@ -767,10 +767,10 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
IRInstruction(Opcode.CALL, labelSymbol = fcall.name, fcallArgs = FunctionCallArgs(argRegisters, returnRegisters)) IRInstruction(Opcode.CALL, labelSymbol = fcall.name, fcallArgs = FunctionCallArgs(argRegisters, returnRegisters))
else { else {
val address = callTarget.address!! val address = callTarget.address!!
if(address.rombank==null && address.rambank==null) { if(address.first==null) {
IRInstruction( IRInstruction(
Opcode.CALL, Opcode.CALL,
address = address.address.toInt(), address = address.second.toInt(),
fcallArgs = FunctionCallArgs(argRegisters, returnRegisters) fcallArgs = FunctionCallArgs(argRegisters, returnRegisters)
) )
} }

View File

@ -534,7 +534,7 @@ class TestVmCodeGen: FunSpec({
val codegen = VmCodeGen() val codegen = VmCodeGen()
val program = PtProgram("test", DummyMemsizer, DummyStringEncoder) val program = PtProgram("test", DummyMemsizer, DummyStringEncoder)
val block = PtBlock("main", false, SourceCode.Generated("test"), PtBlock.Options(), Position.DUMMY) 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) block.add(romsub)
val sub = PtSub("start", emptyList(), null, Position.DUMMY) val sub = PtSub("start", emptyList(), null, Position.DUMMY)
val call = PtFunctionCall("main.routine", true, DataType.UNDEFINED, 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) uword disknumberAndColors @R3, uword headerAndStatusColors @R4) clobbers(A,X,Y)
; Audio (rom bank 10) ; 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 @bank 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 $C0A5 = ym_get_chip_type() clobbers(X) -> ubyte @A
; extapi call numbers ; extapi call numbers
const ubyte EXTAPI_clear_status = $01 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) if(uniqueNames.size!=subroutine.parameters.size)
err("parameter names must be unique") err("parameter names must be unique")
val rambank = subroutine.asmAddress?.rambank val bank = subroutine.asmAddress?.first
val rombank = subroutine.asmAddress?.rombank if(bank!=null && bank>255u)
if(rambank!=null && rambank>255u)
err("bank must be 0 to 255")
if(rombank!=null && rombank>255u)
err("bank must be 0 to 255") err("bank must be 0 to 255")
if(subroutine.inline && subroutine.asmAddress!=null) if(subroutine.inline && subroutine.asmAddress!=null)
throw FatalAstException("romsub cannot be inline") 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 { private fun transformAsmSub(srcSub: Subroutine): PtAsmSub {
val params = srcSub.asmParameterRegisters.zip(srcSub.parameters.map { PtSubroutineParameter(it.name, it.type, it.position) }) 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, val sub = PtAsmSub(srcSub.name,
asmAddr, asmAddr,
srcSub.asmClobbers, srcSub.asmClobbers,

View File

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

View File

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

View File

@ -177,13 +177,11 @@ private fun AsmsubroutineContext.toAst(): Subroutine {
private fun RomsubroutineContext.toAst(): Subroutine { private fun RomsubroutineContext.toAst(): Subroutine {
val subdecl = asmsub_decl().toAst() val subdecl = asmsub_decl().toAst()
val rombank = rombankspec()?.integerliteral()?.toAst()?.number?.toUInt() val bank = bank?.toAst()?.number?.toUInt()?.toUByte()
val rambank = rambankspec()?.integerliteral()?.toAst()?.number?.toUInt() val addr = address.toAst().number.toUInt()
val addr = integerliteral().toAst().number.toUInt()
val address = Subroutine.Address(rombank, rambank, addr)
return Subroutine(subdecl.name, subdecl.parameters.toMutableList(), subdecl.returntypes.toMutableList(), return Subroutine(subdecl.name, subdecl.parameters.toMutableList(), subdecl.returntypes.toMutableList(),
subdecl.asmParameterRegisters, subdecl.asmReturnvaluesRegisters, 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 val targetAsmAddress = (target as? Subroutine)?.asmAddress
if(targetAsmAddress!=null) { if(targetAsmAddress!=null) {
if(targetAsmAddress.rombank==null && targetAsmAddress.rambank==null) return NumericLiteral(DataType.UWORD, targetAsmAddress.second.toDouble(), position)
return NumericLiteral(DataType.UWORD, targetAsmAddress.address.toDouble(), position)
} }
return null return null
} }

View File

@ -806,7 +806,7 @@ class Subroutine(override val name: String,
val asmParameterRegisters: List<RegisterOrStatusflag>, val asmParameterRegisters: List<RegisterOrStatusflag>,
val asmReturnvaluesRegisters: List<RegisterOrStatusflag>, val asmReturnvaluesRegisters: List<RegisterOrStatusflag>,
val asmClobbers: Set<CpuRegister>, val asmClobbers: Set<CpuRegister>,
val asmAddress: Address?, val asmAddress: Pair<UByte?, UInt>?, // bank, address
val isAsmSubroutine: Boolean, val isAsmSubroutine: Boolean,
var inline: Boolean, var inline: Boolean,
var hasBeenInlined: Boolean=false, 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 accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
override fun toString() = override fun toString() =
"Subroutine(name=$name, parameters=$parameters, returntypes=$returntypes, ${statements.size} statements, address=$asmAddress)" "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, 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 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. 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: **Banks:** it is possible to declare a non-standard ROM or RAM bank that the routine is living in, with ``@bank`` like this:
``romsub @rombank 10 $C09F = audio_init()`` to define a routine at $C09F in ROM bank 10. ``romsub @bank 10 $C09F = audio_init()`` to define a routine at $C09F in bank 10.
See :ref:`banking` for more information. See :ref:`banking` for more information.
.. note:: .. 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 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 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 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:: 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 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 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. 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):: 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:: .. caution::
Calls with automatic bank switching like this are not safe to use from IRQ handlers. Don't use them there. 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 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 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) add support for banked romsubs on the C64 as well (banks basic/kernal rom in/out)
rename 'romsub' to 'extsub' ? keep romsub as alias? 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 regenerate symbol dump files
Improve register load order in subroutine call args assignments: Improve register load order in subroutine call args assignments:

View File

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

View File

@ -294,12 +294,9 @@ asmsubroutine :
; ;
romsubroutine : 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_decl : identifier '(' asmsub_params? ')' asmsub_clobbers? asmsub_returns? ;
asmsub_params : asmsub_param (',' EOL? asmsub_param)* ; asmsub_params : asmsub_param (',' EOL? asmsub_param)* ;

View File

@ -12,7 +12,7 @@
<option name="HAS_STRING_ESCAPES" value="true" /> <option name="HAS_STRING_ESCAPES" value="true" />
</options> </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" /> <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" /> <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" /> <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> </highlighting>

View File

@ -43,7 +43,7 @@ syn region prog8ArrayType matchgroup=prog8Type
\ start="\<\%(u\?byte\|u\?word\|float\|str\|bool\)\[" end="\]" \ start="\<\%(u\?byte\|u\?word\|float\|str\|bool\)\[" end="\]"
\ transparent \ transparent
syn keyword prog8StorageClass const 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 prog8Block start="{" end="}" transparent
syn region prog8Expression start="(" end=")" transparent syn region prog8Expression start="(" end=")" transparent