From 2cadb546d56adf2f00c943f077f31d7ce3f5bd26 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 4 Feb 2024 13:50:18 +0100 Subject: [PATCH] optimized in-place memory/pointervar operations some more --- .../assignment/AugmentableAssignmentAsmGen.kt | 44 +++++++++++++++++++ docs/source/todo.rst | 1 - examples/test.p8 | 13 ++++-- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt index 636579afd..393fc0e79 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AugmentableAssignmentAsmGen.kt @@ -163,6 +163,8 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, } } else -> { + if(memory.address is PtBinaryExpression && tryOptimizedMemoryInplace(memory.address as PtBinaryExpression, operator, value)) + return asmgen.assignExpressionToRegister(memory.address, RegisterOrPair.AY, false) asmgen.saveRegisterStack(CpuRegister.A, true) asmgen.saveRegisterStack(CpuRegister.Y, true) @@ -474,6 +476,48 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram, } } + private fun tryOptimizedMemoryInplace(address: PtBinaryExpression, operator: String, value: AsmAssignSource): Boolean { + if(value.datatype !in ByteDatatypes || operator !in "|&^+-") + return false + val rightTc = address.right as? PtTypeCast + val constOffset = (address.right as? PtNumber)?.number?.toInt() + if(address.operator=="+" && (address.right.type in ByteDatatypes || (rightTc!=null && rightTc.value.type in ByteDatatypes) || (constOffset!=null && constOffset<256)) ) { + if(rightTc!=null) + asmgen.assignExpressionToRegister(rightTc.value, RegisterOrPair.A, false) + else if(constOffset!=null) + asmgen.out(" lda #${constOffset}") + else + asmgen.assignExpressionToRegister(address.right, RegisterOrPair.A, false) + asmgen.out(" pha") // offset on stack + val zpPointerVarName: String + if(address.left is PtIdentifier && asmgen.isZpVar(address.left as PtIdentifier)) { + zpPointerVarName = (address.left as PtIdentifier).name + } else { + zpPointerVarName = "P8ZP_SCRATCH_W2" + asmgen.assignExpressionToRegister(address.left, RegisterOrPair.AY, false) + asmgen.out(" sta $zpPointerVarName | sty $zpPointerVarName+1") + } + // calculate value into A + val assignValue = AsmAssignment(value, + AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, DataType.UBYTE, + address.definingISub(), Position.DUMMY, register = RegisterOrPair.A), + program.memsizer, Position.DUMMY) + assignmentAsmGen.translateNormalAssignment(assignValue, address.definingISub()) + asmgen.restoreRegisterStack(CpuRegister.Y, false) // offset into Y + when(operator) { + "|" -> asmgen.out(" ora ($zpPointerVarName),y") + "&" -> asmgen.out(" and ($zpPointerVarName),y") + "^" -> asmgen.out(" eor ($zpPointerVarName),y") + "+" -> asmgen.out(" clc | adc ($zpPointerVarName),y") + "-" -> asmgen.out(" sta P8ZP_SCRATCH_REG | lda ($zpPointerVarName),y | sec | sbc P8ZP_SCRATCH_REG") + else -> throw AssemblyError("invalid op") + } + asmgen.out(" sta ($zpPointerVarName),y") + return true + } + return false + } + private fun inplacemodificationSplitWordWithR0(arrayVar: String, index: Int, operator: String) { when (operator) { "+" -> { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 61b777273..097d9584d 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -43,7 +43,6 @@ Compiler: Once new codegen is written that is based on the IR, this point is mostly moot anyway as that will have its own dead code removal on the IR level. - Zig-like try-based error handling where the V flag could indicate error condition? and/or BRK to jump into monitor on failure? (has to set BRK vector for that) But the V flag is also set on certain normal instructions - generate WASM to eventually run prog8 on a browser canvas? Use binaryen toolkit and/or my binaryen kotlin library? -- add Vic20 target? - split words arrays all() - split words arrays sort() diff --git a/examples/test.p8 b/examples/test.p8 index 903b0fd2f..06575e3d2 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -11,10 +11,15 @@ main { uword @shared az = $4000 ubyte @shared value = 22 - az[20] = 99 - az[2000] = 99 - az[value] = 99 - az[cx16.r0] = 99 + az[20] |= 99 + az[21] &= 99 + az[22] ^= 99 + az[23] += 99 + az[24] -= 99 +; az[2000] |= 99 +; az[value] |= 99 +; az[cx16.r0] |= 99 + ; cx16.r0L = az[200] ; cx16.r1L = az[2000] ; cx16.r0L = az[value]