fixed and optimized pointervar indexed in-place operations

This commit is contained in:
Irmen de Jong 2024-03-11 23:13:32 +01:00
parent e63a8f0c01
commit 820541e427
4 changed files with 186 additions and 41 deletions

View File

@ -382,21 +382,18 @@ private fun optimizeStoreLoadSame(
machine: IMachineDefinition, machine: IMachineDefinition,
symbolTable: SymbolTable symbolTable: SymbolTable
): List<Modification> { ): List<Modification> {
// sta X + lda X, sty X + ldy X, stx X + ldx X -> the second instruction can OFTEN be eliminated
val mods = mutableListOf<Modification>() val mods = mutableListOf<Modification>()
for (lines in linesByFour) { for (lines in linesByFour) {
val first = lines[1].value.trimStart() val first = lines[1].value.trimStart()
val second = lines[2].value.trimStart() val second = lines[2].value.trimStart()
// sta X + lda X, sty X + ldy X, stx X + ldx X -> the second instruction can OFTEN be eliminated
if ((first.startsWith("sta ") && second.startsWith("lda ")) || if ((first.startsWith("sta ") && second.startsWith("lda ")) ||
(first.startsWith("stx ") && second.startsWith("ldx ")) || (first.startsWith("stx ") && second.startsWith("ldx ")) ||
(first.startsWith("sty ") && second.startsWith("ldy ")) || (first.startsWith("sty ") && second.startsWith("ldy ")) ||
(first.startsWith("lda ") && second.startsWith("lda ")) || (first.startsWith("lda ") && second.startsWith("lda ")) ||
(first.startsWith("ldy ") && second.startsWith("ldy ")) || (first.startsWith("ldy ") && second.startsWith("ldy ")) ||
(first.startsWith("ldx ") && second.startsWith("ldx ")) || (first.startsWith("ldx ") && second.startsWith("ldx "))
(first.startsWith("sta ") && second.startsWith("lda ")) ||
(first.startsWith("sty ") && second.startsWith("ldy ")) ||
(first.startsWith("stx ") && second.startsWith("ldx "))
) { ) {
val third = lines[3].value.trimStart() val third = lines[3].value.trimStart()
val attemptRemove = val attemptRemove =
@ -439,6 +436,18 @@ private fun optimizeStoreLoadSame(
mods.add(Modification(lines[1].index, true, null)) mods.add(Modification(lines[1].index, true, null))
mods.add(Modification(lines[2].index, false, " tya")) mods.add(Modification(lines[2].index, false, " tya"))
} }
// lda X + sta X, ldy X + sty X, ldx X + stx X -> the second instruction can be eliminated
if ((first.startsWith("lda ") && second.startsWith("sta ")) ||
(first.startsWith("ldx ") && second.startsWith("stx ")) ||
(first.startsWith("ldy ") && second.startsWith("sty "))
) {
val firstLoc = first.substring(4).trimStart()
val secondLoc = second.substring(4).trimStart()
if (firstLoc == secondLoc)
mods.add(Modification(lines[2].index, true, null))
}
} }
return mods return mods
} }
@ -485,6 +494,7 @@ private fun optimizeIncDec(linesByFour: Sequence<List<IndexedValue<String>>>): L
mods.add(Modification(lines[0].index, true, null)) mods.add(Modification(lines[0].index, true, null))
mods.add(Modification(lines[1].index, true, null)) mods.add(Modification(lines[1].index, true, null))
} }
} }
return mods return mods
} }

View File

