vm: more optimal code when array index is constant value

This commit is contained in:
Irmen de Jong 2022-04-05 00:19:37 +02:00
parent 2b7c09e6ee
commit d78bfcc35c
3 changed files with 21 additions and 20 deletions

View File

@ -138,15 +138,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val vmDt = codeGen.vmType(arrayIx.type)
val code = VmCodeChunk()
val idxReg = codeGen.vmRegisters.nextFree()
// TODO: optimized code when the index is a constant value
code += translateExpression(arrayIx.index, idxReg)
if(eltSize>1) {
val factorReg = codeGen.vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=factorReg, value=eltSize)
code += VmCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=idxReg, reg2=idxReg, reg3=factorReg)
}
val arrayLocation = codeGen.allocations.get(arrayIx.variable.targetName)
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
if(arrayIx.index is PtNumber) {
// optimized code when index is known - just calculate the memory address here
val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize
code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset)
} else {
code += translateExpression(arrayIx.index, idxReg)
if(eltSize>1) {
val factorReg = codeGen.vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=factorReg, value=eltSize)
code += VmCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=idxReg, reg2=idxReg, reg3=factorReg)
}
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
}
return code
}

View File

@ -7,13 +7,9 @@
main {
sub start() {
ubyte counter
uword[] array = [1111,2222,3333,4444,5555]
repeat 256 {
txt.print_ub(counter)
txt.spc()
counter ++
}
txt.print_uw(array[3])
txt.nl()
; a "pixelshader":

View File

@ -588,7 +588,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
if(right==0.toUByte()) 0xffu
else left % right
}
else -> TODO("operator byte $operator")
else -> throw IllegalArgumentException("operator byte $operator")
}
registers.setUB(reg1, result.toUByte())
}
@ -608,7 +608,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
if(right==0.toUShort()) 0xffffu
else left % right
}
else -> TODO("operator word $operator")
else -> throw IllegalArgumentException("operator word $operator")
}
registers.setUW(reg1, result.toUShort())
}
@ -624,7 +624,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
private fun InsEXT(i: Instruction) {
when(i.type!!){
VmDataType.BYTE -> registers.setUW(i.reg1!!, registers.getUB(i.reg1).toUShort())
VmDataType.WORD -> TODO("ext.w requires 32 bits registers")
VmDataType.WORD -> TODO("ext.w not yet supported, requires 32 bits registers")
}
pc++
}
@ -632,7 +632,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
private fun InsEXTS(i: Instruction) {
when(i.type!!){
VmDataType.BYTE -> registers.setSW(i.reg1!!, registers.getSB(i.reg1).toShort())
VmDataType.WORD -> TODO("ext.w requires 32 bits registers")
VmDataType.WORD -> TODO("exts.w not yet supported, requires 32 bits registers")
}
pc++
}
@ -716,7 +716,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
val newValue = value.toUByte()*256u + (value.toInt() ushr 8).toUInt()
registers.setUW(i.reg1, newValue.toUShort())
}
VmDataType.WORD -> TODO("swap.w requires 32-bits registers")
VmDataType.WORD -> TODO("swap.w not yet supported, requires 32-bits registers")
}
pc++
}
@ -728,7 +728,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
val lsb = registers.getUB(i.reg3!!)
registers.setUW(i.reg1!!, ((msb.toInt() shl 8) or lsb.toInt()).toUShort())
}
VmDataType.WORD -> TODO("swap.w requires 32-bits registers")
VmDataType.WORD -> TODO("concat.w not yet supported, requires 32-bits registers")
}
pc++
}