diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt
index 7550640ca..cb2a988c0 100644
--- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt
+++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt
@@ -966,12 +966,10 @@ internal class AsmGen(private val program: Program,
val name = asmVariableName(stmt.iterations as IdentifierReference)
when(vardecl.datatype) {
DataType.UBYTE, DataType.BYTE -> {
- out(" lda $name")
- repeatByteCountInA(null, repeatLabel, endLabel, stmt.body)
+ repeatByteCountVar(name, repeatLabel, endLabel, stmt.body)
}
DataType.UWORD, DataType.WORD -> {
- out(" lda $name | ldy $name+1")
- repeatWordCountInAY(null, repeatLabel, endLabel, stmt.body)
+ repeatWordCountVar(name, repeatLabel, endLabel, stmt.body)
}
else -> throw AssemblyError("invalid loop variable datatype $vardecl")
}
@@ -1001,6 +999,7 @@ internal class AsmGen(private val program: Program,
if(constIterations==0)
return
// note: A/Y must have been loaded with the number of iterations already!
+ // TODO can be even more optimized by iterating over pages
val counterVar = makeLabel("repeatcounter")
out("""
sta $counterVar
@@ -1035,22 +1034,54 @@ $counterVar .word 0""")
val counterVar = makeLabel("repeatcounter")
if(constIterations==null)
out(" beq $endLabel")
- out("""
- sta $counterVar
-$repeatLabel""")
+ out(" sta $counterVar")
+ out(repeatLabel)
translate(body)
out("""
dec $counterVar
bne $repeatLabel
- beq $endLabel""")
- if(constIterations!=null && constIterations>=16 && zeropage.available() > 0) {
- // allocate count var on ZP
- val zpAddr = zeropage.allocate(counterVar, DataType.UBYTE, body.position, errors)
- out("""$counterVar = $zpAddr ; auto zp UBYTE""")
- } else {
- out("""
+ beq $endLabel
$counterVar .byte 0""")
- }
+ out(endLabel)
+ }
+
+ private fun repeatByteCountVar(repeatCountVar: String, repeatLabel: String, endLabel: String, body: AnonymousScope) {
+ // note: cannot use original counter variable because it should retain its original value
+ val counterVar = makeLabel("repeatcounter")
+ out(" lda $repeatCountVar | beq $endLabel | sta $counterVar")
+ out(repeatLabel)
+ translate(body)
+ out(" dec $counterVar | bne $repeatLabel")
+ // inline countervar:
+ out("""
+ beq $endLabel
+$counterVar .byte 0""")
+ out(endLabel)
+ }
+
+ private fun repeatWordCountVar(repeatCountVar: String, repeatLabel: String, endLabel: String, body: AnonymousScope) {
+ // TODO can be even more optimized by iterating over pages
+ // note: cannot use original counter variable because it should retain its original value
+ val counterVar = makeLabel("repeatcounter")
+ out("""
+ lda $repeatCountVar
+ sta $counterVar
+ ora $repeatCountVar+1
+ beq $endLabel
+ lda $repeatCountVar+1
+ sta $counterVar+1""")
+ out(repeatLabel)
+ translate(body)
+ out("""
+ lda $counterVar
+ bne +
+ dec $counterVar+1
++ dec $counterVar
+ lda $counterVar
+ ora $counterVar+1
+ bne $repeatLabel
+ beq $endLabel
+$counterVar .word 0""")
out(endLabel)
}
diff --git a/docs/source/todo.rst b/docs/source/todo.rst
index 7f2560641..7ad210537 100644
--- a/docs/source/todo.rst
+++ b/docs/source/todo.rst
@@ -2,15 +2,13 @@
TODO
====
-- add any2(), all2(), max2(), min2(), reverse2(), sum2(), sort2() that take (array, startindex, length) arguments
- optimize for loop iterations better to allow proper inx, cpx #value, bne loop instructions (like repeat loop)
-- why is there a beq _prog8_label_2_repeatend at the end of repeat loops? seems unused
- optimize swap of two memread values with index, using the same pointer expression/variable, like swap(@(ptr+1), @(ptr+2))
- implement the linked_list millfork benchmark
-- use the 65c02 bit clear/set/test instructions for single-bit operations
- implement highres 4 color mode in gfx2
- make a retro Amiga Workbench "simulator" using that new gfx mode
+- use the 65c02 bit clear/set/test instructions for single-bit operations
- add a flood fill routine to gfx2
- can we get rid of the --longOptionName command line options and only keep the short versions? https://github.com/Kotlin/kotlinx-cli/issues/50
- add a f_seek() routine for the Cx16 that uses its seek dos api?
diff --git a/examples/test.p8 b/examples/test.p8
index b9def49a5..888d18323 100644
--- a/examples/test.p8
+++ b/examples/test.p8
@@ -5,6 +5,12 @@ main {
sub start() {
- txt.print("hello\n")
+ uword xx
+ uword iter = 256
+ repeat iter {
+ xx++
+ }
+
+ txt.print_uw(xx)
}
}
diff --git a/syntax-files/IDEA/Prog8.xml b/syntax-files/IDEA/Prog8.xml
index 453d93906..2a92bb898 100644
--- a/syntax-files/IDEA/Prog8.xml
+++ b/syntax-files/IDEA/Prog8.xml
@@ -11,7 +11,7 @@
-
+