@ -570,31 +570,68 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
private fun tryOptimizedMemoryInplace(address: PtBinaryExpression, operator: String, value: AsmAssignSource): Boolean { private fun tryOptimizedMemoryInplace(address: PtBinaryExpression, operator: String, value: AsmAssignSource): Boolean {
if(value.datatype !in ByteDatatypes || operator !in "|&^+-") if(value.datatype !in ByteDatatypes || operator !in "|&^+-")
return false return false
val rightTc = address.right as? PtTypeCast
val constOffset = (address.right as? PtNumber)?.number?.toInt() fun addrIntoZpPointer(): String {
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)) { if(address.left is PtIdentifier && asmgen.isZpVar(address.left as PtIdentifier)) {
zpPointerVarName = (address.left as PtIdentifier).name return (address.left as PtIdentifier).name
} else { } else {
zpPointerVarName = "P8ZP_SCRATCH_W2"
asmgen.assignExpressionToRegister(address.left, RegisterOrPair.AY, false) asmgen.assignExpressionToRegister(address.left, RegisterOrPair.AY, false)
asmgen.out(" sta $zpPointerVarName | sty $zpPointerVarName+1") asmgen.out(" sta P8ZP_SCRATCH_W2 | sty P8ZP_SCRATCH_W2+1")
return "P8ZP_SCRATCH_W2"
} }
// calculate value into A }
fun assignValueToA() {
val assignValue = AsmAssignment(value, val assignValue = AsmAssignment(value,
AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, DataType.UBYTE, AsmAssignTarget(TargetStorageKind.REGISTER, asmgen, DataType.UBYTE,
address.definingISub(), Position.DUMMY, register = RegisterOrPair.A), address.definingISub(), Position.DUMMY, register = RegisterOrPair.A),
program.memsizer, Position.DUMMY) program.memsizer, Position.DUMMY)
assignmentAsmGen.translateNormalAssignment(assignValue, address.definingISub()) assignmentAsmGen.translateNormalAssignment(assignValue, address.definingISub()) // calculate value into A
asmgen.restoreRegisterStack(CpuRegister.Y, false) // offset into Y }
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(constOffset!=null) {
val zpPointerVarName = addrIntoZpPointer()
if(value.number==null) assignValueToA()
asmgen.out(" ldy #$constOffset")
when(operator) {
"|" -> {
if(value.number!=null) asmgen.out(" lda #${value.number.number.toInt()}")
asmgen.out(" ora ($zpPointerVarName),y")
}
"&" -> {
if(value.number!=null) asmgen.out(" lda #${value.number.number.toInt()}")
asmgen.out(" and ($zpPointerVarName),y")
}
"^" -> {
if(value.number!=null) asmgen.out(" lda #${value.number.number.toInt()}")
asmgen.out(" eor ($zpPointerVarName),y")
}
"+" -> {
// note: there is no inc (ZP),y instruction...
if (value.number != null) asmgen.out(" lda #${value.number.number.toInt()}")
asmgen.out(" clc | adc ($zpPointerVarName),y")
}
"-" -> {
// note: there is no dec (ZP),y instruction...
if (value.number != null) asmgen.out(" lda ($zpPointerVarName),y | sec | sbc #${value.number.number.toInt()}")
else 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
}
if(rightTc!=null)
asmgen.assignExpressionToRegister(rightTc.value, RegisterOrPair.A, false)
else
asmgen.assignExpressionToRegister(address.right, RegisterOrPair.A, false)
asmgen.out(" pha") // offset on stack
val zpPointerVarName = addrIntoZpPointer()
assignValueToA()
asmgen.restoreRegisterStack(CpuRegister.Y, true) // offset from stack back into Y
when(operator) { when(operator) {
"|" -> asmgen.out(" ora ($zpPointerVarName),y") "|" -> asmgen.out(" ora ($zpPointerVarName),y")
"&" -> asmgen.out(" and ($zpPointerVarName),y") "&" -> asmgen.out(" and ($zpPointerVarName),y")

View File

@ -1,11 +1,6 @@
TODO TODO
==== ====
Petaxian has gameplay problems on the C64 (with and without optimization) , cx16 target is fine.
(seems unrelated to boolean type changes. 10.1 was still fine.)
caused by 358215e4ddf408e568ded0d36afce9f0162e21d1 Removed PostIncrDecr
... ...

View File

@ -4,21 +4,124 @@
main { main {
sub start() { sub start() {
derp("hello") uword @shared ref = $2000
mult3("hello") ref[5]=10
} txt.print_ub(ref[5])
txt.spc()
ref[5]--
txt.print_ub(ref[5])
txt.spc()
ref[5]++
txt.print_ub(ref[5])
txt.nl()
ref[5]-=2
txt.print_ub(ref[5])
txt.spc()
ref[5]+=2
txt.print_ub(ref[5])
txt.nl()
ref[5]-=3
txt.print_ub(ref[5])
txt.spc()
ref[5]+=3
txt.print_ub(ref[5])
txt.nl()
sub derp(str arg) -> str {
cx16.r0++
return arg
}
asmsub mult3(str input @XY) -> ubyte @A, str @XY { ubyte[] array = [1,2,3,4,5,10]
%asm {{ array[5]=10
lda #99 txt.print_ub(array[5])
ldx #100 txt.spc()
ldy #101 array[5]--
rts txt.print_ub(array[5])
}} txt.spc()
array[5]++
txt.print_ub(array[5])
txt.nl()
array[5]-=2
txt.print_ub(array[5])
txt.spc()
array[5]+=2
txt.print_ub(array[5])
txt.nl()
array[5]-=3
txt.print_ub(array[5])
txt.spc()
array[5]+=3
txt.print_ub(array[5])
txt.nl()
; cx16.r0L = 5
; ref[cx16.r0L]=10
; txt.print_ub(ref[cx16.r0L])
; txt.spc()
; ref[cx16.r0L]--
; txt.print_ub(ref[cx16.r0L])
; txt.spc()
; ref[cx16.r0L]++
; txt.print_ub(ref[cx16.r0L])
; txt.nl()
;
; uword @shared uw = 1000
; word @shared sw = -1000
;
; txt.print_uw(uw)
; txt.spc()
; uw++
; txt.print_uw(uw)
; txt.spc()
; uw--
; txt.print_uw(uw)
; txt.nl()
; uw = $00ff
; txt.print_uw(uw)
; txt.spc()
; uw++
; txt.print_uw(uw)
; txt.spc()
; uw--
; txt.print_uw(uw)
; txt.nl()
;
; txt.print_w(sw)
; txt.spc()
; sw++
; txt.print_w(sw)
; txt.spc()
; sw--
; txt.print_w(sw)
; txt.nl()
; sw = $00ff
; txt.print_w(sw)
; txt.spc()
; sw++
; txt.print_w(sw)
; txt.spc()
; sw--
; txt.print_w(sw)
; txt.nl()
; sw = -257
; txt.print_w(sw)
; txt.spc()
; sw++
; txt.print_w(sw)
; txt.spc()
; sw--
; txt.print_w(sw)
; txt.nl()
/*
seekerRef[SKR_X]-- this code looks very wrong with the pha/pla stuff
bulletRef[BD_Y]--/++
enemyRef[EN_MOVE_CNT]--/++
signed word--/++
unsigned word--/++
attackRef+=FIELD_COUNT
*/
} }
} }