diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index ae8102675..d3887735d 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -695,25 +695,56 @@ internal class AsmGen(private val program: Program, when { iterations == 0 -> {} iterations <= 255 -> { - out(""" - lda #${iterations} - sta $counterLabel -$repeatLabel lda $counterLabel - beq $endLabel - dec $counterLabel -""") - translate(stmt.body) - out(""" - jmp $repeatLabel -$counterLabel .byte 0 -$endLabel""") + out(" lda #${iterations}") + repeatByteCountInA(counterLabel, repeatLabel, endLabel, stmt.body) } else -> { - out(""" - lda #<${iterations} + out(" lda #<${iterations} | ldy #>${iterations}") + repeatWordCountInAY(counterLabel, repeatLabel, endLabel, stmt.body) + } + } + } + is IdentifierReference -> { + val vardecl = (stmt.iterations as IdentifierReference).targetStatement(program.namespace) as VarDecl + val name = asmIdentifierName(stmt.iterations as IdentifierReference) + when(vardecl.datatype) { + DataType.UBYTE, DataType.BYTE -> { + out(" lda $name") + repeatByteCountInA(counterLabel, repeatLabel, endLabel, stmt.body) + } + DataType.UWORD, DataType.WORD -> { + out(" lda $name | ldy $name+1") + repeatWordCountInAY(counterLabel, repeatLabel, endLabel, stmt.body) + } + else -> throw AssemblyError("invalid loop variable datatype $vardecl") + } + } + else -> { + translateExpression(stmt.iterations!!) + val dt = stmt.iterations!!.inferType(program).typeOrElse(DataType.STRUCT) + when (dt) { + in ByteDatatypes -> { + out(" inx | lda ${ESTACK_LO_HEX},x") + repeatByteCountInA(counterLabel, repeatLabel, endLabel, stmt.body) + } + in WordDatatypes -> { + out(" inx | lda ${ESTACK_LO_HEX},x | ldy ${ESTACK_HI_HEX},x") + repeatWordCountInAY(counterLabel, repeatLabel, endLabel, stmt.body) + } + else -> throw AssemblyError("invalid loop expression datatype $dt") + } + } + } + + loopEndLabels.pop() + loopContinueLabels.pop() + } + + private fun repeatWordCountInAY(counterLabel: String, repeatLabel: String, endLabel: String, body: AnonymousScope) { + // note: A/Y must have been loaded with the number of iterations already! + out(""" sta $counterLabel - lda #>${iterations} - sta $counterLabel+1 + sty $counterLabel+1 $repeatLabel lda $counterLabel bne + lda $counterLabel+1 @@ -723,24 +754,25 @@ $repeatLabel lda $counterLabel dec $counterLabel+1 + dec $counterLabel """) - translate(stmt.body) - out(""" + translate(body) + out(""" jmp $repeatLabel $counterLabel .word 0 $endLabel""") - } - } - } - is IdentifierReference -> { - TODO("iterations ${stmt.iterations}") - } - else -> { - TODO("repeat loop with iterations ${stmt.iterations}") - } - } + } - loopEndLabels.pop() - loopContinueLabels.pop() + private fun repeatByteCountInA(counterLabel: String, repeatLabel: String, endLabel: String, body: AnonymousScope) { + // note: A must have been loaded with the number of iterations already! + out(""" + sta $counterLabel +$repeatLabel lda $counterLabel + beq $endLabel + dec $counterLabel""") + translate(body) + out(""" + jmp $repeatLabel +$counterLabel .byte 0 +$endLabel""") } private fun translate(stmt: WhileLoop) { diff --git a/examples/test.p8 b/examples/test.p8 index e7ccfea7f..16c1f62ae 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -9,5 +9,38 @@ main { sub start() { - } + repeat 10 { + c64.CHROUT('*') + } + c64.CHROUT('\n') + + ubyte ub = 9 + repeat ub { + c64.CHROUT('*') + } + c64.CHROUT('\n') + + repeat 320 { + c64.CHROUT('+') + } + c64.CHROUT('\n') + + uword uw = 320 + repeat uw { + c64.CHROUT('-') + } + c64.CHROUT('\n') + + ub = 7 + repeat ub+2 { + c64.CHROUT('*') + } + c64.CHROUT('\n') + + uw = 318 + repeat uw+2 { + c64.CHROUT('*') + } + c64.CHROUT('\n') + } } diff --git a/examples/turtle-gfx.p8 b/examples/turtle-gfx.p8 index 306080ff6..3fe54e3cb 100644 --- a/examples/turtle-gfx.p8 +++ b/examples/turtle-gfx.p8 @@ -10,11 +10,9 @@ main { sub start() { graphics.enable_bitmap_mode() turtle.init() - - repeat 100 { - while c64.RASTER { - } - } +; turtle.pu() +; turtle.pos(150, 110) +; turtle.pd() ubyte i for i in 0 to 100 {