mirror of
https://github.com/irmen/prog8.git
synced 2024-12-22 03:29:41 +00:00
consolidate @rombank and @rambank into just @bank
This commit is contained in:
parent
cb47e2c149
commit
85e87dfe2e
@ -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) :
|
||||
|
@ -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 -> {
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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,
|
||||
|
@ -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} (")
|
||||
|
@ -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")
|
||||
|
@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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::
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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)* ;
|
||||
|
@ -12,7 +12,7 @@
|
||||
<option name="HAS_STRING_ESCAPES" value="true" />
|
||||
</options>
|
||||
<keywords keywords="&;->;@;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>
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user