From ad2355f8d3c83cb7606dd685bd437344ed601cbc Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 31 Mar 2022 01:41:59 +0200 Subject: [PATCH] vm forloop done --- .../src/prog8/codegen/virtual/CodeGen.kt | 53 ++++++++++++++----- docs/source/todo.rst | 8 +-- examples/test.p8 | 4 +- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index 966d3da3f..e9e3d53f3 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -9,7 +9,7 @@ import prog8.vm.VmDataType import kotlin.math.pow -internal class VmRegisterPool() { +internal class VmRegisterPool { private var firstFree: Int=3 // registers 0,1,2 are reserved fun peekNext() = firstFree @@ -164,8 +164,32 @@ class CodeGen(internal val program: PtProgram, private fun translateForInNonConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): VmCodeChunk { val iterable = forLoop.iterable as PtRange - TODO("forloop ${loopvar.dt} ${loopvar.scopedName} in non-constant range ${iterable} ") - iterable.printIndented(0) + val step = iterable.step.number.toInt() + if (step==0) + throw AssemblyError("step 0") + val indexReg = vmRegisters.nextFree() + val endvalueReg = vmRegisters.nextFree() + val loopvarAddress = allocations.get(loopvar.scopedName) + val loopvarDt = vmType(loopvar.dt) + val loopLabel = createLabelName() + val code = VmCodeChunk() + + code += expressionEval.translateExpression(iterable.to, endvalueReg) + code += expressionEval.translateExpression(iterable.from, indexReg) + 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 { + code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress) + code += addConstReg(loopvarDt, indexReg, step) + code += VmCodeInstruction(Opcode.STOREM, 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, symbol=loopLabel) + return code } private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): VmCodeChunk { @@ -182,22 +206,23 @@ class CodeGen(internal val program: PtProgram, val loopvarAddress = allocations.get(loopvar.scopedName) val indexReg = vmRegisters.nextFree() val endvalueReg = vmRegisters.nextFree() - val vmDt = vmType(loopvar.dt) + val loopvarDt = vmType(loopvar.dt) val code = VmCodeChunk() - code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=endvalueReg, value=range.last) - code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=indexReg, value=range.first) - code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=indexReg, value=loopvarAddress) + code += VmCodeInstruction(Opcode.LOAD, loopvarDt, reg1=endvalueReg, value=range.last) + code += VmCodeInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=range.first) + code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress) code += VmCodeLabel(loopLabel) code += translateNode(forLoop.statements) - if(range.step==1 || range.step==2) { - code += addConstMem(vmDt, loopvarAddress.toUInt(), range.step) - code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = indexReg, value = loopvarAddress) + if(range.step<3) { + code += addConstMem(loopvarDt, loopvarAddress.toUInt(), range.step) + code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress) } else { - code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = indexReg, value = loopvarAddress) - code += addConstReg(vmDt, indexReg, range.step) - code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = indexReg, value = loopvarAddress) + code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress) + code += addConstReg(loopvarDt, indexReg, range.step) + code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1 = indexReg, value = loopvarAddress) } - code += VmCodeInstruction(Opcode.BNE, vmDt, reg1=indexReg, reg2=endvalueReg, symbol=loopLabel) + // TODO more optimal loop instruction for loops ending on 0 (BNZ?) + code += VmCodeInstruction(Opcode.BNE, loopvarDt, reg1=indexReg, reg2=endvalueReg, symbol=loopLabel) return code } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 23a95ab9b..33e52b71b 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -6,20 +6,20 @@ For next release - x16: screen_set_mode -> screen_mode + other args https://github.com/commanderx16/x16-docs/blob/master/Commander%20X16%20Programmer's%20Reference%20Guide.md#function-name-screen_mode - x16: change mouse_config API https://github.com/commanderx16/x16-docs/blob/master/Commander%20X16%20Programmer's%20Reference%20Guide.md#function-name-mouse_config also add mouse_config2() ? that does the screen_mode() trick internally for you? +- x16: check new ZP free addresses https://github.com/commanderx16/x16-docs/commit/541f2ce9e61d1d0d0e157d7f52fe16bc0895e6f0 + and https://www.commanderx16.com/forum/index.php?/topic/363-keep-zero-page-empty-as-much-as-possible/#comment-18561 - x16: check additional FP lib changes https://github.com/commanderx16/x16-rom/commit/ae608673f0210953172d6837acfbb231d62ddbd1 and https://github.com/commanderx16/x16-docs/commit/21238aedc641da91df88e04c4ce9bf3324a3c12d - x16: check joystick support (petaxian, own stuff) because of api change in r39 kernal https://github.com/commanderx16/x16-docs/blob/master/Commander%20X16%20Programmer's%20Reference%20Guide.md#function-name-joystick_get - x16: new vera memory layout https://github.com/commanderx16/x16-rom/issues/185 this may break certain things in gfx2 and elsewhere. Such as font rendering broken examples: amiga, colorbars, cube3d, highresbitmap, rasterbars, tehtriz, testgfx2, testvtui can we make the code read the new layout from vera registers instead of hardcoding it? -- x16: check new ZP free addresses https://github.com/commanderx16/x16-docs/commit/541f2ce9e61d1d0d0e157d7f52fe16bc0895e6f0 - and https://www.commanderx16.com/forum/index.php?/topic/363-keep-zero-page-empty-as-much-as-possible/#comment-18561 - x16: optimize diskio load_raw because headerless files are now supported https://github.com/commanderx16/x16-rom/pull/216 note: must still work on c64/c128 that don't have this! -- vm codegen: ForLoop + - vm codegen: When - vm codegen: Pipe expression -- vm codegen: validate that PtFunctionCall translation works okay with resultregister +- vm codegen: validate that PtFunctionCall translation works okay with resultregister, and multiple paramsters in correct order - vm codegen: postincrdecr arrayvalue - vm: support no globals re-init option - vm: how to remove all unused subroutines? (for asm, 64tass used to do this) diff --git a/examples/test.p8 b/examples/test.p8 index 8673c8494..fa576d9cf 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -34,8 +34,8 @@ main { txt.print_uw(ww) ; 11 txt.nl() - const ubyte rfrom = 10 - const ubyte rto = 17 + ubyte rfrom = 10 + ubyte rto = 17 for bc in rfrom to rto step 2 { ; 10,12,14,16