optimized in-place memory/pointervar operations some more

This commit is contained in:
Irmen de Jong 2024-02-04 13:50:18 +01:00
parent 344a1b9eb8
commit 2cadb546d5
3 changed files with 53 additions and 5 deletions

View File

@ -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) {
"+" -> {

View File

@ -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()

View File

@ -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]