mirror of
https://github.com/irmen/prog8.git
synced 2026-04-26 05:17:54 +00:00
fix typecasted byte-to-word pointer assignment, some more asm optimizations
This commit is contained in:
@@ -831,6 +831,10 @@ class AsmGen6502Internal (
|
||||
assignExpressionToRegister(zero, target.register!!)
|
||||
return
|
||||
}
|
||||
TargetStorageKind.POINTER -> {
|
||||
TODO("assign to pointer ${target.position}")
|
||||
return
|
||||
}
|
||||
else -> { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ internal fun optimizeAssembly(lines: MutableList<String>, machine: ICompilationT
|
||||
numberOfOptimizations++
|
||||
}
|
||||
|
||||
mods = optimizeAddWordToSameVariable(linesByFourteen)
|
||||
mods = optimizeAddWordToSameVariableOrExtraRegisterLoadInWordStore(linesByFourteen)
|
||||
if(mods.isNotEmpty()) {
|
||||
apply(mods, lines)
|
||||
linesByFourteen = getLinesBy(lines, 14)
|
||||
@@ -453,15 +453,26 @@ private fun optimizeStoreLoadSame(
|
||||
|
||||
|
||||
// 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 "))
|
||||
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))
|
||||
}
|
||||
|
||||
// all 3 registers: lda VALUE + sta SOMEWHERE + lda VALUE -> last load can be eliminated
|
||||
if (first.startsWith("lda ") && second.startsWith("sta ") && third.startsWith("lda ") ||
|
||||
first.startsWith("ldx ") && second.startsWith("stx ") && third.startsWith("ldx ") ||
|
||||
first.startsWith("ldy ") && second.startsWith("sty ") && third.startsWith("ldy ")
|
||||
) {
|
||||
val firstVal = first.substring(4).trimStart()
|
||||
val thirdVal = third.substring(4).trimStart()
|
||||
if (firstVal == thirdVal)
|
||||
mods.add(Modification(lines[3].index, true, null))
|
||||
}
|
||||
}
|
||||
return mods
|
||||
}
|
||||
@@ -701,23 +712,32 @@ private fun optimizeUselessPushPopStack(linesByFour: Sequence<List<IndexedValue<
|
||||
optimize('x', lines)
|
||||
optimize('y', lines)
|
||||
|
||||
val first = lines[1].value.trimStart()
|
||||
val second = lines[2].value.trimStart()
|
||||
val third = lines[3].value.trimStart()
|
||||
val first = lines[0].value.trimStart()
|
||||
val second = lines[1].value.trimStart()
|
||||
val third = lines[2].value.trimStart()
|
||||
val fourth = lines[3].value.trimStart()
|
||||
|
||||
// phy + ldy + pla -> tya + ldy
|
||||
// phx + ldx + pla -> txa + ldx
|
||||
// pha + lda + pla -> nop
|
||||
// pha + tya + tay + pla -> nop
|
||||
// pha + txa + tax + pla -> nop
|
||||
when (first) {
|
||||
"phy" if second.startsWith("ldy ") && third=="pla" -> {
|
||||
mods.add(Modification(lines[3].index, true, null))
|
||||
mods.add(Modification(lines[1].index, false, " tya"))
|
||||
mods.add(Modification(lines[2].index, true, null))
|
||||
mods.add(Modification(lines[0].index, false, " tya"))
|
||||
}
|
||||
"phx" if second.startsWith("ldx ") && third=="pla" -> {
|
||||
mods.add(Modification(lines[3].index, true, null))
|
||||
mods.add(Modification(lines[1].index, false, " txa"))
|
||||
mods.add(Modification(lines[2].index, true, null))
|
||||
mods.add(Modification(lines[0].index, false, " txa"))
|
||||
}
|
||||
"pha" if second.startsWith("lda ") && third=="pla" -> {
|
||||
mods.add(Modification(lines[0].index, true, null))
|
||||
mods.add(Modification(lines[1].index, true, null))
|
||||
mods.add(Modification(lines[2].index, true, null))
|
||||
}
|
||||
"pha" if ((second=="tya" && third=="tay") || (second=="txa" && third=="tax")) && fourth=="pla" -> {
|
||||
mods.add(Modification(lines[0].index, true, null))
|
||||
mods.add(Modification(lines[1].index, true, null))
|
||||
mods.add(Modification(lines[2].index, true, null))
|
||||
mods.add(Modification(lines[3].index, true, null))
|
||||
@@ -729,7 +749,6 @@ private fun optimizeUselessPushPopStack(linesByFour: Sequence<List<IndexedValue<
|
||||
return mods
|
||||
}
|
||||
|
||||
|
||||
private fun optimizeTSBtoRegularOr(linesByFour: Sequence<List<IndexedValue<String>>>): List<Modification> {
|
||||
// Asm peephole: lda var2 / tsb var1 / lda var1 Replace this with this to save 1 cycle: lda var1 / ora var2 / sta var1
|
||||
val mods = mutableListOf<Modification>()
|
||||
@@ -775,9 +794,9 @@ private fun optimizeUnneededTempvarInAdd(linesByFour: Sequence<List<IndexedValue
|
||||
return mods
|
||||
}
|
||||
|
||||
private fun optimizeAddWordToSameVariable(linesByFourteen: Sequence<List<IndexedValue<String>>>): List<Modification> {
|
||||
private fun optimizeAddWordToSameVariableOrExtraRegisterLoadInWordStore(linesByFourteen: Sequence<List<IndexedValue<String>>>): List<Modification> {
|
||||
/*
|
||||
; P8ZP_SCRATCH_PTR += AY :
|
||||
; FIRST SEQUYENCE: P8ZP_SCRATCH_PTR += AY :
|
||||
clc
|
||||
adc P8ZP_SCRATCH_PTR
|
||||
pha
|
||||
@@ -796,7 +815,37 @@ private fun optimizeAddWordToSameVariable(linesByFourteen: Sequence<List<Indexed
|
||||
tya
|
||||
adc P8ZP_SCRATCH_PTR+1
|
||||
sta P8ZP_SCRATCH_PTR+1
|
||||
*/
|
||||
|
||||
|
||||
also SECOND SEQUENCE:
|
||||
|
||||
ldx VALUE/ ldy VALUE
|
||||
sta SOMEWHERE_WITHOUT_,x_OR_,y
|
||||
txa / tya
|
||||
ldy #1
|
||||
sta SOMEWHERE
|
||||
-->
|
||||
sta SOMEWHERE_WITHOUT_,x_OR_,y
|
||||
lda VALUE
|
||||
ldy #1
|
||||
sta SOMEWHERE
|
||||
|
||||
|
||||
also THIRD SEQUENCE:
|
||||
|
||||
ldx VALUE
|
||||
ldy #0
|
||||
sta SOMEWHERE_WITHOUT_,x
|
||||
txa
|
||||
iny
|
||||
sta SOMEWHERE
|
||||
-->
|
||||
ldy #0
|
||||
sta SOMEWHERE_WITHOUT_,x
|
||||
lda VALUE
|
||||
iny
|
||||
sta SOMEWHERE
|
||||
*/
|
||||
val mods = mutableListOf<Modification>()
|
||||
for (lines in linesByFourteen) {
|
||||
val first = lines[0].value.trimStart()
|
||||
@@ -809,6 +858,7 @@ private fun optimizeAddWordToSameVariable(linesByFourteen: Sequence<List<Indexed
|
||||
val eight = lines[7].value.trimStart()
|
||||
val ninth = lines[8].value.trimStart()
|
||||
|
||||
// FIRST SEQUENCE
|
||||
if(first=="clc" && second.startsWith("adc") && third=="pha" && fourth=="tya" &&
|
||||
fifth.startsWith("adc") && sixth=="tay" && seventh=="pla" && eight.startsWith("sta") && ninth.startsWith("sty")) {
|
||||
val var2 = second.substring(4)
|
||||
@@ -825,6 +875,38 @@ private fun optimizeAddWordToSameVariable(linesByFourteen: Sequence<List<Indexed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SECOND SEQUENCE
|
||||
if(first.startsWith("ldx ") && second.startsWith("sta ") &&
|
||||
third=="txa" && fourth.startsWith("ldy ") && fifth.startsWith("sta ")
|
||||
) {
|
||||
if(",x" !in second) {
|
||||
val value = first.substring(4)
|
||||
mods.add(Modification(lines[0].index, true, null))
|
||||
mods.add(Modification(lines[2].index, false, " lda $value"))
|
||||
}
|
||||
}
|
||||
if(first.startsWith("ldy ") && second.startsWith("sta ") &&
|
||||
third=="tya" && fourth.startsWith("ldy ") && fifth.startsWith("sta ")
|
||||
) {
|
||||
if(",y" !in second) {
|
||||
val value = first.substring(4)
|
||||
mods.add(Modification(lines[0].index, true, null))
|
||||
mods.add(Modification(lines[2].index, false, " lda $value"))
|
||||
}
|
||||
}
|
||||
|
||||
// THIRD SEQUENCE
|
||||
if(first.startsWith("ldx ") && second.startsWith("ldy ") && third.startsWith("sta ") &&
|
||||
fourth=="txa" && fifth=="iny" && sixth.startsWith("sta ")
|
||||
) {
|
||||
if(",x" !in third) {
|
||||
val value = first.substring(4)
|
||||
mods.add(Modification(lines[0].index, true, null))
|
||||
mods.add(Modification(lines[3].index, false, " lda $value"))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return mods
|
||||
}
|
||||
@@ -2411,7 +2411,11 @@ $endLabel""")
|
||||
assignExpressionToRegister(value, target.register!!, targetDt.isSigned)
|
||||
return
|
||||
}
|
||||
else -> throw AssemblyError("weird target")
|
||||
TargetStorageKind.POINTER -> {
|
||||
pointergen.assignByteToWord(PtrTarget(target), value)
|
||||
return
|
||||
}
|
||||
else -> throw AssemblyError("weird target at ${target.position}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2435,7 +2439,7 @@ $endLabel""")
|
||||
assignExpressionToRegister(value, RegisterOrPair.AY, true)
|
||||
asmgen.out(" jsr floats.GIVAYFAY")
|
||||
}
|
||||
else -> throw AssemblyError("invalid dt")
|
||||
else -> throw AssemblyError("invalid dt at ${target.position}")
|
||||
}
|
||||
if(target.register==RegisterOrPair.FAC2) {
|
||||
asmgen.out(" jsr floats.MOVEF")
|
||||
@@ -3257,7 +3261,7 @@ $endLabel""")
|
||||
else -> throw AssemblyError("weird register")
|
||||
}
|
||||
}
|
||||
TargetStorageKind.POINTER -> pointergen.assignByteVar(PtrTarget(target), varName)
|
||||
TargetStorageKind.POINTER -> pointergen.assignByteVar(PtrTarget(target), varName, false, false)
|
||||
TargetStorageKind.VOID -> { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
@@ -3347,6 +3351,7 @@ $endLabel""")
|
||||
else -> throw AssemblyError("only reg pairs allowed as word target ${wordtarget.register}")
|
||||
}
|
||||
}
|
||||
TargetStorageKind.POINTER -> pointergen.assignByteVar(PtrTarget(wordtarget), sourceName, extendToWord=true, signed=true)
|
||||
else -> throw AssemblyError("target type isn't word")
|
||||
}
|
||||
}
|
||||
@@ -3419,6 +3424,7 @@ $endLabel""")
|
||||
else -> throw AssemblyError("only reg pairs allowed as word target")
|
||||
}
|
||||
}
|
||||
TargetStorageKind.POINTER -> pointergen.assignByteVar(PtrTarget(wordtarget), sourceName, extendToWord=true, signed=false)
|
||||
else -> throw AssemblyError("target type isn't word")
|
||||
}
|
||||
}
|
||||
@@ -4293,6 +4299,7 @@ $endLabel""")
|
||||
}
|
||||
else -> throw AssemblyError("word regs can only be pair")
|
||||
}
|
||||
TargetStorageKind.POINTER -> TODO("assign membyte into word pointer target ${wordtarget.position}")
|
||||
else -> throw AssemblyError("other types aren't word")
|
||||
}
|
||||
} else if (identifier != null) {
|
||||
@@ -4326,6 +4333,7 @@ $endLabel""")
|
||||
else -> throw AssemblyError("word regs can only be pair")
|
||||
}
|
||||
}
|
||||
TargetStorageKind.POINTER -> TODO("assign membyte into word pointer ${wordtarget.position}")
|
||||
else -> throw AssemblyError("other types aren't word")
|
||||
}
|
||||
}
|
||||
@@ -4603,6 +4611,7 @@ $endLabel""")
|
||||
sta ${target.asmVarname}+1""")
|
||||
}
|
||||
TargetStorageKind.ARRAY -> assignPrefixedExpressionToArrayElt(makePrefixedExprFromArrayExprAssign("-", assign), scope)
|
||||
TargetStorageKind.POINTER -> pointergen.inplaceFloatNegate(PtrTarget(target), scope)
|
||||
else -> throw AssemblyError("weird target for in-place float negation")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +52,13 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
asmgen.storeIndirectFloatVar(varName, zpPtrVar, offset)
|
||||
}
|
||||
|
||||
internal fun assignByteVar(target: PtrTarget, varName: String) {
|
||||
internal fun assignByteVar(target: PtrTarget, varName: String, extendToWord: Boolean, signed: Boolean) {
|
||||
val (zpPtrVar, offset) = deref(target.pointer)
|
||||
asmgen.storeIndirectByteVar(varName, zpPtrVar, offset)
|
||||
if(extendToWord) {
|
||||
TODO("assign byte var to word pointer ${target.position} signed=$signed")
|
||||
} else {
|
||||
asmgen.storeIndirectByteVar(varName, zpPtrVar, offset)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun assignByteReg(target: PtrTarget, register: CpuRegister, signed: Boolean, extendWord: Boolean) {
|
||||
@@ -64,6 +68,11 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
asmgen.storeIndirectByteReg(register, zpPtrVar, offset, signed, extendWord && target.dt.isWord)
|
||||
}
|
||||
|
||||
internal fun assignByteToWord(target: PtrTarget, value: PtExpression) {
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.AX, target.dt.isSigned)
|
||||
assignWordReg(target, RegisterOrPair.AX)
|
||||
}
|
||||
|
||||
internal fun assignWordReg(target: PtrTarget, regs: RegisterOrPair) {
|
||||
saveOnStack(regs)
|
||||
val (zpPtrVar, offset) = deref(target.pointer)
|
||||
@@ -110,6 +119,10 @@ internal class PointerAssignmentsGen(private val asmgen: AsmGen6502Internal, pri
|
||||
TODO("inplace word negate pointer deref ${target.position}")
|
||||
}
|
||||
|
||||
internal fun inplaceFloatNegate(target: PtrTarget, scope: IPtSubroutine?) {
|
||||
TODO("inplace float negate pointer deref ${target.position}")
|
||||
}
|
||||
|
||||
|
||||
internal fun deref(pointer: PtPointerDeref, forceTemporary: Boolean=false, addOffsetToPointer: Boolean=false): Pair<String, UByte> {
|
||||
// walk the pointer deref chain and leaves the final pointer value in a ZP var
|
||||
|
||||
Reference in New Issue
Block a user