ir: JUMPI instruction added to support indirect jumps

This commit is contained in:
Irmen de Jong 2023-07-07 18:25:05 +02:00
parent 90c4b00f74
commit 334d382bfa
6 changed files with 31 additions and 22 deletions

View File

@ -1,9 +1,6 @@
package prog8.codegen.intermediate
import prog8.code.StMemVar
import prog8.code.StNode
import prog8.code.StStaticVariable
import prog8.code.SymbolTable
import prog8.code.*
import prog8.code.ast.*
import prog8.code.core.*
import prog8.intermediate.*
@ -1520,17 +1517,26 @@ class IRCodeGen(
private fun translate(jump: PtJump): IRCodeChunks {
val result = mutableListOf<IRCodeChunkBase>()
val instr = if(jump.address!=null) {
IRInstruction(Opcode.JUMPA, address = jump.address!!.toInt())
val chunk = IRCodeChunk(null, null)
if(jump.address!=null) {
chunk += IRInstruction(Opcode.JUMP, address = jump.address!!.toInt())
} else {
if (jump.generatedLabel != null)
IRInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!)
else if (jump.identifier != null)
IRInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.name)
chunk += IRInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!)
else if (jump.identifier != null) {
val symbol = symbolTable.lookup(jump.identifier!!.name)
if(symbol?.type==StNodeType.MEMVAR || symbol?.type==StNodeType.STATICVAR) {
val jumpReg = registers.nextFree()
chunk += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1 = jumpReg, labelSymbol = jump.identifier!!.name)
chunk += IRInstruction(Opcode.JUMPI, reg1 = jumpReg)
} else {
chunk += IRInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.name)
}
}
else
throw AssemblyError("weird jump")
}
addInstr(result, instr, null)
result += chunk
return result
}

View File

@ -17,10 +17,10 @@ main {
txt.print_ub('a' in name)
txt.print_ub('e' in name)
txt.nl()
txt.print_ub(all(othercells)) ;; TODO fix vm ALL() !
txt.print_ub(all(othercells))
txt.print_ub(any(othercells))
othercells[3] = 0
txt.print_ub(all(othercells)) ;; TODO fix vm ALL() !
txt.print_ub(all(othercells))
txt.print_ub(any(othercells))
reverse(othercells)
sort(othercells)

View File

@ -51,8 +51,8 @@ storezx reg1, address - store zero at memory address, indexed by
CONTROL FLOW
------------
jump location - continue running at instruction number given by location
jumpa address - continue running at memory address (note: only used to encode a physical cpu jump to fixed address instruction)
jump location - continue running at instruction at 'location' (label/memory address)
jumpi reg1 - continue running at memory address in reg1 (indirect jump)
call label(argument register list) [: resultreg.type]
- calls a subroutine with the given arguments and return value (optional).
save current instruction location+1, continue execution at instruction nr of the label.
@ -240,7 +240,7 @@ enum class Opcode {
STOREZX,
JUMP,
JUMPA,
JUMPI,
CALL,
SYSCALL,
RETURN,
@ -378,14 +378,14 @@ enum class Opcode {
val OpcodesThatJump = setOf(
Opcode.JUMP,
Opcode.JUMPA,
Opcode.JUMPI,
Opcode.RETURN,
Opcode.RETURNR
)
val OpcodesThatBranch = setOf(
Opcode.JUMP,
Opcode.JUMPA,
Opcode.JUMPI,
Opcode.RETURN,
Opcode.RETURNR,
Opcode.CALL,
@ -514,7 +514,7 @@ val instructionFormats = mutableMapOf(
Opcode.STOREZI to InstructionFormat.from("BW,<r1 | F,<r1"),
Opcode.STOREZX to InstructionFormat.from("BW,<r1,>a | F,<r1,>a"),
Opcode.JUMP to InstructionFormat.from("N,<a"),
Opcode.JUMPA to InstructionFormat.from("N,<a"),
Opcode.JUMPI to InstructionFormat.from("N,<r1"),
Opcode.CALL to InstructionFormat.from("N,call"),
Opcode.SYSCALL to InstructionFormat.from("N,syscall"),
Opcode.RETURN to InstructionFormat.from("N"),

View File

@ -95,6 +95,7 @@ class IRProgram(val name: String,
}
}
}
result.remove(null)
return result
}
@ -407,6 +408,7 @@ class IRAsmSubroutine(
init {
require('.' in label) { "subroutine name is not scoped: $label" }
require(!label.startsWith("main.main.")) { "subroutine name invalid main prefix: $label" }
require(label==asmChunk.label)
}
private val registersUsed by lazy { registersUsedInAssembly(asmChunk.isIR, asmChunk.assembly) }

View File

@ -147,6 +147,10 @@ class VirtualMachine(irProgram: IRProgram) {
null -> {
if(i.address!=null)
throw IllegalArgumentException("vm program can't jump to system memory address (${i.opcode} ${i.address!!.toHex()})")
else if(i.labelSymbol!=null)
throw IllegalArgumentException("vm program can't jump to system memory address (${i.opcode} ${i.labelSymbol})")
else if(i.reg1!=null)
throw IllegalArgumentException("vm program can't jump to system memory address (${i})")
else
throw IllegalArgumentException("no branchtarget in $i")
}
@ -174,8 +178,7 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.STOREZM -> InsSTOREZM(ins)
Opcode.STOREZX -> InsSTOREZX(ins)
Opcode.STOREZI -> InsSTOREZI(ins)
Opcode.JUMP -> InsJUMP(ins)
Opcode.JUMPA -> throw IllegalArgumentException("vm program can't jump to system memory address (JUMPA)")
Opcode.JUMP, Opcode.JUMPI -> InsJUMP(ins)
Opcode.CALL -> InsCALL(ins)
Opcode.SYSCALL -> InsSYSCALL(ins)
Opcode.RETURN -> InsRETURN()

View File

@ -191,8 +191,6 @@ class VmProgramLoader {
}
}
private val functionCallOpcodes = setOf(Opcode.CALL, Opcode.SYSCALL, Opcode.JUMP, Opcode.JUMPA)
private fun varsToMemory(
program: IRProgram,
allocations: VmVariableAllocator,