From 2265ae96008b9dd11bdb1b320073af1d7791d4cb Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 8 Dec 2020 22:54:20 +0100 Subject: [PATCH] optimized setting word values into array if index is fixed number --- .../codegen/assignment/AssignmentAsmGen.kt | 62 +++++++++++-------- docs/source/todo.rst | 1 + examples/test.p8 | 48 ++++---------- 3 files changed, 48 insertions(+), 63 deletions(-) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index b1d79f57a..0874a02e1 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -1164,22 +1164,20 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen storeRegisterInMemoryAddress(register, target.memory!!) } TargetStorageKind.ARRAY -> { - when { - target.constArrayIndexValue!=null -> { - when (register) { - CpuRegister.A -> asmgen.out(" sta ${target.asmVarname}+${target.constArrayIndexValue}") - CpuRegister.X -> asmgen.out(" stx ${target.asmVarname}+${target.constArrayIndexValue}") - CpuRegister.Y -> asmgen.out(" sty ${target.asmVarname}+${target.constArrayIndexValue}") - } + if (target.constArrayIndexValue!=null) { + when (register) { + CpuRegister.A -> asmgen.out(" sta ${target.asmVarname}+${target.constArrayIndexValue}") + CpuRegister.X -> asmgen.out(" stx ${target.asmVarname}+${target.constArrayIndexValue}") + CpuRegister.Y -> asmgen.out(" sty ${target.asmVarname}+${target.constArrayIndexValue}") } - else -> { - when (register) { - CpuRegister.A -> {} - CpuRegister.X -> asmgen.out(" txa") - CpuRegister.Y -> asmgen.out(" tya") - } - asmgen.out(" ldy ${asmgen.asmVariableName(target.array!!.indexer.indexVar!!)} | sta ${target.asmVarname},y") + } + else { + when (register) { + CpuRegister.A -> {} + CpuRegister.X -> asmgen.out(" txa") + CpuRegister.Y -> asmgen.out(" tya") } + asmgen.out(" ldy ${asmgen.asmVariableName(target.array!!.indexer.indexVar!!)} | sta ${target.asmVarname},y") } } TargetStorageKind.REGISTER -> { @@ -1238,20 +1236,30 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } } TargetStorageKind.ARRAY -> { - // TODO can be a bit more optimized if the array indexer is a number - when(regs) { - RegisterOrPair.AX -> asmgen.out(" pha | txa | pha") - RegisterOrPair.AY -> asmgen.out(" pha | tya | pha") - RegisterOrPair.XY -> asmgen.out(" txa | pha | tya | pha") - else -> throw AssemblyError("expected reg pair") + if (target.constArrayIndexValue!=null) { + val idx = target.constArrayIndexValue!! * 2 + when (regs) { + RegisterOrPair.AX -> asmgen.out(" sta ${target.asmVarname}+$idx | stx ${target.asmVarname}+$idx+1") + RegisterOrPair.AY -> asmgen.out(" sta ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1") + RegisterOrPair.XY -> asmgen.out(" stx ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1") + else -> throw AssemblyError("expected reg pair") + } } - asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y, true) - asmgen.out(""" - pla - sta ${target.asmVarname},y - dey - pla - sta ${target.asmVarname},y""") + else { + when(regs) { + RegisterOrPair.AX -> asmgen.out(" pha | txa | pha") + RegisterOrPair.AY -> asmgen.out(" pha | tya | pha") + RegisterOrPair.XY -> asmgen.out(" txa | pha | tya | pha") + else -> throw AssemblyError("expected reg pair") + } + asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y, true) + asmgen.out(""" + pla + sta ${target.asmVarname},y + dey + pla + sta ${target.asmVarname},y""") + } } TargetStorageKind.REGISTER -> { when(regs) { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 2bc492e6f..69ce21186 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -4,6 +4,7 @@ TODO - see if we can group some errors together for instance the (now single) errors about unidentified symbols - Cx16 target: support full-screen 640x480 and 320x240 graphics? That requires our own custom graphics routines though to draw lines. +- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine) - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' - option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging) - use VIC banking to move up the graphics bitmap memory location. Move it to $e000 under the kernal rom? diff --git a/examples/test.p8 b/examples/test.p8 index 8b1d39e9e..3265ab6f5 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,44 +5,20 @@ %import test_stack %option no_sysinit -errors { - sub tofix() { - - -; ; TODO fix undefined symbol: -; repeat { -; ubyte char = c64.CHRIN() -; ; ... -; } -; do { -; char = c64.CHRIN() ; TODO fix undefined symbol error, should refer to 'char' above in the subroutine's scope -; } until char==0 - - str[4] names1 = ["one", "two", "three", "four"] - str[4] names2 - - names2[0] = "four" - names2[1] = "three" - names2[2] = "two" - names2[3] = "one" - - uword xx - for xx in names1 { - txt.print(xx) - txt.chrout(',') - } - txt.chrout('\n') - for xx in names2 { - txt.print(xx) - txt.chrout(',') - } - txt.chrout('\n') - } -} - main { sub start() { - errors.tofix() + ubyte[] barr = [0,0,0] + uword[] warr = [0,0,0] + + ubyte xx = 0 + barr[1] = xx+9 + warr[1] = &warr + + txt.print_ub(barr[1]) + txt.chrout('\n') + txt.print_uwhex(warr[1],1 ) + txt.chrout('\n') + test_stack.test() } }