tweak vm codegen

This commit is contained in:
Irmen de Jong 2022-08-07 13:45:03 +02:00
parent 93ce74eeb1
commit 1e441c2ddf
6 changed files with 23 additions and 55 deletions

View File

@ -1,9 +1,7 @@
package prog8.codegen.virtual
import prog8.code.ast.*
import prog8.code.core.AssemblyError
import prog8.code.core.DataType
import prog8.code.core.SignedDatatypes
import prog8.code.core.*
import prog8.vm.Opcode
import prog8.vm.VmDataType
@ -33,7 +31,9 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
else
fallbackAssign(assignment)
} else if(array!=null) {
// TODO in-place array element assignment?
// NOTE: naive fallback assignment here will sometimes generate code that loads the index value multiple times
// in a register. It's way too much work to optimize that here - instead, we trust that the generated IL assembly
// will be optimized later and have the double assignments removed.
fallbackAssign(assignment)
} else {
fallbackAssign(assignment)

View File

@ -275,15 +275,8 @@ class CodeGen(internal val program: PtProgram,
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress)
code += VmCodeLabel(loopLabel)
code += translateNode(forLoop.statements)
if(step<3) {
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step)
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
} else {
// TODO WHY THIS DISTINCTION?
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
code += addConstReg(loopvarDt, indexReg, step)
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
}
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step)
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
val branchOpcode = if(loopvar.dt in SignedDatatypes) Opcode.BLES else Opcode.BLE
code += VmCodeInstruction(branchOpcode, loopvarDt, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel)
return code
@ -315,15 +308,8 @@ class CodeGen(internal val program: PtProgram,
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress)
code += VmCodeLabel(loopLabel)
code += translateNode(forLoop.statements)
if(step<3) {
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step)
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
} else {
// TODO WHY THIS DISTICTION ?
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
code += addConstReg(loopvarDt, indexReg, step)
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
}
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step)
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
code += if(rangeEndWrapped==0) {
VmCodeInstruction(Opcode.BNZ, loopvarDt, reg1 = indexReg, labelSymbol = loopLabel)
} else {
@ -381,18 +367,13 @@ class CodeGen(internal val program: PtProgram,
}
else -> {
val valueReg = vmRegisters.nextFree()
val operandReg = vmRegisters.nextFree()
if(value>0) {
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=valueReg, value=address.toInt())
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=operandReg, value=value)
code += VmCodeInstruction(Opcode.ADDR, dt, reg1 = valueReg, reg2 = operandReg) // TODO USE ADDM?
code += VmCodeInstruction(Opcode.STOREM, dt, reg1=valueReg, value=address.toInt())
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value=value)
code += VmCodeInstruction(Opcode.ADDM, dt, reg1=valueReg, value=address.toInt())
}
else {
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=valueReg, value=address.toInt())
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=operandReg, value=-value)
code += VmCodeInstruction(Opcode.SUBR, dt, reg1 = valueReg, reg2 = operandReg) // TODO USE ADDM?
code += VmCodeInstruction(Opcode.STOREM, dt, reg1=valueReg, value=address.toInt())
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value=-value)
code += VmCodeInstruction(Opcode.SUBM, dt, reg1=valueReg, value=address.toInt())
}
}
}

View File

@ -172,6 +172,7 @@ class VmPeepholeOptimizer(private val vmprog: AssemblyProgram, private val alloc
// TODO: detect multiple sequential rnd with same reg1, only keep one
// TODO: detect subsequent same xors/nots/negs, remove the pairs completely as they cancel out
// TODO: detect multiple same ands, ors; only keep first
// TODO: (hard) detect multiple registers being assigned the same value (and not changed) - use only 1 of them
// ...
}
return changed

View File

@ -3,9 +3,6 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- fix the obvious TODOs in CodeGen (vm)
- vm: AssignmentGen - fix in-place array assign TODO
...

View File

@ -2,27 +2,16 @@
%zeropage basicsafe
main {
romsub $ea31 = foobar(uword derp @AY) -> ubyte @A
romsub $ea33 = foobar2() -> ubyte @A
romsub $ea33 = foobar3()
sub subroutine(ubyte subroutineArg) -> ubyte {
return subroutineArg+22
}
asmsub asmsubje(uword arg @AY) -> ubyte @A {
%asm {{
rts
return
}}
}
sub start() {
ubyte @shared qq0 = subroutine(11)
ubyte @shared qq1 = foobar(12345)
ubyte @shared qq2 = foobar2()
foobar3()
ubyte[] arr = [1,2,3,4]
uword pointer
ubyte ix
txt.print_ub(qq0)
arr[ix] = arr[ix]+1
; arr[3] = arr[3]+1
; pointer[3] = pointer[3]+1
txt.print_ub(arr[3])
}
}

View File

@ -102,7 +102,7 @@ add reg1, value - reg1 += value (unsigned + signed)
addm reg1, address - memory at address += reg1 (unsigned + signed)
subr reg1, reg2 - reg1 -= reg2 (unsigned + signed)
sub reg1, value - reg1 -= value (unsigned + signed)
subm reg1, address - memory at address -= reg2 (unsigned + signed)
subm reg1, address - memory at address -= reg1 (unsigned + signed)
mulr reg1, reg2 - unsigned multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
mul reg1, value - unsigned multiply reg1 *= value note: byte*byte->byte, no type extension to word!
mulm reg1, address - memory at address *= reg2 note: byte*byte->byte, no type extension to word!