vm: loadix instruction added for indirect addressing via pointer

This commit is contained in:
Irmen de Jong 2022-06-04 17:49:25 +02:00
parent 2002412026
commit 3c8c44155d
6 changed files with 53 additions and 33 deletions

View File

@ -78,6 +78,8 @@ internal class AssignmentAsmGen(private val program: Program,
// indexing a pointer var instead of a real array or string
if(elementDt !in ByteDatatypes)
throw AssemblyError("non-array var indexing requires bytes dt")
if(value.inferType(program) isnot DataType.UBYTE)
throw AssemblyError("non-array var indexing requires bytes index")
asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y)
if(asmgen.isZpVar(value.arrayvar)) {
asmgen.out(" lda ($arrayVarName),y")

View File

@ -82,34 +82,34 @@ internal class VmCodeInstruction(
value: Int?=null, // 0-$ffff
fpValue: Float?=null,
labelSymbol: List<String>?=null // alternative to value for branch/call/jump labels
): VmCodeLine() {
val ins = Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value, fpValue, labelSymbol)
): VmCodeLine() {
val ins = Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value, fpValue, labelSymbol)
init {
if(reg1!=null && (reg1<0 || reg1>65536))
throw IllegalArgumentException("reg1 out of bounds")
if(reg2!=null && (reg2<0 || reg2>65536))
throw IllegalArgumentException("reg2 out of bounds")
if(fpReg1!=null && (fpReg1<0 || fpReg1>65536))
throw IllegalArgumentException("fpReg1 out of bounds")
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))
throw IllegalArgumentException("fpReg2 out of bounds")
init {
if(reg1!=null && (reg1<0 || reg1>65536))
throw IllegalArgumentException("reg1 out of bounds")
if(reg2!=null && (reg2<0 || reg2>65536))
throw IllegalArgumentException("reg2 out of bounds")
if(fpReg1!=null && (fpReg1<0 || fpReg1>65536))
throw IllegalArgumentException("fpReg1 out of bounds")
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))
throw IllegalArgumentException("fpReg2 out of bounds")
if(value!=null && opcode !in OpcodesWithAddress) {
when (type) {
VmDataType.BYTE -> {
if (value < -128 || value > 255)
throw IllegalArgumentException("value out of range for byte: $value")
}
VmDataType.WORD -> {
if (value < -32768 || value > 65535)
throw IllegalArgumentException("value out of range for word: $value")
}
VmDataType.FLOAT, null -> {}
if(value!=null && opcode !in OpcodesWithAddress) {
when (type) {
VmDataType.BYTE -> {
if (value < -128 || value > 255)
throw IllegalArgumentException("value out of range for byte: $value")
}
VmDataType.WORD -> {
if (value < -32768 || value > 65535)
throw IllegalArgumentException("value out of range for word: $value")
}
VmDataType.FLOAT, null -> {}
}
}
}
}
internal class VmCodeLabel(val name: List<String>): VmCodeLine()
internal class VmCodeComment(val comment: String): VmCodeLine()

View File

@ -154,12 +154,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
// indexing a pointer var instead of a real array or string
if(eltSize!=1)
throw AssemblyError("non-array var indexing requires bytes dt")
val pointerReg = codeGen.vmRegisters.nextFree()
code += translateExpression(arrayIx.index, idxReg, -1)
// TODO introduce LOADIX instruction to skip the ADD (requires 3 registers)
code += VmCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1=pointerReg, value=arrayLocation)
code += VmCodeInstruction(Opcode.ADD, VmDataType.WORD, reg1=pointerReg, reg2=idxReg)
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1=resultRegister, reg2=pointerReg)
code += VmCodeInstruction(Opcode.LOADIX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
return code
}

View File

@ -3,9 +3,8 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- optimize pointervar indexing codegen: reading (expressions) via optimized codegen instead of @(pointer+idx)
- optimize pointervar indexing codegen: writing (all sorts of things)
- why is this code so much larger:
- fix pointervar indexing 6502 codegen (AssignmentAsmGen translateNormalAssignment) -> gridcommander worm doesn't move
- is this code still so much larger:
uword xx
for xx in 0 to size-1 {
gfx2.next_pixel(bitmapbuf[xx])
@ -16,8 +15,8 @@ For next release
gfx2.next_pixel(@(srcptr))
srcptr++
}
any difference between 6502 codegen and vm codegen?
- optimize pointervar indexing codegen: writing (all sorts of things)
- pipe operator: (targets other than 'Virtual'): allow non-unary function calls in the pipe that specify the other argument(s) in the calls. Already working for VM target.
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?
- Inliner: also inline function call expressions, and remove it from the StatementOptimizer

View File

@ -24,8 +24,9 @@ All have type b or w or f.
load reg1, value - load immediate value into register
loadm reg1, address - load reg1 with value at memory address
loadi reg1, reg2 - load reg1 with value at memory indirect, memory pointed to by reg2
loadx reg1, reg2, address - load reg1 with value at memory address, indexed by value in reg2
loadr reg1, reg2 - load reg1 with value at register reg2
loadx reg1, reg2, address - load reg1 with value at memory address indexed by value in reg2
loadix reg1, reg2, pointeraddr - load reg1 with value at memory indirect, pointed to by pointeraddr indexed by value in reg2
loadr reg1, reg2 - load reg1 with value in register reg2
storem reg1, address - store reg1 at memory address
storei reg1, reg2 - store reg1 at memory indirect, memory pointed to by reg2
@ -184,6 +185,7 @@ enum class Opcode {
LOADM,
LOADI,
LOADX,
LOADIX,
LOADR,
STOREM,
STOREI,
@ -313,6 +315,7 @@ enum class Opcode {
val OpcodesWithAddress = setOf(
Opcode.LOADM,
Opcode.LOADX,
Opcode.LOADIX,
Opcode.STOREM,
Opcode.STOREX,
Opcode.STOREZM,
@ -481,6 +484,7 @@ val instructionFormats = mutableMapOf(
Opcode.LOADM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.LOADI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),
Opcode.LOADX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
Opcode.LOADIX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
Opcode.LOADR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.STOREM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.STOREI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),

View File

@ -91,6 +91,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
Opcode.LOADM -> InsLOADM(ins)
Opcode.LOADX -> InsLOADX(ins)
Opcode.LOADI -> InsLOADI(ins)
Opcode.LOADIX -> InsLOADIX(ins)
Opcode.LOADR -> InsLOADR(ins)
Opcode.STOREM -> InsSTOREM(ins)
Opcode.STOREX -> InsSTOREX(ins)
@ -308,6 +309,24 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsLOADIX(i: Instruction) {
when (i.type!!) {
VmDataType.BYTE -> {
val pointer = memory.getUW(i.value!!) + registers.getUB(i.reg2!!)
registers.setUB(i.reg1!!, memory.getUB(pointer.toInt()))
}
VmDataType.WORD -> {
val pointer = memory.getUW(i.value!!) + registers.getUB(i.reg2!!)
registers.setUW(i.reg1!!, memory.getUW(pointer.toInt()))
}
VmDataType.FLOAT -> {
val pointer = memory.getUW(i.value!!) + registers.getUB(i.reg1!!)
registers.setFloat(i.fpReg1!!, memory.getFloat(pointer.toInt()))
}
}
pc++
}
private fun InsLOADR(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg2!!))