From 6055b8c3dc872f81b201f157d2cd1a40b2b6d23c Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 10 Jul 2023 19:42:55 +0200 Subject: [PATCH] IR: fix forloop codegen for steps != 1 --- .../prog8/codegen/intermediate/IRCodeGen.kt | 26 ++++++------ docs/source/syntaxreference.rst | 8 +++- docs/source/todo.rst | 6 ++- examples/test.p8 | 42 +++++++++++-------- 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index ba3a606d5..4568e4c5c 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -552,22 +552,24 @@ class IRCodeGen( addInstr(result, IRInstruction(Opcode.STOREM, loopvarDtIr, reg1=fromTr.resultReg, labelSymbol=loopvarSymbol), null) result += labelFirstChunk(translateNode(forLoop.statements), loopLabel) - result += addConstMem(loopvarDtIr, null, loopvarSymbol, step) addInstr(result, IRInstruction(Opcode.LOADM, loopvarDtIr, reg1 = fromTr.resultReg, labelSymbol = loopvarSymbol), null) - // if endvalue >= index, iterate loop - val branchInstr = if(loopvarDt in SignedDatatypes) { - if(step>0) - IRInstruction(Opcode.BGESR, loopvarDtIr, reg1=toTr.resultReg, reg2=fromTr.resultReg, labelSymbol=loopLabel) - else - IRInstruction(Opcode.BGESR, loopvarDtIr, reg1=fromTr.resultReg, reg2=toTr.resultReg, labelSymbol=loopLabel) + if(step==1 || step==-1) { + // if endvalue == index, stop loop, else iterate + addInstr(result, IRInstruction(Opcode.BEQR, loopvarDtIr, reg1=toTr.resultReg, reg2=fromTr.resultReg, labelSymbol = labelAfterFor), null) + result += addConstMem(loopvarDtIr, null, loopvarSymbol, step) + addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = loopLabel), null) } else { - if(step>0) - IRInstruction(Opcode.BGER, loopvarDtIr, reg1=toTr.resultReg, reg2=fromTr.resultReg, labelSymbol=loopLabel) + // ind/dec index, then: + // ascending: if endvalue >= index, iterate + // descending: if index >= endvalue, iterate + result += addConstMem(loopvarDtIr, null, loopvarSymbol, step) + addInstr(result, IRInstruction(Opcode.LOADM, loopvarDtIr, reg1=fromTr.resultReg, labelSymbol = loopvarSymbol), null) + if(step > 0) + addInstr(result, IRInstruction(Opcode.CMP, loopvarDtIr, reg1 = toTr.resultReg, fromTr.resultReg), null) else - IRInstruction(Opcode.BGER, loopvarDtIr, reg1=fromTr.resultReg, reg2=toTr.resultReg, labelSymbol=loopLabel) + addInstr(result, IRInstruction(Opcode.CMP, loopvarDtIr, reg1 = fromTr.resultReg, toTr.resultReg), null) + addInstr(result, IRInstruction(Opcode.BSTPOS, labelSymbol = loopLabel), null) } - addInstr(result, branchInstr, null) - result += IRCodeChunk(labelAfterFor, null) return result } diff --git a/docs/source/syntaxreference.rst b/docs/source/syntaxreference.rst index 6c32e9f05..ecbe01d8e 100644 --- a/docs/source/syntaxreference.rst +++ b/docs/source/syntaxreference.rst @@ -145,12 +145,16 @@ Directives Level: not at module scope. This directive can only be used inside a block. - The assembler will include the file as binary bytes at this point, prog8 will not process this at all. - The optional offset and length can be used to select a particular piece of the file. + The assembler itself will include the file as binary bytes at this point, prog8 will not process this at all. + This means that the filename must be spelled exactly as it appears on your computer's file system. + Note that this filename may differ in case compared to when you chose to load the file from disk from within the + program code itself (for example on the C64 and X16 there's the PETSCII encoding difference). The file is located relative to the current working directory! + The optional offset and length can be used to select a particular piece of the file. To reference the contents of the included binary data, you can put a label in your prog8 code just before the %asmbinary. An example program for this can be found below at the description of %asminclude. + .. data:: %asminclude "" Level: not at module scope. diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 32cfe267b..2cd306b14 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,9 +1,13 @@ TODO ==== -- VM: fix endless loop n=0 :: for i in 5 downto n (fine for n=1) (wrong for bytes and words) +- codegen: fix endless loop uword n=0 :: for uword i in 10 downto n step -3 + +- investigate if the hiscores issue on the forum is a compiler bug or not. - IR: instructions that do type conversion (SZ etc, CONCAT, SGN) should put the result in a DIFFERENT register. +- IR: optimize forloop codegen to use a reg as loop variable instead of a memory variable, just store it in the mem var before entering the loop body + check repeat loop as well it shouldn't be using a tempvar just a register to count. ... diff --git a/examples/test.p8 b/examples/test.p8 index ce8138a38..9db4dd57e 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,23 +4,31 @@ main { sub start() { - byte intensity = -25 - txt.print_b(intensity) - txt.nl() - txt.print_b(abs(intensity)) - intensity = abs(intensity) - txt.nl() - txt.print_b(intensity) - txt.nl() + uword n=0 + uword i + txt.print("ascending:\n") + n=10 + for i in 0 to n step 3 { + cx16.r0++ + txt.print(" i=") + txt.print_uw(i) + txt.spc() + txt.print(" n=") + txt.print_uw(n) + txt.nl() + } - txt.print_uw0(12345) - txt.nl() - word intensityw = -12345 - txt.print_w(intensityw) - txt.nl() - txt.print_w(abs(intensityw)) - intensityw = abs(intensityw) - txt.nl() - txt.print_w(intensityw) + txt.print("descending:\n") + n=0 + for i in 10 downto n step -3 { + cx16.r0++ + txt.print(" i=") + txt.print_uw(i) + txt.spc() + txt.print(" n=") + txt.print_uw(n) + txt.nl() + } } } +