From 9bb16e293cb7c5a7bf7a81b5313ba9d7747faae0 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 31 Jul 2023 19:35:57 +0200 Subject: [PATCH] vm: fix postincr/decr on indexed pointervariables --- codeCore/src/prog8/code/ast/AstExpressions.kt | 3 ++ .../cpu6502/assignment/AssignmentAsmGen.kt | 34 +++++++++---------- .../codegen/intermediate/AssignmentGen.kt | 3 +- .../codegen/intermediate/ExpressionGen.kt | 3 +- .../prog8/codegen/intermediate/IRCodeGen.kt | 26 +++++++++++--- examples/test.p8 | 26 ++++++++------ 6 files changed, 58 insertions(+), 37 deletions(-) diff --git a/codeCore/src/prog8/code/ast/AstExpressions.kt b/codeCore/src/prog8/code/ast/AstExpressions.kt index 472c0d2a8..8a46a8227 100644 --- a/codeCore/src/prog8/code/ast/AstExpressions.kt +++ b/codeCore/src/prog8/code/ast/AstExpressions.kt @@ -118,6 +118,9 @@ class PtArrayIndexer(elementType: DataType, position: Position): PtExpression(el val splitWords: Boolean get() = variable.type in SplitWordArrayTypes + val usesPointerVariable: Boolean + get() = variable.type==DataType.UWORD + init { require(elementType in NumericDatatypes) } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 175037976..0f4b9cb1b 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -61,8 +61,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, val elementDt = assign.source.datatype val arrayVarName = asmgen.asmVariableName(value.variable) - if(value.variable.type==DataType.UWORD) { - // indexing a pointer var instead of a real array or string + if(value.usesPointerVariable) { if(elementDt !in ByteDatatypes) throw AssemblyError("non-array var indexing requires bytes dt") if(value.type != DataType.UBYTE) @@ -2267,14 +2266,13 @@ internal class AssignmentAsmGen(private val program: PtProgram, storeRegisterAInMemoryAddress(target.memory!!) } TargetStorageKind.ARRAY -> { - if(target.origAstTarget?.array?.variable?.type==DataType.UWORD) { - // assigning an indexed pointer var + if(assignsIndexedPointerVar(target)) { if (target.constArrayIndexValue==0u) { asmgen.out(" lda $sourceName") - asmgen.storeAIntoPointerVar(target.origAstTarget.array!!.variable) + asmgen.storeAIntoPointerVar(target.origAstTarget!!.array!!.variable) } else { asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y) - if (asmgen.isZpVar(target.origAstTarget.array!!.variable)) { + if (asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) { 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") @@ -2489,8 +2487,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, TODO("assign register as word into Array not yet supported") if(target.array!!.splitWords) TODO("assign register into split words ${target.position}") - if(target.origAstTarget?.array?.variable?.type==DataType.UWORD) { - // assigning an indexed pointer var + if(assignsIndexedPointerVar(target)) { if (target.constArrayIndexValue!=null) { when (register) { CpuRegister.A -> {} @@ -2515,7 +2512,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, CpuRegister.X -> asmgen.out(" txa") CpuRegister.Y -> asmgen.out(" tya") } - val indexVar = target.array!!.index as PtIdentifier + val indexVar = target.array.index as PtIdentifier if(asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) { asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta (${target.asmVarname}),y") } else { @@ -2545,7 +2542,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, CpuRegister.X -> asmgen.out(" txa") CpuRegister.Y -> asmgen.out(" tya") } - val indexVar = target.array!!.index as PtIdentifier + val indexVar = target.array.index as PtIdentifier asmgen.out(" ldy ${asmgen.asmVariableName(indexVar)} | sta ${target.asmVarname},y") } } @@ -2987,14 +2984,13 @@ internal class AssignmentAsmGen(private val program: PtProgram, storeRegisterAInMemoryAddress(target.memory!!) } TargetStorageKind.ARRAY -> { - if(target.origAstTarget?.array?.variable?.type==DataType.UWORD) { - // assigning an indexed pointer var + if(assignsIndexedPointerVar(target)) { if (target.constArrayIndexValue==0u) { asmgen.out(" lda #0") - asmgen.storeAIntoPointerVar(target.origAstTarget.array!!.variable) + asmgen.storeAIntoPointerVar(target.origAstTarget!!.array!!.variable) } else { asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y) - if (asmgen.isZpVar(target.origAstTarget.array!!.variable)) { + if (asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) { 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") @@ -3042,14 +3038,13 @@ internal class AssignmentAsmGen(private val program: PtProgram, storeRegisterAInMemoryAddress(target.memory!!) } TargetStorageKind.ARRAY -> { - if(target.origAstTarget?.array?.variable?.type==DataType.UWORD) { - // assigning an indexed pointer var + if(assignsIndexedPointerVar(target)) { if (target.constArrayIndexValue==0u) { asmgen.out(" lda #${byte.toHex()}") - asmgen.storeAIntoPointerVar(target.origAstTarget.array!!.variable) + asmgen.storeAIntoPointerVar(target.origAstTarget!!.array!!.variable) } else { asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y) - if (asmgen.isZpVar(target.origAstTarget.array!!.variable)) { + if (asmgen.isZpVar(target.origAstTarget!!.array!!.variable)) { 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") @@ -3095,6 +3090,9 @@ internal class AssignmentAsmGen(private val program: PtProgram, } } + private fun assignsIndexedPointerVar(target: AsmAssignTarget): Boolean = + target.origAstTarget?.array?.variable?.type==DataType.UWORD + internal fun assignConstantFloat(target: AsmAssignTarget, float: Double) { if (float == 0.0) { // optimized case for float zero diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index d9fc18a21..92d8fbaf8 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -198,8 +198,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express val variable = targetArray.variable.name val itemsize = codeGen.program.memsizer.memorySize(targetArray.type) - if(targetArray.variable.type==DataType.UWORD) { - // indexing a pointer var instead of a real array or string + if(targetArray.usesPointerVariable) { if(itemsize!=1) throw AssemblyError("non-array var indexing requires bytes dt") if(targetArray.index.type!=DataType.UBYTE) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 7684c8a88..3848552c0 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -147,8 +147,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { val result = mutableListOf() val arrayVarSymbol = arrayIx.variable.name - if(arrayIx.variable.type==DataType.UWORD) { - // indexing a pointer var instead of a real array or string + if(arrayIx.usesPointerVariable) { if(eltSize!=1) throw AssemblyError("non-array var indexing requires bytes dt") if(arrayIx.index.type!=DataType.UBYTE) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index 11c620ff7..5dfd573b0 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -1469,7 +1469,19 @@ class IRCodeGen( val fixedIndex = constIntValue(array.index) if(fixedIndex!=null) { val offset = fixedIndex*itemsize - addInstr(result, IRInstruction(operationMem, irDt, labelSymbol="$variable+$offset"), null) + val indexReg = registers.nextFree() + val dataReg = registers.nextFree() + if(array.usesPointerVariable) { + // we don't have an indirect dec/inc so do it via an intermediate register + result += IRCodeChunk(null,null).also { + it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = indexReg, immediate = offset) + it += IRInstruction(Opcode.LOADIX, irDt, reg1 = dataReg, reg2 = indexReg, labelSymbol = variable) + it += IRInstruction(operationRegister, irDt, reg1=dataReg) + it += IRInstruction(Opcode.STOREIX, irDt, reg1 = dataReg, reg2 = indexReg, labelSymbol = variable) + } + } else { + addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = "$variable+$offset"), null) + } } else { val indexTr = expressionEval.translateExpression(array.index) addToResult(result, indexTr, indexTr.resultReg, -1) @@ -1477,9 +1489,15 @@ class IRCodeGen( result += multiplyByConst(IRDataType.BYTE, indexTr.resultReg, itemsize) result += IRCodeChunk(null, null).also { val incReg = registers.nextFree() - it += IRInstruction(Opcode.LOADX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable) - it += IRInstruction(operationRegister, irDt, reg1=incReg) - it += IRInstruction(Opcode.STOREX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable) + if(array.usesPointerVariable) { + it += IRInstruction(Opcode.LOADIX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable) + it += IRInstruction(operationRegister, irDt, reg1=incReg) + it += IRInstruction(Opcode.STOREIX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable) + } else { + it += IRInstruction(Opcode.LOADX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable) + it += IRInstruction(operationRegister, irDt, reg1=incReg) + it += IRInstruction(Opcode.STOREX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable) + } } } } else diff --git a/examples/test.p8 b/examples/test.p8 index 681d459c2..be9105b27 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,16 +1,20 @@ %import textio -%zeropage basicsafe main { - sub start() { - ubyte var = 0 + ubyte[2] data = [100, 100] + uword dRef = &data - when var { - 1 -> txt.print("one") - 2 -> txt.print("two") - 0 -> { - } - else -> txt.print("other") - } - } + sub start() { + dRef[0]-- + dRef[1]++ + + cx16.r0L = 0 + cx16.r1L = 1 + dRef[cx16.r0L]-- + dRef[cx16.r1L]++ + + txt.print_ub(data[0]) + txt.spc() + txt.print_ub(data[1]) + } }