diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index ec0e45723..fe29ad2b8 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -72,6 +72,23 @@ internal class AssignmentAsmGen(private val program: Program, val value = assign.source.array!! val elementDt = assign.source.datatype val arrayVarName = asmgen.asmVariableName(value.arrayvar) + + val arrayVarDecl = value.arrayvar.targetVarDecl(program)!! + if(arrayVarDecl.datatype==DataType.UWORD) { + // indexing a pointer var instead of a real array or string + if(elementDt !in ByteDatatypes) + throw AssemblyError("non-array var indexing requires bytes dt") + asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y) + if(asmgen.isZpVar(value.arrayvar)) { + asmgen.out(" lda ($arrayVarName),y") + } else { + asmgen.out(" lda $arrayVarName | sta P8ZP_SCRATCH_W1 | lda $arrayVarName+1 | sta P8ZP_SCRATCH_W1+1") + asmgen.out(" lda (P8ZP_SCRATCH_W1),y") + } + assignRegisterByte(assign.target, CpuRegister.A) + return + } + val constIndex = value.indexer.constIndex() if (constIndex!=null) { // constant array index value diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index ccd890588..241ea6969 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -149,6 +149,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) { val code = VmCodeChunk() val idxReg = codeGen.vmRegisters.nextFree() val arrayLocation = codeGen.allocations.get(arrayIx.variable.targetName) + + if(arrayIx.variable.type==DataType.UWORD) { + // indexing a pointer var instead of a real array or string + if(eltSize!=1) + throw AssemblyError("non-array var indexing requires bytes dt") + val pointerReg = codeGen.vmRegisters.nextFree() + code += translateExpression(arrayIx.index, idxReg, -1) + // TODO introduce LOADIX instruction to skip the ADD (requires 3 registers) + code += VmCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1=pointerReg, value=arrayLocation) + code += VmCodeInstruction(Opcode.ADD, VmDataType.WORD, reg1=pointerReg, reg2=idxReg) + code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1=resultRegister, reg2=pointerReg) + return code + } + if(arrayIx.index is PtNumber) { // optimized code when index is known - just calculate the memory address here val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize diff --git a/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt b/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt index f3d9c9e0e..d3a836961 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstOnetimeTransforms.kt @@ -45,13 +45,11 @@ internal class AstOnetimeTransforms(private val program: Program) : AstWalker() return if(fcall!=null) { val fname = fcall.target.nameInSource if(fname.size==1 && fname[0] in InplaceModifyingBuiltinFunctions) { - // TODO for now, swap() etc don't work on pointer var indexed args + // TODO for now, swap() etc don't work on pointer var indexed args, so still replace this val memread = DirectMemoryRead(add, arrayIndexedExpression.position) listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent)) } else { - // TODO first candidate for optimization is to remove this: - val memread = DirectMemoryRead(add, arrayIndexedExpression.position) - listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent)) + noModifications } } else { val memread = DirectMemoryRead(add, arrayIndexedExpression.position) diff --git a/examples/test.p8 b/examples/test.p8 index 45b28e7ff..2c1705f5f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,5 +1,5 @@ %import textio -%zeropage dontuse +%zeropage basicsafe ; NOTE: meant to test to virtual machine output target (use -target vitual)