vm: codegen uses INCM/DECM if possible

This commit is contained in:
Irmen de Jong 2022-05-11 23:00:15 +02:00
parent 517cf61d11
commit a7df828932
5 changed files with 43 additions and 29 deletions

View File

@ -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")

View File

@ -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) {

View File

@ -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

View File

@ -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()

View File

@ -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??? >