fix IR loader for romsub calls (calls to an address)

This commit is contained in:
Irmen de Jong 2023-07-02 23:41:15 +02:00
parent f570b70827
commit f9200a2b75
5 changed files with 28 additions and 19 deletions

View File

@ -1,13 +1,6 @@
TODO
====
- fix IR loading of romsubs
romsub $FFD2 = chrout(ubyte ch @ A)
sub start() {
ubyte ch = '\n'
chrout(ch)
}
...

View File

@ -2,10 +2,9 @@
%zeropage basicsafe
main {
romsub $FFD2 = chrout(ubyte ch @ A)
sub start() {
ubyte ch = '\n'
ubyte ch = '2'
chrout(ch)
}
}

View File

@ -138,9 +138,14 @@ class IRProgram(val name: String,
// link all jump and branching instructions to their target
chunk.instructions.forEach {
if(it.opcode in OpcodesThatBranch && it.opcode!=Opcode.RETURN && it.opcode!=Opcode.RETURNR && it.labelSymbol!=null)
if(it.opcode in OpcodesThatBranch && it.opcode!=Opcode.RETURN && it.opcode!=Opcode.RETURNR && it.labelSymbol!=null) {
if(it.labelSymbol.startsWith('$') || it.labelSymbol.first().isDigit()) {
// it's a call to an address (romsub most likely)
require(it.address!=null)
} else {
it.branchTarget = labeledChunks.getValue(it.labelSymbol)
// note: branches with an address value cannot be linked to something...
}
}
}
}
is IRInlineAsmChunk -> {
@ -199,7 +204,8 @@ class IRProgram(val name: String,
require(!chunk.isIR) { "inline IR-asm should have been converted into regular code chunk"}
}
chunk.instructions.forEach {
if(it.labelSymbol!=null && it.opcode in OpcodesThatBranch)
if(it.labelSymbol!=null && it.opcode in OpcodesThatBranch) {
if(!it.labelSymbol.startsWith('$') && !it.labelSymbol.first().isDigit())
require(it.branchTarget != null) { "branching instruction to label should have branchTarget set" }
}
}
@ -207,6 +213,7 @@ class IRProgram(val name: String,
}
}
}
}
fun registersUsed(): RegistersUsed {
val readRegsCounts = mutableMapOf<Int, Int>().withDefault { 0 }

View File

@ -131,11 +131,11 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
}
if(format.sysCall) {
val call = parseCall(rest)
val syscallNum = parseIRValue(call.target).toInt()
val syscallNum = call.address ?: parseIRValue(call.target ?: "").toInt()
return left(IRInstruction(Opcode.SYSCALL, immediate = syscallNum, fcallArgs = FunctionCallArgs(call.args, call.returns)))
} else if (format.funcCall) {
val call = parseCall(rest)
return left(IRInstruction(Opcode.CALL, labelSymbol = call.target, fcallArgs = FunctionCallArgs(call.args, call.returns)))
return left(IRInstruction(Opcode.CALL, address = call.address, labelSymbol = call.target, fcallArgs = FunctionCallArgs(call.args, call.returns)))
} else {
operands.forEach { oper ->
if (oper[0] == '&')
@ -222,7 +222,8 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
}
private class ParsedCall(
val target: String,
val target: String?,
val address: Int?,
val args: List<FunctionCallArgs.ArgumentSpec>,
val returns: FunctionCallArgs.RegSpec?
)
@ -266,8 +267,17 @@ private fun parseCall(rest: String): ParsedCall {
val args = match.groups["arglist"]!!.value
val arguments = parseArgs(args)
val returns = match.groups["returns"]?.value
var address: Int? = null
var actualTarget: String? = target
if(target.startsWith('$') || target[0].isDigit()) {
address = parseIRValue(target).toInt()
actualTarget = null
}
return ParsedCall(
target,
actualTarget,
address,
arguments,
if(returns==null) null else parseRegspec(returns)
)

View File

@ -179,7 +179,7 @@ class VmProgramLoader {
if(arg.address!=null)
arg
else {
val address = variableAddresses.getValue(ins.labelSymbol + "." + arg.name)
val address = ins.address ?: variableAddresses.getValue(ins.labelSymbol + "." + arg.name)
FunctionCallArgs.ArgumentSpec(arg.name, address, arg.reg)
}
}