From a7df8289328bef51efe678dc1a3170d72f5ffa19 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 11 May 2022 23:00:15 +0200 Subject: [PATCH] vm: codegen uses INCM/DECM if possible --- .../src/prog8/codegen/virtual/CodeGen.kt | 44 +++++++++---------- .../prog8/codegen/virtual/ExpressionGen.kt | 1 - docs/source/todo.rst | 3 +- examples/test.p8 | 20 +++++++-- virtualmachine/src/prog8/vm/Instructions.kt | 4 +- 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index b1253101d..50b0de6bb 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -507,53 +507,53 @@ class CodeGen(internal val program: PtProgram, private fun translate(postIncrDecr: PtPostIncrDecr): VmCodeChunk { val code = VmCodeChunk() - val operation = when(postIncrDecr.operator) { - "++" -> Opcode.INC - "--" -> Opcode.DEC + val operationMem: Opcode + val operationRegister: Opcode + when(postIncrDecr.operator) { + "++" -> { + operationMem = Opcode.INCM + operationRegister = Opcode.INC + } + "--" -> { + operationMem = Opcode.DECM + operationRegister = Opcode.DEC + } else -> throw AssemblyError("weird operator") } val ident = postIncrDecr.target.identifier val memory = postIncrDecr.target.memory val array = postIncrDecr.target.array val vmDt = vmType(postIncrDecr.target.type) - val resultReg = vmRegisters.nextFree() if(ident!=null) { val address = allocations.get(ident.targetName) - code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultReg, value = address) - code += VmCodeInstruction(operation, vmDt, reg1=resultReg) - code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultReg, value = address) + code += VmCodeInstruction(operationMem, vmDt, value = address) } else if(memory!=null) { if(memory.address is PtNumber) { val address = (memory.address as PtNumber).number.toInt() - code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultReg, value = address) - code += VmCodeInstruction(operation, vmDt, reg1 = resultReg) - code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, value=address) + code += VmCodeInstruction(operationMem, vmDt, value = address) } else { + val incReg = vmRegisters.nextFree() val addressReg = vmRegisters.nextFree() code += expressionEval.translateExpression(memory.address, addressReg, -1) - code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1 = resultReg, reg2 = addressReg) - code += VmCodeInstruction(operation, vmDt, reg1 = resultReg) - code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1 = resultReg, reg2 = addressReg) + code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1 = incReg, reg2 = addressReg) + code += VmCodeInstruction(operationRegister, vmDt, reg1 = incReg) + code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1 = incReg, reg2 = addressReg) } } else if (array!=null) { val variable = array.variable.targetName var variableAddr = allocations.get(variable) val itemsize = program.memsizer.memorySize(array.type) val fixedIndex = constIntValue(array.index) - val memOp = when(postIncrDecr.operator) { - "++" -> Opcode.INCM - "--" -> Opcode.DECM - else -> throw AssemblyError("weird operator") - } if(fixedIndex!=null) { variableAddr += fixedIndex*itemsize - code += VmCodeInstruction(memOp, vmDt, value=variableAddr) + code += VmCodeInstruction(operationMem, vmDt, value=variableAddr) } else { + val incReg = vmRegisters.nextFree() val indexReg = vmRegisters.nextFree() code += expressionEval.translateExpression(array.index, indexReg, -1) - code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultReg, reg2=indexReg, value=variableAddr) - code += VmCodeInstruction(operation, vmDt, reg1=resultReg) - code += VmCodeInstruction(Opcode.STOREX, vmDt, reg1=resultReg, reg2=indexReg, value=variableAddr) + code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=incReg, reg2=indexReg, value=variableAddr) + code += VmCodeInstruction(operationRegister, vmDt, reg1=incReg) + code += VmCodeInstruction(Opcode.STOREX, vmDt, reg1=incReg, reg2=indexReg, value=variableAddr) } } else throw AssemblyError("weird assigntarget") diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index 7c7049cbb..49b6cfe8a 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -173,7 +173,6 @@ internal class ExpressionGen(private val codeGen: CodeGen) { private fun translate(expr: PtPrefix, resultRegister: Int): VmCodeChunk { val code = VmCodeChunk() - // TODO if the value is a variable or memory read, use memory-versions of the opcodes instead of using intermediary register code += translateExpression(expr.value, resultRegister, -1) val vmDt = codeGen.vmType(expr.type) when(expr.operator) { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 6f4f0cd35..ab97746e3 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,8 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: use more instructions in codegen: branching +- vm: use more instructions in codegen: branching, don't use the conditional set instructions here +- vm: get rid of all the conditional set instructions - vm: add more instructions operating directly on memory instead of only registers? - in-place modifiying functions (rol, ror, ..) don't accept a memory address but require a memory-read expression. that is weird. - complete the Inliner diff --git a/examples/test.p8 b/examples/test.p8 index d212e2a59..46b0849c4 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -25,10 +25,24 @@ main { ubyte @shared value = inline_candidate() - ubyte lowb = $31 + ubyte lowb = 4 ubyte highb = $ea - uword result = mkword(highb, lowb) - txt.print_uwhex(result, true) + + if lowb==3 + lowb++ + + if lowb!=3 + lowb++ + + if lowb==3 + lowb++ + else + lowb-- + + if lowb!=3 + lowb++ + else + lowb-- ; txt.print_ub(inline_candidate()) ; txt.nl() diff --git a/virtualmachine/src/prog8/vm/Instructions.kt b/virtualmachine/src/prog8/vm/Instructions.kt index 0c8d1e6f5..f0c2654cc 100644 --- a/virtualmachine/src/prog8/vm/Instructions.kt +++ b/virtualmachine/src/prog8/vm/Instructions.kt @@ -184,8 +184,8 @@ enum class Opcode { BSTPOS, BZ, BNZ, - BEQ, - BNE, + BEQ, // TODO not used in codegen??? == nonzero + BNE, // TODO not used in codegen??? != nonzero BLT, // TODO not used in codegen??? < BLTS, // TODO not used in codegen??? < BGT, // TODO not used in codegen??? >