From 07b5c44a54e9f7d14ab99f8c4dae7c7ef6e639a2 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 28 Feb 2021 17:00:52 +0100 Subject: [PATCH] preparing to optimize 16 bit repeat loop --- .../compiler/target/cpu6502/codegen/AsmGen.kt | 76 +++++-------------- examples/test.p8 | 24 +++++- 2 files changed, 42 insertions(+), 58 deletions(-) diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index c71d19860..715accc23 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -976,10 +976,12 @@ internal class AsmGen(private val program: Program, val name = asmVariableName(stmt.iterations as IdentifierReference) when(vardecl.datatype) { DataType.UBYTE, DataType.BYTE -> { - repeatByteCountVar(name, repeatLabel, endLabel, stmt.body) + assignVariableToRegister(name, RegisterOrPair.A) + repeatByteCountInA(null, repeatLabel, endLabel, stmt.body) } DataType.UWORD, DataType.WORD -> { - repeatWordCountVar(name, repeatLabel, endLabel, stmt.body) + assignVariableToRegister(name, RegisterOrPair.AY) + repeatWordCountInAY(null, repeatLabel, endLabel, stmt.body) } else -> throw AssemblyError("invalid loop variable datatype $vardecl") } @@ -1009,22 +1011,26 @@ 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 - sty $counterVar+1 -$repeatLabel lda $counterVar - bne + - lda $counterVar+1 - beq $endLabel -+ lda $counterVar - bne + - dec $counterVar+1 -+ dec $counterVar -""") + cmp #0 + bne + + cpy #0 + beq $endLabel ; skip if 0 iterations ++ sta $counterVar + sty $counterVar+1 +$repeatLabel + lda $counterVar + bne + + lda $counterVar+1 + beq $endLabel ++ lda $counterVar + bne + + dec $counterVar+1 ++ dec $counterVar""") translate(body) jmp(repeatLabel) + if(constIterations!=null && constIterations>=16 && zeropage.available() > 1) { // allocate count var on ZP val zpAddr = zeropage.allocate(counterVar, DataType.UWORD, body.position, errors) @@ -1033,8 +1039,8 @@ $repeatLabel lda $counterVar out(""" $counterVar .word 0""") } - out(endLabel) + out(endLabel) } private fun repeatByteCountInA(constIterations: Int?, repeatLabel: String, endLabel: String, body: AnonymousScope) { @@ -1055,46 +1061,6 @@ $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) - } - private fun translate(stmt: WhileLoop) { checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x ' val booleanCondition = stmt.condition as BinaryExpression diff --git a/examples/test.p8 b/examples/test.p8 index c25cd3907..ecab6a0b3 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,17 +7,35 @@ main { uword xx1 uword xx2 uword xx3 - uword total + uword iterations c64.SETTIM(0,0,0) - repeat 600 { - repeat 600 { + + iterations = 0 + repeat iterations { + repeat iterations { + xx1++ + xx2++ + xx3++ + } + } + + iterations = 600 + repeat iterations { + repeat iterations { xx1++ xx2++ xx3++ } } uword time = c64.RDTIM16() + txt.print("time: ") txt.print_uw(time) + txt.print("\n$7e40? :\n") + txt.print_uwhex(xx1,true) + txt.nl() + txt.print_uwhex(xx2,true) + txt.nl() + txt.print_uwhex(xx3,true) } }