mirror of
https://github.com/irmen/prog8.git
synced 2024-08-12 13:28:57 +00:00
ir: JUMPI instruction added to support indirect jumps
This commit is contained in:
parent
90c4b00f74
commit
334d382bfa
@ -1,9 +1,6 @@
|
|||||||
package prog8.codegen.intermediate
|
package prog8.codegen.intermediate
|
||||||
|
|
||||||
import prog8.code.StMemVar
|
import prog8.code.*
|
||||||
import prog8.code.StNode
|
|
||||||
import prog8.code.StStaticVariable
|
|
||||||
import prog8.code.SymbolTable
|
|
||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.intermediate.*
|
import prog8.intermediate.*
|
||||||
@ -1520,17 +1517,26 @@ class IRCodeGen(
|
|||||||
|
|
||||||
private fun translate(jump: PtJump): IRCodeChunks {
|
private fun translate(jump: PtJump): IRCodeChunks {
|
||||||
val result = mutableListOf<IRCodeChunkBase>()
|
val result = mutableListOf<IRCodeChunkBase>()
|
||||||
val instr = if(jump.address!=null) {
|
val chunk = IRCodeChunk(null, null)
|
||||||
IRInstruction(Opcode.JUMPA, address = jump.address!!.toInt())
|
if(jump.address!=null) {
|
||||||
|
chunk += IRInstruction(Opcode.JUMP, address = jump.address!!.toInt())
|
||||||
} else {
|
} else {
|
||||||
if (jump.generatedLabel != null)
|
if (jump.generatedLabel != null)
|
||||||
IRInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!)
|
chunk += IRInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!)
|
||||||
else if (jump.identifier != null)
|
else if (jump.identifier != null) {
|
||||||
IRInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.name)
|
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
|
else
|
||||||
throw AssemblyError("weird jump")
|
throw AssemblyError("weird jump")
|
||||||
}
|
}
|
||||||
addInstr(result, instr, null)
|
result += chunk
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,10 +17,10 @@ main {
|
|||||||
txt.print_ub('a' in name)
|
txt.print_ub('a' in name)
|
||||||
txt.print_ub('e' in name)
|
txt.print_ub('e' in name)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
txt.print_ub(all(othercells)) ;; TODO fix vm ALL() !
|
txt.print_ub(all(othercells))
|
||||||
txt.print_ub(any(othercells))
|
txt.print_ub(any(othercells))
|
||||||
othercells[3] = 0
|
othercells[3] = 0
|
||||||
txt.print_ub(all(othercells)) ;; TODO fix vm ALL() !
|
txt.print_ub(all(othercells))
|
||||||
txt.print_ub(any(othercells))
|
txt.print_ub(any(othercells))
|
||||||
reverse(othercells)
|
reverse(othercells)
|
||||||
sort(othercells)
|
sort(othercells)
|
||||||
|
@ -51,8 +51,8 @@ storezx reg1, address - store zero at memory address, indexed by
|
|||||||
|
|
||||||
CONTROL FLOW
|
CONTROL FLOW
|
||||||
------------
|
------------
|
||||||
jump location - continue running at instruction number given by location
|
jump location - continue running at instruction at 'location' (label/memory address)
|
||||||
jumpa address - continue running at memory address (note: only used to encode a physical cpu jump to fixed address instruction)
|
jumpi reg1 - continue running at memory address in reg1 (indirect jump)
|
||||||
call label(argument register list) [: resultreg.type]
|
call label(argument register list) [: resultreg.type]
|
||||||
- calls a subroutine with the given arguments and return value (optional).
|
- calls a subroutine with the given arguments and return value (optional).
|
||||||
save current instruction location+1, continue execution at instruction nr of the label.
|
save current instruction location+1, continue execution at instruction nr of the label.
|
||||||
@ -240,7 +240,7 @@ enum class Opcode {
|
|||||||
STOREZX,
|
STOREZX,
|
||||||
|
|
||||||
JUMP,
|
JUMP,
|
||||||
JUMPA,
|
JUMPI,
|
||||||
CALL,
|
CALL,
|
||||||
SYSCALL,
|
SYSCALL,
|
||||||
RETURN,
|
RETURN,
|
||||||
@ -378,14 +378,14 @@ enum class Opcode {
|
|||||||
|
|
||||||
val OpcodesThatJump = setOf(
|
val OpcodesThatJump = setOf(
|
||||||
Opcode.JUMP,
|
Opcode.JUMP,
|
||||||
Opcode.JUMPA,
|
Opcode.JUMPI,
|
||||||
Opcode.RETURN,
|
Opcode.RETURN,
|
||||||
Opcode.RETURNR
|
Opcode.RETURNR
|
||||||
)
|
)
|
||||||
|
|
||||||
val OpcodesThatBranch = setOf(
|
val OpcodesThatBranch = setOf(
|
||||||
Opcode.JUMP,
|
Opcode.JUMP,
|
||||||
Opcode.JUMPA,
|
Opcode.JUMPI,
|
||||||
Opcode.RETURN,
|
Opcode.RETURN,
|
||||||
Opcode.RETURNR,
|
Opcode.RETURNR,
|
||||||
Opcode.CALL,
|
Opcode.CALL,
|
||||||
@ -514,7 +514,7 @@ val instructionFormats = mutableMapOf(
|
|||||||
Opcode.STOREZI to InstructionFormat.from("BW,<r1 | F,<r1"),
|
Opcode.STOREZI to InstructionFormat.from("BW,<r1 | F,<r1"),
|
||||||
Opcode.STOREZX to InstructionFormat.from("BW,<r1,>a | F,<r1,>a"),
|
Opcode.STOREZX to InstructionFormat.from("BW,<r1,>a | F,<r1,>a"),
|
||||||
Opcode.JUMP to InstructionFormat.from("N,<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.CALL to InstructionFormat.from("N,call"),
|
||||||
Opcode.SYSCALL to InstructionFormat.from("N,syscall"),
|
Opcode.SYSCALL to InstructionFormat.from("N,syscall"),
|
||||||
Opcode.RETURN to InstructionFormat.from("N"),
|
Opcode.RETURN to InstructionFormat.from("N"),
|
||||||
|
@ -95,6 +95,7 @@ class IRProgram(val name: String,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
result.remove(null)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,6 +408,7 @@ class IRAsmSubroutine(
|
|||||||
init {
|
init {
|
||||||
require('.' in label) { "subroutine name is not scoped: $label" }
|
require('.' in label) { "subroutine name is not scoped: $label" }
|
||||||
require(!label.startsWith("main.main.")) { "subroutine name invalid main prefix: $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) }
|
private val registersUsed by lazy { registersUsedInAssembly(asmChunk.isIR, asmChunk.assembly) }
|
||||||
|
@ -147,6 +147,10 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
null -> {
|
null -> {
|
||||||
if(i.address!=null)
|
if(i.address!=null)
|
||||||
throw IllegalArgumentException("vm program can't jump to system memory address (${i.opcode} ${i.address!!.toHex()})")
|
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
|
else
|
||||||
throw IllegalArgumentException("no branchtarget in $i")
|
throw IllegalArgumentException("no branchtarget in $i")
|
||||||
}
|
}
|
||||||
@ -174,8 +178,7 @@ class VirtualMachine(irProgram: IRProgram) {
|
|||||||
Opcode.STOREZM -> InsSTOREZM(ins)
|
Opcode.STOREZM -> InsSTOREZM(ins)
|
||||||
Opcode.STOREZX -> InsSTOREZX(ins)
|
Opcode.STOREZX -> InsSTOREZX(ins)
|
||||||
Opcode.STOREZI -> InsSTOREZI(ins)
|
Opcode.STOREZI -> InsSTOREZI(ins)
|
||||||
Opcode.JUMP -> InsJUMP(ins)
|
Opcode.JUMP, Opcode.JUMPI -> InsJUMP(ins)
|
||||||
Opcode.JUMPA -> throw IllegalArgumentException("vm program can't jump to system memory address (JUMPA)")
|
|
||||||
Opcode.CALL -> InsCALL(ins)
|
Opcode.CALL -> InsCALL(ins)
|
||||||
Opcode.SYSCALL -> InsSYSCALL(ins)
|
Opcode.SYSCALL -> InsSYSCALL(ins)
|
||||||
Opcode.RETURN -> InsRETURN()
|
Opcode.RETURN -> InsRETURN()
|
||||||
|
@ -191,8 +191,6 @@ class VmProgramLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val functionCallOpcodes = setOf(Opcode.CALL, Opcode.SYSCALL, Opcode.JUMP, Opcode.JUMPA)
|
|
||||||
|
|
||||||
private fun varsToMemory(
|
private fun varsToMemory(
|
||||||
program: IRProgram,
|
program: IRProgram,
|
||||||
allocations: VmVariableAllocator,
|
allocations: VmVariableAllocator,
|
||||||
|
Loading…
Reference in New Issue
Block a user