diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index b37a7d491..8ea5bb3fd 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -1384,6 +1384,22 @@ internal class AssignmentAsmGen(private val program: Program, storeRegisterAInMemoryAddress(target.memory!!) } TargetStorageKind.ARRAY -> { + if(target.origAstTarget?.arrayindexed?.arrayvar?.targetVarDecl(program)?.datatype==DataType.UWORD) { + // assigning an indexed pointer var + if (target.constArrayIndexValue==0u) { + asmgen.out(" lda $sourceName") + asmgen.storeAIntoPointerVar(target.origAstTarget.arrayindexed!!.arrayvar) + } else { + asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y) + if (asmgen.isZpVar(target.origAstTarget.arrayindexed!!.arrayvar)) { + asmgen.out(" lda $sourceName | sta (${target.asmVarname}),y") + } else { + asmgen.out(" lda ${target.asmVarname} | sta P8ZP_SCRATCH_W2 | lda ${target.asmVarname}+1 | sta P8ZP_SCRATCH_W2+1") + asmgen.out(" lda $sourceName | sta (P8ZP_SCRATCH_W2),y") + } + } + return + } if (target.constArrayIndexValue!=null) { val scaledIdx = target.constArrayIndexValue!! * program.memsizer.memorySize(target.datatype).toUInt() asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx") @@ -1916,6 +1932,22 @@ internal class AssignmentAsmGen(private val program: Program, storeRegisterAInMemoryAddress(target.memory!!) } TargetStorageKind.ARRAY -> { + if(target.origAstTarget?.arrayindexed?.arrayvar?.targetVarDecl(program)?.datatype==DataType.UWORD) { + // assigning an indexed pointer var + if (target.constArrayIndexValue==0u) { + asmgen.out(" lda #0") + asmgen.storeAIntoPointerVar(target.origAstTarget.arrayindexed!!.arrayvar) + } else { + asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y) + if (asmgen.isZpVar(target.origAstTarget.arrayindexed!!.arrayvar)) { + asmgen.out(" lda #0 | sta (${target.asmVarname}),y") + } else { + asmgen.out(" lda ${target.asmVarname} | sta P8ZP_SCRATCH_W2 | lda ${target.asmVarname}+1 | sta P8ZP_SCRATCH_W2+1") + asmgen.out(" lda #0 | sta (P8ZP_SCRATCH_W2),y") + } + } + return + } if (target.constArrayIndexValue!=null) { val indexValue = target.constArrayIndexValue!! asmgen.out(" stz ${target.asmVarname}+$indexValue") @@ -1959,13 +1991,29 @@ internal class AssignmentAsmGen(private val program: Program, storeRegisterAInMemoryAddress(target.memory!!) } TargetStorageKind.ARRAY -> { + if(target.origAstTarget?.arrayindexed?.arrayvar?.targetVarDecl(program)?.datatype==DataType.UWORD) { + // assigning an indexed pointer var + if (target.constArrayIndexValue==0u) { + asmgen.out(" lda #${byte.toHex()}") + asmgen.storeAIntoPointerVar(target.origAstTarget.arrayindexed!!.arrayvar) + } else { + asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y) + if (asmgen.isZpVar(target.origAstTarget.arrayindexed!!.arrayvar)) { + asmgen.out(" lda #${byte.toHex()} | sta (${target.asmVarname}),y") + } else { + asmgen.out(" lda ${target.asmVarname} | sta P8ZP_SCRATCH_W2 | lda ${target.asmVarname}+1 | sta P8ZP_SCRATCH_W2+1") + asmgen.out(" lda #${byte.toHex()} | sta (P8ZP_SCRATCH_W2),y") + } + } + return + } if (target.constArrayIndexValue!=null) { val indexValue = target.constArrayIndexValue!! asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname}+$indexValue") } else { asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y) - asmgen.out(" lda #<${byte.toHex()} | sta ${target.asmVarname},y") + asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname},y") } } TargetStorageKind.REGISTER -> when(target.register!!) { diff --git a/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt b/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt index 436f2eba8..11ef786f4 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt @@ -2,10 +2,9 @@ package prog8.compiler.astprocessing import prog8.ast.Node import prog8.ast.Program -import prog8.ast.expressions.ArrayIndexedExpression -import prog8.ast.expressions.BinaryExpression -import prog8.ast.expressions.Expression +import prog8.ast.expressions.* import prog8.ast.statements.AssignTarget +import prog8.ast.statements.Assignment import prog8.ast.statements.DirectMemoryWrite import prog8.ast.statements.VarDecl import prog8.ast.walk.AstWalker @@ -31,13 +30,19 @@ internal class AstOnetimeTransforms(private val program: Program, private val op private fun replacePointerVarIndexWithMemreadOrMemwrite(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable { if(options.compTarget.name== VMTarget.NAME) - return noModifications + return noModifications // vm codegen deals correctly with all cases val arrayVar = arrayIndexedExpression.arrayvar.targetVarDecl(program) if(arrayVar!=null && arrayVar.datatype == DataType.UWORD) { if(parent is AssignTarget) { - // rewrite assignment target pointervar[index] into @(pointervar+index) - //println("REWRITE POINTER INDEXED: ${arrayVar.name}[${arrayIndexedExpression.indexer.indexExpr}] as assignment target at ${parent.position}") // TODO + val assignment = parent.parent as? Assignment + if(assignment?.value is NumericLiteral || assignment?.value is IdentifierReference) { + // ONLY for a constant assignment, or direct variable assignment, the codegen contains correct optimized code. + return noModifications + } + // Other cases aren't covered correctly by the 6502 codegen, and there are a LOT of cases. + // So rewrite assignment target pointervar[index] into @(pointervar+index) + // (the 6502 codegen covers all cases correctly for a direct memory assignment). val indexer = arrayIndexedExpression.indexer val add: Expression = if(indexer.indexExpr.constValue(program)?.number==0.0) diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 60ae3b42f..f44c44440 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,6 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- 6502: fix optimized pointervar indexing codegen when it is an assignment target (i.e. writing to ptr[ix]) - pipe operator: (targets other than 'Virtual'): allow non-unary function calls in the pipe that specify the other argument(s) in the calls. Already working for VM target. - add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value? - Inliner: also inline function call expressions, and remove it from the StatementOptimizer diff --git a/examples/test.p8 b/examples/test.p8 index 9008a21de..ffe552870 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -40,32 +40,32 @@ main { uword bitmapbuf = &data ; 11 22 33 -; txt.print_ub(bitmapbuf[0]) -; txt.spc() -; txt.print_ub(bitmapbuf[1]) -; txt.spc() -; txt.print_ub(bitmapbuf[2]) -; txt.nl() -; rol(bitmapbuf[0]) -; rol(bitmapbuf[0]) -; txt.print_ub(bitmapbuf[0]) ; 44 -; txt.spc() -; ror(bitmapbuf[0]) -; ror(bitmapbuf[0]) -; txt.print_ub(bitmapbuf[0]) ; 11 -; txt.nl() -; -; ; 22 44 66 -; txt.print_ub(bitmapbuf[0]*2) -; txt.spc() -; txt.print_ub(bitmapbuf[1]*2) -; txt.spc() -; txt.print_ub(bitmapbuf[2]*2) -; txt.nl() -; -; value = one+one+one+one+one -; txt.print_ub(value) ; 5 -; txt.nl() + txt.print_ub(bitmapbuf[0]) + txt.spc() + txt.print_ub(bitmapbuf[1]) + txt.spc() + txt.print_ub(bitmapbuf[2]) + txt.nl() + rol(bitmapbuf[0]) + rol(bitmapbuf[0]) + txt.print_ub(bitmapbuf[0]) ; 44 + txt.spc() + ror(bitmapbuf[0]) + ror(bitmapbuf[0]) + txt.print_ub(bitmapbuf[0]) ; 11 + txt.nl() + + ; 22 44 66 + txt.print_ub(bitmapbuf[0]*2) + txt.spc() + txt.print_ub(bitmapbuf[1]*2) + txt.spc() + txt.print_ub(bitmapbuf[2]*2) + txt.nl() + + value = one+one+one+one+one + txt.print_ub(value) ; 5 + txt.nl() bitmapbuf[0] = one+one+one bitmapbuf[0] = one+one+one @@ -76,6 +76,7 @@ main { bitmapbuf[2] = one bitmapbuf[2] = one bitmapbuf[2] = one + bitmapbuf[3] = 42 bitmapbuf[2] += 100 bitmapbuf[2] -= 1 bitmapbuf[2] -= 1 @@ -91,7 +92,7 @@ main { txt.nl() for value in data { - txt.print_ub(value) ; 3 2 97 4 5 6 7 8 9 10 + txt.print_ub(value) ; 3 2 97 42 5 6 7 8 9 10 txt.spc() } txt.nl()