diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ForLoopsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ForLoopsAsmGen.kt index 5d609b974..80640a8ba 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ForLoopsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ForLoopsAsmGen.kt @@ -51,7 +51,22 @@ internal class ForLoopsAsmGen(private val program: PtProgram, // loop over byte range via loopvar val varname = asmgen.asmVariableName(stmt.variable) asmgen.assignExpressionToVariable(range.from, varname, ArrayToElementTypes.getValue(iterableDt)) - asmgen.assignExpressionToVariable(range.to, "$modifiedLabel+1", ArrayToElementTypes.getValue(iterableDt)) + asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false) + // pre-check for end already reached + if(iterableDt==DataType.ARRAY_B) { + if(stepsize<0) { + println("signed byte check to<=from") // TODO + } else { + println("signed byte check from<=to") // TODO + } + } else { + if(stepsize<0) { + println("unsigned byte check to<=from") // TODO + } else { + println("unsigned byte check from<=to") // TODO + } + } + asmgen.out(" sta $modifiedLabel+1") asmgen.out(loopLabel) asmgen.translate(stmt.statements) asmgen.out(""" @@ -70,6 +85,20 @@ $modifiedLabel cmp #0 ; modified val varname = asmgen.asmVariableName(stmt.variable) asmgen.assignExpressionToVariable(range.from, varname, ArrayToElementTypes.getValue(iterableDt)) asmgen.assignExpressionToVariable(range.to, "$modifiedLabel+1", ArrayToElementTypes.getValue(iterableDt)) + // pre-check for end already reached + if(iterableDt==DataType.ARRAY_B) { + if(stepsize<0) { + println("signed byte check to<=from") // TODO + } else { + println("signed byte check from<=to") // TODO + } + } else { + if(stepsize<0) { + println("unsigned byte check to<=from") // TODO + } else { + println("unsigned byte check from<=to") // TODO + } + } asmgen.out(loopLabel) asmgen.translate(stmt.statements) if(stepsize>0) { @@ -102,6 +131,20 @@ $modifiedLabel cmp #0 ; modified val varname = asmgen.asmVariableName(stmt.variable) assignLoopvar(stmt, range) asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY) + // pre-check for end already reached + if(iterableDt==DataType.ARRAY_W) { + if(stepsize<0) { + println("signed word check to<=from") // TODO + } else { + println("signed word check from<=to") // TODO + } + } else { + if(stepsize<0) { + println("unsigned word check to<=from") // TODO + } else { + println("unsigned word check from<=to") // TODO + } + } asmgen.out(""" sty $modifiedLabel+1 sta $modifiedLabel2+1 @@ -136,6 +179,12 @@ $modifiedLabel2 cmp #0 ; modified val varname = asmgen.asmVariableName(stmt.variable) assignLoopvar(stmt, range) asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY) + // pre-check for end already reached + if(iterableDt==DataType.ARRAY_W) { + println("signed word check from<=to") // TODO + } else { + println("unsigned word check from<=to") // TODO + } asmgen.out(""" sty $modifiedLabel+1 sta $modifiedLabel2+1 @@ -184,6 +233,12 @@ $endLabel""") val varname = asmgen.asmVariableName(stmt.variable) assignLoopvar(stmt, range) asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY) + // pre-check for end already reached + if(iterableDt==DataType.ARRAY_W) { + println("signed word check to<=from") // TODO + } else { + println("unsigned word check to<=from") // TODO + } asmgen.out(""" sty $modifiedLabel+1 sta $modifiedLabel2+1 diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 3ae1d8fda..10787c554 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -488,8 +488,8 @@ the given number of times. It's meant to "unroll loops" - trade memory for speed Only simple statements are allowed to be inside an unroll loop (assignments, function calls etc.). .. attention:: - The value of the loop variable after executing the loop *is undefined*. Don't use it immediately - after the loop without first assigning a new value to it! + The value of the loop variable after executing the loop *is undefined* - you cannot rely + on it to be the last value in the range for instance! The value of the variable should only be used inside the for loop body. (this is an optimization issue to avoid having to deal with mostly useless post-loop logic to adjust the loop variable's value) .. warning:: diff --git a/docs/source/todo.rst b/docs/source/todo.rst index b1a7e461c..c450bdb35 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -11,10 +11,11 @@ For 9.0 major changes - DONE: cx16diskio module merged into diskio (which got specialized for commander x16 target). load() and load_raw() with extra ram bank parameter are gone. - DONE: drivenumber parameter removed from all routines in diskio module. The drive to work on is now simply stored as a diskio.drivenumber variable, which defaults to 8. +- VM codegen: fix for loop pre-check for negative stepsizes. - 6502 codegen: see if we can let for loops skip the loop if startvar>endvar, without adding a lot of code size/duplicating the loop condition. It is documented behavior to now loop 'around' $00 but it's too easy to forget about! - Lot of work because of so many special cases in ForLoopsAsmgen..... - (vm codegen already behaves like this!) + Lot of work because of many special cases in ForLoopsAsmgen.translateForOverNonconstRange() + (vm codegen already behaves like this partly! Except for negative step sizes right now) - once 9.0 is stable, upgrade other programs (assem, shell, etc) to it. + add migration guide to the manual. - [much work:] add special (u)word array type (or modifier such as @fast? ) that puts the array into memory as 2 separate byte-arrays 1 for LSB 1 for MSB -> allows for word arrays of length 256 and faster indexing this is an enormous amout of work, if this type is to be treated equally as existing (u)word , because all expression / lookup / assignment routines need to know about the distinction.... diff --git a/examples/test.p8 b/examples/test.p8 index 48fc47100..0d371aa96 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,12 +6,66 @@ main { sub start() { - ubyte bb = 199 - txt.print_ub(sqrt(bb)) - txt.nl() - float fl = 199.99 - floats.print_f(floats.sqrtf(fl)) - txt.nl() + ubyte target = 10 + ubyte from = 250 + + ubyte xx + for xx in from to target { + txt.print_ub(xx) + txt.spc() + } + txt.print("done\n") + for xx in target downto from { + txt.print_ub(xx) + txt.spc() + } + txt.print("done\n") + + byte starget = -120 + byte sfrom = 120 + + byte sxx + for sxx in sfrom to starget { + txt.print_b(sxx) + txt.spc() + } + txt.print("done\n") + for sxx in starget downto sfrom { + txt.print_b(sxx) + txt.spc() + } + txt.print("done\n") + + uword wtarget = 10 + uword wfrom = 65530 + + uword ww + for ww in wfrom to wtarget { + txt.print_uw(ww) + txt.spc() + } + txt.print("done\n") + for ww in wtarget downto wfrom { + txt.print_uw(ww) + txt.spc() + } + txt.print("done\n") + + word swtarget = -32760 + word swfrom = 32760 + word sww + for sww in swfrom to swtarget { + txt.print_w(sww) + txt.spc() + } + txt.print("done\n") + for sww in swtarget downto swfrom { + txt.print_w(sww) + txt.spc() + } + txt.print("done\n") + + ; TODO all of the above with stepsize 2 / -2 } }