From e6079dfd718f8ad66ce3a6ff945ee4f6c7b75f60 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 27 Feb 2021 16:21:46 +0100 Subject: [PATCH] don't always use pha/pla in pointer expression code --- .../compiler/target/c64/codegen/AsmGen.kt | 61 ++++++++++--------- examples/test.p8 | 9 +++ 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index 712778aba..ef8da67a6 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -1407,39 +1407,44 @@ $label nop""") internal fun tryOptimizedPointerAccessWithA(expr: BinaryExpression, write: Boolean): Boolean { // optimize pointer,indexregister if possible + + fun evalBytevalueWillClobberA(expr: Expression): Boolean { + val dt = expr.inferType(program) + if(!dt.istype(DataType.UBYTE) && !dt.istype(DataType.BYTE)) + return true + return when(expr) { + is IdentifierReference -> false + is NumericLiteralValue -> false + is DirectMemoryRead -> expr.addressExpression !is IdentifierReference && expr.addressExpression !is NumericLiteralValue + is TypecastExpression -> evalBytevalueWillClobberA(expr.expression) + else -> true + } + } + + if(expr.operator=="+") { val ptrAndIndex = pointerViaIndexRegisterPossible(expr) if(ptrAndIndex!=null) { val pointervar = ptrAndIndex.first as? IdentifierReference if(write) { - when(ptrAndIndex.second) { - is NumericLiteralValue, is IdentifierReference -> { - if(pointervar!=null && isZpVar(pointervar)) { - out(" pha") - assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y) - out(" pla | sta (${asmSymbolName(pointervar)}),y") - } else { - // copy the pointer var to zp first - out(" pha") - assignExpressionToVariable(ptrAndIndex.first, asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null) - assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y) - out(" pla | sta (P8ZP_SCRATCH_W2),y") - } - } - else -> { - // same as above but we need to save the A register - if(pointervar!=null && isZpVar(pointervar)) { - out(" pha") - assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y) - out(" pla | sta (${asmSymbolName(pointervar)}),y") - } else { - // copy the pointer var to zp first - assignExpressionToVariable(ptrAndIndex.first, asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null) - out(" pha") - assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y) - out(" pla | sta (P8ZP_SCRATCH_W2),y") - } - } + if(pointervar!=null && isZpVar(pointervar)) { + val saveA = evalBytevalueWillClobberA(ptrAndIndex.second) + if(saveA) + out(" pha") + assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y) + if(saveA) + out(" pla") + out(" sta (${asmSymbolName(pointervar)}),y") + } else { + // copy the pointer var to zp first + val saveA = evalBytevalueWillClobberA(ptrAndIndex.first) || evalBytevalueWillClobberA(ptrAndIndex.second) + if(saveA) + out(" pha") + assignExpressionToVariable(ptrAndIndex.first, asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null) + assignExpressionToRegister(ptrAndIndex.second, RegisterOrPair.Y) + if(saveA) + out(" pla") + out(" sta (P8ZP_SCRATCH_W2),y") } } else { if(pointervar!=null && isZpVar(pointervar)) { diff --git a/examples/test.p8 b/examples/test.p8 index bf6c5f695..60c278389 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,6 +4,15 @@ main { sub start() { + uword screen = 2000 + ubyte i = 1 + uword w = 33 + str derp ="derp" + ubyte[] array = [1,2,3] + + @(screen+i) = 128 + @(i+screen) = 129 + txt.print("done\n") } }