diff --git a/compiler/src/prog8/compiler/target/c64/codegen2/AsmGen2.kt b/compiler/src/prog8/compiler/target/c64/codegen2/AsmGen2.kt index a84ab921f..a49837735 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen2/AsmGen2.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen2/AsmGen2.kt @@ -965,11 +965,14 @@ internal class AsmGen2(val program: Program, when(iterableDt) { in ByteDatatypes -> { if(stmt.loopRegister!=null) { - // loop register + + // loop register over range + if(stmt.loopRegister!=Register.A) throw AssemblyError("can only use A") when { range.step==1 -> { + // step = 1 val counterLabel = makeLabel("for_counter") out(""" lda #${range.first} @@ -987,6 +990,7 @@ $counterLabel .byte 0 $endLabel""") } range.step==-1 -> { + // step = -1 val counterLabel = makeLabel("for_counter") out(""" lda #${range.first} @@ -1004,6 +1008,7 @@ $counterLabel .byte 0 $endLabel""") } range.step>0 -> { + // step >= 2 val counterLabel = makeLabel("for_counter") out(""" lda #${(range.last-range.first) / range.step + 1} @@ -1022,6 +1027,7 @@ $counterLabel .byte 0 $endLabel""") } else -> { + // step <= -2 val counterLabel = makeLabel("for_counter") out(""" lda #${(range.first-range.last) / range.step.absoluteValue + 1} @@ -1040,8 +1046,91 @@ $counterLabel .byte 0 $endLabel""") } } + } else { - TODO("loop over byte range via loopvar $stmt") + + // loop over byte range via loopvar + val varname = asmIdentifierName(stmt.loopVar!!) + when { + range.step==1 -> { + // step = 1 + val counterLabel = makeLabel("for_counter") + out(""" + lda #${range.first} + sta $varname + lda #${range.last-range.first+1 and 255} + sta $counterLabel +$loopLabel""") + translate(stmt.body) + out(""" + dec $counterLabel + beq $endLabel + inc $varname + jmp $loopLabel +$counterLabel .byte 0 +$endLabel""") + } + range.step==-1 -> { + // step = -1 + val counterLabel = makeLabel("for_counter") + out(""" + lda #${range.first} + sta $varname + lda #${range.first-range.last+1 and 255} + sta $counterLabel +$loopLabel""") + translate(stmt.body) + out(""" + dec $counterLabel + beq $endLabel + dec $varname + jmp $loopLabel +$counterLabel .byte 0 +$endLabel""") + } + range.step>0 -> { + // step >= 2 + val counterLabel = makeLabel("for_counter") + out(""" + lda #${(range.last-range.first) / range.step + 1} + sta $counterLabel + lda #${range.first} + sta $varname +$loopLabel""") + translate(stmt.body) + out(""" + dec $counterLabel + beq $endLabel + lda $varname + clc + adc #${range.step} + sta $varname + jmp $loopLabel +$counterLabel .byte 0 +$endLabel""") + } + else -> { + // step <= -2 + val counterLabel = makeLabel("for_counter") + out(""" + lda #${(range.first-range.last) / range.step.absoluteValue + 1} + sta $counterLabel + lda #${range.first} + sta $varname +$loopLabel""") + translate(stmt.body) + out(""" + dec $counterLabel + beq $endLabel + lda $varname + sec + sbc #${range.step.absoluteValue} + sta $varname + jmp $loopLabel +$counterLabel .byte 0 +$endLabel""") + } + } } } in WordDatatypes -> { @@ -1056,37 +1145,32 @@ $endLabel""") val decl = ident.targetVarDecl(program.namespace)!! when(iterableDt) { DataType.STR, DataType.STR_S -> { - if(stmt.loopRegister!=null) { - // loop register - if(stmt.loopRegister!=Register.A) - throw AssemblyError("can only use A") - out(""" + if(stmt.loopRegister!=null && stmt.loopRegister!=Register.A) + throw AssemblyError("can only use A") + out(""" lda #<$iterableName ldy #>$iterableName sta $loopLabel+1 sty $loopLabel+2 $loopLabel lda ${65535.toHex()} ; modified beq $endLabel""") - translate(stmt.body) - out(""" + if(stmt.loopVar!=null) + out(" sta ${asmIdentifierName(stmt.loopVar!!)}") + translate(stmt.body) + out(""" inc $loopLabel+1 bne $loopLabel inc $loopLabel+2 bne $loopLabel $endLabel""") - } else { - TODO("loop over string via loopvar $stmt") - } } DataType.ARRAY_UB, DataType.ARRAY_B -> { val length = decl.arraysize!!.size() - if(stmt.loopRegister!=null) { - // loop register - if(stmt.loopRegister!=Register.A) - throw AssemblyError("can only use A") - val counterLabel = makeLabel("for_counter") - val modifiedLabel = makeLabel("for_modified") - out(""" + if(stmt.loopRegister!=null && stmt.loopRegister!=Register.A) + throw AssemblyError("can only use A") + val counterLabel = makeLabel("for_counter") + val modifiedLabel = makeLabel("for_modified") + out(""" lda #<$iterableName ldy #>$iterableName sta $modifiedLabel+1 @@ -1095,18 +1179,16 @@ $endLabel""") $loopLabel sty $counterLabel cpy #$length beq $endLabel -$modifiedLabel lda ${65535.toHex()},y ; modified - """) - translate(stmt.body) - out(""" +$modifiedLabel lda ${65535.toHex()},y ; modified""") + if(stmt.loopVar!=null) + out(" sta ${asmIdentifierName(stmt.loopVar!!)}") + translate(stmt.body) + out(""" ldy $counterLabel iny jmp $loopLabel $counterLabel .byte 0 $endLabel""") - } else { - TODO("loop variable over bytearray of len $length") - } } DataType.ARRAY_W, DataType.ARRAY_UW -> { val length = decl.arraysize!!.size() diff --git a/examples/fibonacci.p8 b/examples/fibonacci.p8 index 5b40a359c..3e45d1403 100644 --- a/examples/fibonacci.p8 +++ b/examples/fibonacci.p8 @@ -11,7 +11,7 @@ main { sub start() { c64scr.print("fibonacci sequence\n") fib_setup() - for ubyte i in 0 to 20 { + for A in 0 to 20 { c64scr.print_uw(fib_next()) c64.CHROUT('\n') } diff --git a/examples/test.p8 b/examples/test.p8 index ff30f3ab3..f79fe8b13 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -43,24 +43,45 @@ main { c64.CHROUT(',') } c64.CHROUT('\n') + c64.CHROUT('\n') + + for ubyte cc in "hello" { + c64scr.print_ub(cc) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for ubyte cc2 in [1,3,5,99] { + c64scr.print_ub(cc2) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for ubyte cc3 in 10 to 20 { + c64scr.print_ub(cc3) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for ubyte cc4 in 20 to 10 step -1 { + c64scr.print_ub(cc4) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for ubyte cc5 in 10 to 21 step 3 { + c64scr.print_ub(cc5) + c64.CHROUT(',') + } + c64.CHROUT('\n') + + for ubyte cc6 in 24 to 10 step -3 { + c64scr.print_ub(cc6) + c64.CHROUT(',') + } + c64.CHROUT('\n') + c64.CHROUT('\n') -; for var2 in 10 to 20 { -; c64scr.print_ub(var2) -; c64.CHROUT(',') -; } -; c64.CHROUT('\n') -; -; for ubyte var3 in 10 to 20 { -; c64scr.print_ub(var3) -; c64.CHROUT(',') -; } -; c64.CHROUT('\n') -; -; for bvar in -5 to 5 { -; c64scr.print_b(bvar) -; c64.CHROUT(',') -; } -; c64.CHROUT('\n') ; for float fl in [1.1, 2.2, 5.5, 99.99] { ; c64flt.print_f(fl)