diff --git a/codeGenVirtual/src/prog8/codegen/virtual/AssignmentGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/AssignmentGen.kt index 8b2860bec..2abccb6b5 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/AssignmentGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/AssignmentGen.kt @@ -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) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index 48324bfbd..4eb392159 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -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()) } } } diff --git a/codeGenVirtual/src/prog8/codegen/virtual/VmPeepholeOptimizer.kt b/codeGenVirtual/src/prog8/codegen/virtual/VmPeepholeOptimizer.kt index 3713a269c..3609f8ef3 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/VmPeepholeOptimizer.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/VmPeepholeOptimizer.kt @@ -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 diff --git a/docs/source/todo.rst b/docs/source/todo.rst index b17ea66f1..6cd9810ee 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,9 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- fix the obvious TODOs in CodeGen (vm) -- vm: AssignmentGen - fix in-place array assign TODO - ... diff --git a/examples/test.p8 b/examples/test.p8 index 527901c49..584053fae 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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]) } } diff --git a/virtualmachine/src/prog8/vm/Instructions.kt b/virtualmachine/src/prog8/vm/Instructions.kt index a9b06e508..476734642 100644 --- a/virtualmachine/src/prog8/vm/Instructions.kt +++ b/virtualmachine/src/prog8/vm/Instructions.kt @@ -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!