mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
optimize pointer var access if var is already on zeropage
This commit is contained in:
parent
1481f92cb0
commit
40cc216557
@ -527,7 +527,7 @@ internal class AsmGen(private val program: Program,
|
||||
val vardecl = pointervar.targetVarDecl(program.namespace)!!
|
||||
val scopedName = vardecl.makeScopedName(vardecl.name)
|
||||
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) {
|
||||
return if (scopedName in allocatedZeropageVariables) {
|
||||
return if (isZpVar(scopedName)) {
|
||||
// pointervar is already in the zero page, no need to copy
|
||||
out(" lda ($sourceName)")
|
||||
Pair(true, sourceName)
|
||||
@ -541,7 +541,7 @@ internal class AsmGen(private val program: Program,
|
||||
Pair(false, sourceName)
|
||||
}
|
||||
} else {
|
||||
return if (scopedName in allocatedZeropageVariables) {
|
||||
return if (isZpVar(scopedName)) {
|
||||
// pointervar is already in the zero page, no need to copy
|
||||
out(" ldy #0 | lda ($sourceName),y")
|
||||
Pair(true, sourceName)
|
||||
@ -563,7 +563,7 @@ internal class AsmGen(private val program: Program,
|
||||
val vardecl = pointervar.targetVarDecl(program.namespace)!!
|
||||
val scopedName = vardecl.makeScopedName(vardecl.name)
|
||||
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) {
|
||||
if (scopedName in allocatedZeropageVariables) {
|
||||
if (isZpVar(scopedName)) {
|
||||
// pointervar is already in the zero page, no need to copy
|
||||
if (ldaInstructionArg != null)
|
||||
out(" lda $ldaInstructionArg")
|
||||
@ -578,7 +578,7 @@ internal class AsmGen(private val program: Program,
|
||||
sta (P8ZP_SCRATCH_W2)""")
|
||||
}
|
||||
} else {
|
||||
if (scopedName in allocatedZeropageVariables) {
|
||||
if (isZpVar(scopedName)) {
|
||||
// pointervar is already in the zero page, no need to copy
|
||||
if (ldaInstructionArg != null)
|
||||
out(" lda $ldaInstructionArg")
|
||||
@ -1362,4 +1362,11 @@ $label nop""")
|
||||
else -> throw AssemblyError("need byte type")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun isZpVar(scopedName: String): Boolean = scopedName in allocatedZeropageVariables
|
||||
|
||||
internal fun isZpVar(variable: IdentifierReference): Boolean {
|
||||
val vardecl = variable.targetVarDecl(program.namespace)!!
|
||||
return vardecl.makeScopedName(vardecl.name) in allocatedZeropageVariables
|
||||
}
|
||||
}
|
||||
|
@ -1483,12 +1483,23 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
val idref = expr.left as? IdentifierReference
|
||||
if(idref!=null && asmgen.isZpVar(idref)) {
|
||||
// pointer var is already in zp, we can indirect index immediately
|
||||
if (pushResultOnEstack) {
|
||||
asmgen.out(" dex | ldy #${intIndex} | lda (${asmgen.asmSymbolName(idref)}),y | sta P8ESTACK_LO+1,x")
|
||||
} else {
|
||||
asmgen.out(" ldy #${intIndex} | lda (${asmgen.asmSymbolName(idref)}),y")
|
||||
}
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
asmgen.assignExpressionToVariable(expr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
if (pushResultOnEstack) {
|
||||
asmgen.out(" dex | ldy #${intIndex} | lda (P8ZP_SCRATCH_W2),y | sta P8ESTACK_LO+1,x")
|
||||
} else {
|
||||
asmgen.out(" ldy #${intIndex} | lda (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -129,8 +129,15 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
val idref = expr.left as? IdentifierReference
|
||||
if(idref!=null && asmgen.isZpVar(idref)) {
|
||||
// pointer var is already in zp, we can indirect index immediately
|
||||
asmgen.out(" ldy #${intIndex} | lda (${asmgen.asmSymbolName(idref)}),y")
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
assignExpressionToVariable(expr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, assign.target.scope)
|
||||
asmgen.out(" ldy #${intIndex} | lda (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
return true
|
||||
}
|
||||
@ -1978,8 +1985,15 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
val idref = expr.left as? IdentifierReference
|
||||
if(idref!=null && asmgen.isZpVar(idref)) {
|
||||
// pointer var is already in zp, we can indirect index immediately
|
||||
asmgen.out(" lda $ldaInstructionArg | ldy #${intIndex} | sta (${asmgen.asmSymbolName(idref)}),y")
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
assignExpressionToVariable(expr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
asmgen.out(" lda $ldaInstructionArg | ldy #${intIndex} | sta (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -2026,10 +2040,21 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
val idref = expr.left as? IdentifierReference
|
||||
if(idref!=null && asmgen.isZpVar(idref)) {
|
||||
// pointer var is already in zp, we can indirect index immediately
|
||||
when(register) {
|
||||
CpuRegister.A -> asmgen.out(" ldy #${intIndex} | sta (${asmgen.asmSymbolName(idref)}),y")
|
||||
CpuRegister.X -> asmgen.out(" txa | ldy #${intIndex} | sta (${asmgen.asmSymbolName(idref)}),y")
|
||||
CpuRegister.Y -> asmgen.out(" tya | ldy #${intIndex} | sta (${asmgen.asmSymbolName(idref)}),y")
|
||||
}
|
||||
} else {
|
||||
// copy the pointer var to zp first
|
||||
asmgen.saveRegisterStack(register, false)
|
||||
assignExpressionToVariable(expr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||
asmgen.out(" ldy #${intIndex} | sta (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- optimize pointer access if it's via a var that's already in ZP. in AssignmentAsmGen 3 times,
|
||||
and in translateDirectMemReadExpression. like loadByteFromPointerIntoA() is doing.
|
||||
- why is fibonacci example (and others) generating larger code now? fix?
|
||||
- can we get rid of the --longOptionName command line options and only keep the short versions? https://github.com/Kotlin/kotlinx-cli/issues/50
|
||||
- add a f_seek() routine for the Cx16 that uses its seek dos api?
|
||||
- add a compiler option to generate a symbol listing at the end
|
||||
- optimizer: detect variables that are written but never read - mark those as unused too and remove them, such as uword unused = memory("unused222", 20) - also remove the memory slab allocation
|
||||
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
|
||||
|
@ -24,7 +24,6 @@ main {
|
||||
txt.nl()
|
||||
|
||||
cc=0
|
||||
|
||||
txt.chrout(@(ptr)+cc)
|
||||
txt.chrout(@(ptr+1)+cc)
|
||||
txt.chrout(@(ptr+2)+cc)
|
||||
|
Loading…
Reference in New Issue
Block a user