mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-24 15:29:23 +00:00
Optimization improvements:
– better zeropage register flow tracking – reverse flow analysis speed improvement – optimize TXA/TAX after LAX – don't stash A onto stack over externally linear code blocks
This commit is contained in:
parent
5ee9fd85ce
commit
816bfb5f06
@ -508,6 +508,13 @@ object AlwaysGoodOptimizations {
|
|||||||
(Elidable & HasOpcode(PLY)) ~~> { code =>
|
(Elidable & HasOpcode(PLY)) ~~> { code =>
|
||||||
code.head :: (code.drop(2).init :+ code.head)
|
code.head :: (code.drop(2).init :+ code.head)
|
||||||
},
|
},
|
||||||
|
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||||
|
(Elidable & HasOpcode(PHA)) ~
|
||||||
|
(Not(ConcernsStack) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).*.capture(2) ~
|
||||||
|
Where(ctx => ctx.isExternallyLinearBlock(2))~
|
||||||
|
(Elidable & HasOpcode(PLA)) ~~> { code =>
|
||||||
|
code.head :: (code.drop(2).init :+ code.head)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
val IncrementingIndexRegistersAfterTransfer = new RuleBasedAssemblyOptimization("Incrementing index registers after transfer",
|
val IncrementingIndexRegistersAfterTransfer = new RuleBasedAssemblyOptimization("Incrementing index registers after transfer",
|
||||||
@ -839,7 +846,7 @@ object AlwaysGoodOptimizations {
|
|||||||
HasOpcode(TAX) ~ (Elidable & Set(TXA, TAX)) ~~> (_.init),
|
HasOpcode(TAX) ~ (Elidable & Set(TXA, TAX)) ~~> (_.init),
|
||||||
HasOpcode(TSX) ~ (Elidable & Set(TXS, TSX)) ~~> (_.init),
|
HasOpcode(TSX) ~ (Elidable & Set(TXS, TSX)) ~~> (_.init),
|
||||||
HasOpcode(TXS) ~ (Elidable & Set(TXS, TSX)) ~~> (_.init),
|
HasOpcode(TXS) ~ (Elidable & Set(TXS, TSX)) ~~> (_.init),
|
||||||
HasOpcodeIn(Set(TXA, TAX)) ~
|
HasOpcodeIn(Set(TXA, TAX, LAX, LXA)) ~
|
||||||
(Linear & Not(ChangesNAndZ) & Not(ChangesA) & Not(ChangesX)).* ~
|
(Linear & Not(ChangesNAndZ) & Not(ChangesA) & Not(ChangesX)).* ~
|
||||||
(Elidable & HasOpcodeIn(Set(TXA, TAX))) ~~> (_.init),
|
(Elidable & HasOpcodeIn(Set(TXA, TAX))) ~~> (_.init),
|
||||||
HasOpcodeIn(Set(TYA, TAY)) ~
|
HasOpcodeIn(Set(TYA, TAY)) ~
|
||||||
@ -1079,7 +1086,7 @@ object AlwaysGoodOptimizations {
|
|||||||
(HasOpcode(LABEL) & MatchParameter(3) & HasCallerCount(1)) ~
|
(HasOpcode(LABEL) & MatchParameter(3) & HasCallerCount(1)) ~
|
||||||
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||||
|
|
||||||
HasOpcodeIn(Set(TXA, TAX)) ~
|
HasOpcodeIn(Set(TXA, TAX, LAX, LXA)) ~
|
||||||
(Not(Set(TXA, TAX)) & Linear & Not(ChangesA) & Not(ChangesX)).* ~
|
(Not(Set(TXA, TAX)) & Linear & Not(ChangesA) & Not(ChangesX)).* ~
|
||||||
(Elidable & HasOpcodeIn(Set(TXA, TAX)) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
(Elidable & HasOpcodeIn(Set(TXA, TAX)) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||||
|
|
||||||
|
@ -92,9 +92,30 @@ case class CpuImportance(a: Importance = UnknownImportance,
|
|||||||
|
|
||||||
object ReverseFlowAnalyzer {
|
object ReverseFlowAnalyzer {
|
||||||
|
|
||||||
val aluAdders = Set(Opcode.ADC, Opcode.SBC, Opcode.ISC, Opcode.DCP, Opcode.ADC_W, Opcode.SBC_W)
|
private val aluAdders = Set(Opcode.ADC, Opcode.SBC, Opcode.ISC, Opcode.DCP, Opcode.ADC_W, Opcode.SBC_W)
|
||||||
val actuallyRead = Set(AddrMode.IndexedZ, AddrMode.IndexedSY, AddrMode.IndexedY, AddrMode.LongIndexedY, AddrMode.LongIndexedZ, AddrMode.IndexedX, AddrMode.Indirect, AddrMode.AbsoluteIndexedX)
|
private val actuallyRead = Set(AddrMode.IndexedZ, AddrMode.IndexedSY, AddrMode.IndexedY, AddrMode.LongIndexedY, AddrMode.LongIndexedZ, AddrMode.IndexedX, AddrMode.Indirect, AddrMode.AbsoluteIndexedX)
|
||||||
val absoluteLike = Set(AddrMode.ZeroPage, AddrMode.Absolute, AddrMode.LongAbsolute)
|
private val absoluteLike = Set(AddrMode.ZeroPage, AddrMode.Absolute, AddrMode.LongAbsolute)
|
||||||
|
private val importanceBeforeJsr: CpuImportance = CpuImportance(
|
||||||
|
a = Unimportant,
|
||||||
|
ah = Unimportant,
|
||||||
|
x = Unimportant,
|
||||||
|
y = Unimportant,
|
||||||
|
iz = Unimportant,
|
||||||
|
z = Unimportant,
|
||||||
|
n = Unimportant,
|
||||||
|
c = Unimportant,
|
||||||
|
v = Unimportant,
|
||||||
|
d = Important,
|
||||||
|
m = Important,
|
||||||
|
w = Important,
|
||||||
|
r0 = Unimportant,
|
||||||
|
r1 = Unimportant)
|
||||||
|
private val finalImportance: CpuImportance = CpuImportance(
|
||||||
|
a = Important, ah = Important,
|
||||||
|
x = Important, y = Important, iz = Important,
|
||||||
|
c = Important, v = Important, d = Important, z = Important, n = Important,
|
||||||
|
m = Important, w = Important,
|
||||||
|
r0 = Important, r1 = Important)
|
||||||
|
|
||||||
//noinspection RedundantNewCaseClass
|
//noinspection RedundantNewCaseClass
|
||||||
def analyze(f: NormalFunction, code: List[AssemblyLine]): List[CpuImportance] = {
|
def analyze(f: NormalFunction, code: List[AssemblyLine]): List[CpuImportance] = {
|
||||||
@ -102,16 +123,10 @@ object ReverseFlowAnalyzer {
|
|||||||
val codeArray = code.toArray
|
val codeArray = code.toArray
|
||||||
|
|
||||||
var changed = true
|
var changed = true
|
||||||
val finalImportance = new CpuImportance(
|
|
||||||
a = Important, ah = Important,
|
|
||||||
x = Important, y = Important, iz = Important,
|
|
||||||
c = Important, v = Important, d = Important, z = Important, n = Important,
|
|
||||||
m = Important, w = Important,
|
|
||||||
r0 = Important, r1 = Important)
|
|
||||||
changed = true
|
changed = true
|
||||||
while (changed) {
|
while (changed) {
|
||||||
changed = false
|
changed = false
|
||||||
var currentImportance: CpuImportance = finalImportance
|
var currentImportance = finalImportance
|
||||||
for (i <- codeArray.indices.reverse) {
|
for (i <- codeArray.indices.reverse) {
|
||||||
import millfork.assembly.mos.Opcode._
|
import millfork.assembly.mos.Opcode._
|
||||||
import AddrMode._
|
import AddrMode._
|
||||||
@ -134,21 +149,7 @@ object ReverseFlowAnalyzer {
|
|||||||
|
|
||||||
case AssemblyLine(JSR | JMP, Absolute | LongAbsolute, MemoryAddressConstant(fun: FunctionInMemory), _) =>
|
case AssemblyLine(JSR | JMP, Absolute | LongAbsolute, MemoryAddressConstant(fun: FunctionInMemory), _) =>
|
||||||
// this case has to be handled first, because the generic JSR importance handler is too conservative
|
// this case has to be handled first, because the generic JSR importance handler is too conservative
|
||||||
var result = new CpuImportance(
|
var result = importanceBeforeJsr
|
||||||
a = Unimportant,
|
|
||||||
ah = Unimportant,
|
|
||||||
x = Unimportant,
|
|
||||||
y = Unimportant,
|
|
||||||
iz = Unimportant,
|
|
||||||
z = Unimportant,
|
|
||||||
n = Unimportant,
|
|
||||||
c = Unimportant,
|
|
||||||
v = Unimportant,
|
|
||||||
d = Important,
|
|
||||||
m = Important,
|
|
||||||
w = Important,
|
|
||||||
r0 = Unimportant,
|
|
||||||
r1 = Unimportant)
|
|
||||||
fun.params match {
|
fun.params match {
|
||||||
case AssemblyParamSignature(params) =>
|
case AssemblyParamSignature(params) =>
|
||||||
params.foreach(_.variable match {
|
params.foreach(_.variable match {
|
||||||
@ -180,7 +181,10 @@ object ReverseFlowAnalyzer {
|
|||||||
case AssemblyLine(AND, _, NumericConstant(0, _), _) =>
|
case AssemblyLine(AND, _, NumericConstant(0, _), _) =>
|
||||||
currentImportance = currentImportance.copy(n = Unimportant, z = Unimportant, a = Unimportant)
|
currentImportance = currentImportance.copy(n = Unimportant, z = Unimportant, a = Unimportant)
|
||||||
|
|
||||||
case AssemblyLine(opcode, addrMode, _, _) if ReverseFlowAnalyzerPerOpcode.hasDefinition(opcode) =>
|
case AssemblyLine(opcode, Implied, _, _) if ReverseFlowAnalyzerPerImpiedOpcode.hasDefinition(opcode) =>
|
||||||
|
currentImportance = ReverseFlowAnalyzerPerImpiedOpcode.get(opcode)(currentImportance)
|
||||||
|
|
||||||
|
case AssemblyLine(opcode, addrMode, _, _) if addrMode != Implied && ReverseFlowAnalyzerPerOpcode.hasDefinition(opcode) =>
|
||||||
currentImportance = ReverseFlowAnalyzerPerOpcode.get(opcode)(currentImportance)
|
currentImportance = ReverseFlowAnalyzerPerOpcode.get(opcode)(currentImportance)
|
||||||
if (addrMode == AbsoluteX || addrMode == LongAbsoluteX || addrMode == IndexedX || addrMode == ZeroPageX || addrMode == AbsoluteIndexedX)
|
if (addrMode == AbsoluteX || addrMode == LongAbsoluteX || addrMode == IndexedX || addrMode == ZeroPageX || addrMode == AbsoluteIndexedX)
|
||||||
currentImportance = currentImportance.copy(x = Important)
|
currentImportance = currentImportance.copy(x = Important)
|
||||||
@ -275,7 +279,7 @@ object ReverseFlowAnalyzer {
|
|||||||
if th.name == "__reg" => currentImportance = currentImportance.copy(r0 = Important, r1 = Important)
|
if th.name == "__reg" => currentImportance = currentImportance.copy(r0 = Important, r1 = Important)
|
||||||
case _ => ()
|
case _ => ()
|
||||||
}
|
}
|
||||||
} else if (OpcodeClasses.ReadsM(currentLine.opcode) || OpcodeClasses.ReadsMemoryIfNotImpliedOrImmediate(currentLine.opcode)) {
|
} else if (OpcodeClasses.ReadsMemoryIfNotImpliedOrImmediate(currentLine.opcode)) {
|
||||||
if (OpcodeClasses.AccessesWordInMemory(currentLine.opcode)) {
|
if (OpcodeClasses.AccessesWordInMemory(currentLine.opcode)) {
|
||||||
currentLine.parameter match {
|
currentLine.parameter match {
|
||||||
case MemoryAddressConstant(th: Thing)
|
case MemoryAddressConstant(th: Thing)
|
||||||
@ -294,10 +298,10 @@ object ReverseFlowAnalyzer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// importanceArray.zip(codeArray).foreach{
|
// importanceArray.zip(codeArray).foreach{
|
||||||
// case (i, y) => if (y.isPrintable) println(f"$y%-32s $i%-32s")
|
// case (i, y) => if (y.isPrintable) println(f"$y%-32s $i%-32s")
|
||||||
// }
|
// }
|
||||||
// println("---------------------")
|
// println("---------------------")
|
||||||
|
|
||||||
importanceArray.toList
|
importanceArray.toList
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,182 @@
|
|||||||
|
package millfork.assembly.mos.opt
|
||||||
|
|
||||||
|
import millfork.assembly.mos.Opcode
|
||||||
|
import millfork.assembly.mos.Opcode._
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karol Stasiak
|
||||||
|
*/
|
||||||
|
object ReverseFlowAnalyzerPerImpiedOpcode {
|
||||||
|
|
||||||
|
private val finalImportance = CpuImportance(
|
||||||
|
a = Important, ah = Important,
|
||||||
|
x = Important, y = Important, iz = Important,
|
||||||
|
c = Important, v = Important, d = Important, z = Important, n = Important,
|
||||||
|
m = Important, w = Important)
|
||||||
|
|
||||||
|
private def allAddingOutputsUnimportant(currentImportance: CpuImportance): Boolean =
|
||||||
|
currentImportance.a == Unimportant &&
|
||||||
|
currentImportance.c == Unimportant &&
|
||||||
|
currentImportance.z == Unimportant &&
|
||||||
|
currentImportance.n == Unimportant &&
|
||||||
|
currentImportance.v == Unimportant
|
||||||
|
|
||||||
|
private def allLoadingAccuOutputsUnimportant(currentImportance: CpuImportance): Boolean =
|
||||||
|
currentImportance.a == Unimportant &&
|
||||||
|
currentImportance.z == Unimportant &&
|
||||||
|
currentImportance.n == Unimportant
|
||||||
|
|
||||||
|
private def allCompareOutputsAreUnimportant(currentImportance: CpuImportance): Boolean =
|
||||||
|
currentImportance.z == Unimportant &&
|
||||||
|
currentImportance.n == Unimportant&&
|
||||||
|
currentImportance.c == Unimportant
|
||||||
|
|
||||||
|
private val map: Map[Opcode.Value, CpuImportance => CpuImportance] = Map(
|
||||||
|
NOP -> identity,
|
||||||
|
SEI -> identity,
|
||||||
|
CLI -> identity,
|
||||||
|
WAI -> identity,
|
||||||
|
STP -> identity,
|
||||||
|
BRK -> (_ => finalImportance),
|
||||||
|
COP -> (_ => finalImportance),
|
||||||
|
RTS -> (_ => finalImportance),
|
||||||
|
RTL -> (_ => finalImportance),
|
||||||
|
|
||||||
|
RTI -> (_ => CpuImportance(
|
||||||
|
a = Unimportant, ah = Unimportant,
|
||||||
|
x = Unimportant, y = Unimportant, iz = Unimportant,
|
||||||
|
z = Unimportant, n = Unimportant, c = Unimportant, v = Unimportant, d = Unimportant,
|
||||||
|
m = Unimportant, w = Unimportant)),
|
||||||
|
|
||||||
|
TAX -> (currentImportance => {
|
||||||
|
currentImportance.copy(
|
||||||
|
a = currentImportance.x ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z,
|
||||||
|
x = Unimportant,
|
||||||
|
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
TAY -> (currentImportance => {
|
||||||
|
currentImportance.copy(
|
||||||
|
a = currentImportance.y ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z,
|
||||||
|
y = Unimportant,
|
||||||
|
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
TXA -> (currentImportance => {
|
||||||
|
currentImportance.copy(
|
||||||
|
x = currentImportance.a ~ currentImportance.x ~ currentImportance.n ~ currentImportance.z,
|
||||||
|
a = Unimportant,
|
||||||
|
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
TYA -> (currentImportance => {
|
||||||
|
currentImportance.copy(
|
||||||
|
y = currentImportance.a ~ currentImportance.y ~ currentImportance.n ~ currentImportance.z,
|
||||||
|
a = Unimportant,
|
||||||
|
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
TAZ -> (currentImportance => {
|
||||||
|
currentImportance.copy(
|
||||||
|
a = currentImportance.iz ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z,
|
||||||
|
iz = Unimportant,
|
||||||
|
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
TZA -> (currentImportance => {
|
||||||
|
currentImportance.copy(
|
||||||
|
iz = currentImportance.a ~ currentImportance.iz ~ currentImportance.n ~ currentImportance.z,
|
||||||
|
a = Unimportant,
|
||||||
|
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
TXY -> (currentImportance => {
|
||||||
|
currentImportance.copy(
|
||||||
|
x = currentImportance.y ~ currentImportance.x ~ currentImportance.n ~ currentImportance.z,
|
||||||
|
y = Unimportant,
|
||||||
|
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
TYX -> (currentImportance => {
|
||||||
|
currentImportance.copy(
|
||||||
|
y = currentImportance.x ~ currentImportance.y ~ currentImportance.n ~ currentImportance.z,
|
||||||
|
x = Unimportant,
|
||||||
|
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
TSX -> (_.copy(x = Unimportant, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
|
TXS -> (_.copy(x = Important, w = Important)),
|
||||||
|
XBA -> (currentImportance => {
|
||||||
|
currentImportance.copy(
|
||||||
|
ah = currentImportance.a ~ currentImportance.iz ~ currentImportance.n ~ currentImportance.z,
|
||||||
|
a = currentImportance.ah,
|
||||||
|
n = Unimportant, z = Unimportant)
|
||||||
|
}),
|
||||||
|
TCD -> (_.copy(a = Important, ah = Important)),
|
||||||
|
TDC -> (_.copy(a = Unimportant, ah = Unimportant, n = Unimportant, z = Unimportant)),
|
||||||
|
TCS -> (_.copy(a = Important, ah = Important)),
|
||||||
|
TSC -> (_.copy(a = Unimportant, ah = Unimportant, n = Unimportant, z = Unimportant)),
|
||||||
|
|
||||||
|
TRB -> (_.copy(a = Important, z = Unimportant, m = Important)),
|
||||||
|
TSB -> (_.copy(a = Important, z = Unimportant, m = Important)),
|
||||||
|
|
||||||
|
HuSAX -> (currentImportance => {
|
||||||
|
currentImportance.copy(a = currentImportance.x, x = currentImportance.a, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
SAY -> (currentImportance => {
|
||||||
|
currentImportance.copy(y = currentImportance.a, a = currentImportance.y, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
SXY -> (currentImportance => {
|
||||||
|
currentImportance.copy(y = currentImportance.x, x = currentImportance.y, m = Important, w = Important)
|
||||||
|
}),
|
||||||
|
|
||||||
|
ASL -> (_.copy(a = Important, c = Unimportant, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
LSR -> (_.copy(a = Important, c = Unimportant, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
ROL -> (_.copy(a = Important, c = Important, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
ROR -> (_.copy(a = Important, c = Important, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
|
||||||
|
ASL_W -> (_.copy(a = Important, ah = Important, c = Unimportant, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
LSR_W -> (_.copy(a = Important, ah = Important, c = Unimportant, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
ROL_W -> (_.copy(a = Important, ah = Important, c = Important, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
ROR_W -> (_.copy(a = Important, ah = Important, c = Important, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
|
||||||
|
DEC -> (_.copy(a = Important, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
DEX -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
|
DEY -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
|
DEZ -> (_.copy(iz = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
|
||||||
|
INC -> (_.copy(a = Important, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
INX -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
|
INY -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
|
INZ -> (_.copy(iz = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
|
||||||
|
DEC_W -> (_.copy(a = Important, ah = Important, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
DEX_W -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
|
DEY_W -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
|
INC_W -> (_.copy(x = Important, ah = Important, n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
INX_W -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
|
INY_W -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
|
|
||||||
|
PHP -> (_.copy(n = Important, c = Important, d = Important, z = Important, v = Important, m = Important, w = Important)),
|
||||||
|
PLP -> (_.copy(n = Unimportant, c = Unimportant, d = Unimportant, z = Unimportant, v = Unimportant, m = Unimportant, w = Unimportant)),
|
||||||
|
|
||||||
|
PHA -> (_.copy(a = Important, m = Important)),
|
||||||
|
PLA -> (_.copy(a = Unimportant, m = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
PHX -> (_.copy(x = Important, w = Important)),
|
||||||
|
PLX -> (_.copy(x = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
PHY -> (_.copy(y = Important, w = Important)),
|
||||||
|
PLY -> (_.copy(y = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
PHZ -> (_.copy(iz = Important, w = Important)),
|
||||||
|
PLZ -> (_.copy(iz = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
|
||||||
|
PHA_W -> (_.copy(a = Important, ah = Important, m = Important)),
|
||||||
|
PLA_W -> (_.copy(a = Unimportant, ah = Unimportant, m = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
PHX_W -> (_.copy(x = Important, w = Important)),
|
||||||
|
PLX_W -> (_.copy(x = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
PHY_W -> (_.copy(y = Important, w = Important)),
|
||||||
|
PLY_W -> (_.copy(y = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
|
||||||
|
CLC -> (_.copy(c = Unimportant)),
|
||||||
|
SEC -> (_.copy(c = Unimportant)),
|
||||||
|
CLD -> (_.copy(d = Unimportant)),
|
||||||
|
SED -> (_.copy(d = Unimportant)),
|
||||||
|
CLV -> (_.copy(v = Unimportant)),
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode)
|
||||||
|
|
||||||
|
def get(opcode: Opcode.Value): CpuImportance => CpuImportance = map(opcode)
|
||||||
|
}
|
@ -26,25 +26,20 @@ object ReverseFlowAnalyzerPerOpcode {
|
|||||||
currentImportance.z == Unimportant &&
|
currentImportance.z == Unimportant &&
|
||||||
currentImportance.n == Unimportant
|
currentImportance.n == Unimportant
|
||||||
|
|
||||||
|
private def allCompareOutputsAreUnimportant(currentImportance: CpuImportance): Boolean =
|
||||||
|
currentImportance.z == Unimportant &&
|
||||||
|
currentImportance.n == Unimportant&&
|
||||||
|
currentImportance.c == Unimportant
|
||||||
|
|
||||||
private val map: Map[Opcode.Value, CpuImportance => CpuImportance] = Map(
|
private val map: Map[Opcode.Value, CpuImportance => CpuImportance] = Map(
|
||||||
NOP -> identity,
|
NOP -> identity,
|
||||||
SEI -> identity,
|
LABEL -> identity,
|
||||||
CLI -> identity,
|
|
||||||
|
|
||||||
JSR -> (_ => finalImportance),
|
JSR -> (_ => finalImportance),
|
||||||
BSR -> (_ => finalImportance),
|
BSR -> (_ => finalImportance),
|
||||||
BRK -> (_ => finalImportance),
|
BRK -> (_ => finalImportance),
|
||||||
COP -> (_ => finalImportance),
|
COP -> (_ => finalImportance),
|
||||||
RTS -> (_ => finalImportance),
|
|
||||||
RTL -> (_ => finalImportance),
|
|
||||||
BYTE -> (_ => finalImportance),
|
BYTE -> (_ => finalImportance),
|
||||||
|
|
||||||
RTI -> (_ => CpuImportance(
|
|
||||||
a = Unimportant, ah = Unimportant,
|
|
||||||
x = Unimportant, y = Unimportant, iz = Unimportant,
|
|
||||||
z = Unimportant, n = Unimportant, c = Unimportant, v = Unimportant, d = Unimportant,
|
|
||||||
m = Unimportant, w = Unimportant)),
|
|
||||||
|
|
||||||
BNE -> (_.copy(z = Important)),
|
BNE -> (_.copy(z = Important)),
|
||||||
BEQ -> (_.copy(z = Important)),
|
BEQ -> (_.copy(z = Important)),
|
||||||
BMI -> (_.copy(n = Important)),
|
BMI -> (_.copy(n = Important)),
|
||||||
@ -54,71 +49,6 @@ object ReverseFlowAnalyzerPerOpcode {
|
|||||||
BCC -> (_.copy(c = Important)),
|
BCC -> (_.copy(c = Important)),
|
||||||
BCS -> (_.copy(c = Important)),
|
BCS -> (_.copy(c = Important)),
|
||||||
|
|
||||||
TAX -> (currentImportance => {
|
|
||||||
currentImportance.copy(
|
|
||||||
a = currentImportance.x ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z,
|
|
||||||
x = Unimportant,
|
|
||||||
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
TAY -> (currentImportance => {
|
|
||||||
currentImportance.copy(
|
|
||||||
a = currentImportance.y ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z,
|
|
||||||
y = Unimportant,
|
|
||||||
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
TXA -> (currentImportance => {
|
|
||||||
currentImportance.copy(
|
|
||||||
x = currentImportance.a ~ currentImportance.x ~ currentImportance.n ~ currentImportance.z,
|
|
||||||
a = Unimportant,
|
|
||||||
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
TYA -> (currentImportance => {
|
|
||||||
currentImportance.copy(
|
|
||||||
y = currentImportance.a ~ currentImportance.y ~ currentImportance.n ~ currentImportance.z,
|
|
||||||
a = Unimportant,
|
|
||||||
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
TAZ -> (currentImportance => {
|
|
||||||
currentImportance.copy(
|
|
||||||
a = currentImportance.iz ~ currentImportance.a ~ currentImportance.n ~ currentImportance.z,
|
|
||||||
iz = Unimportant,
|
|
||||||
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
TZA -> (currentImportance => {
|
|
||||||
currentImportance.copy(
|
|
||||||
iz = currentImportance.a ~ currentImportance.iz ~ currentImportance.n ~ currentImportance.z,
|
|
||||||
a = Unimportant,
|
|
||||||
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
TXY -> (currentImportance => {
|
|
||||||
currentImportance.copy(
|
|
||||||
x = currentImportance.y ~ currentImportance.x ~ currentImportance.n ~ currentImportance.z,
|
|
||||||
y = Unimportant,
|
|
||||||
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
TYX -> (currentImportance => {
|
|
||||||
currentImportance.copy(
|
|
||||||
y = currentImportance.x ~ currentImportance.y ~ currentImportance.n ~ currentImportance.z,
|
|
||||||
x = Unimportant,
|
|
||||||
n = Unimportant, z = Unimportant, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
XBA -> (currentImportance => {
|
|
||||||
currentImportance.copy(
|
|
||||||
ah = currentImportance.a ~ currentImportance.iz ~ currentImportance.n ~ currentImportance.z,
|
|
||||||
a = currentImportance.ah,
|
|
||||||
n = Unimportant, z = Unimportant)
|
|
||||||
}),
|
|
||||||
|
|
||||||
HuSAX -> (currentImportance => {
|
|
||||||
currentImportance.copy(a = currentImportance.x, x = currentImportance.a, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
SAY -> (currentImportance => {
|
|
||||||
currentImportance.copy(y = currentImportance.a, a = currentImportance.y, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
SXY -> (currentImportance => {
|
|
||||||
currentImportance.copy(y = currentImportance.x, x = currentImportance.y, m = Important, w = Important)
|
|
||||||
}),
|
|
||||||
|
|
||||||
DISCARD_XF -> (_.copy(x = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant, r0 = Unimportant, r1 = Unimportant)),
|
DISCARD_XF -> (_.copy(x = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant, r0 = Unimportant, r1 = Unimportant)),
|
||||||
DISCARD_YF -> (_.copy(y = Unimportant, iz = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant, r0 = Unimportant, r1 = Unimportant)),
|
DISCARD_YF -> (_.copy(y = Unimportant, iz = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant, r0 = Unimportant, r1 = Unimportant)),
|
||||||
DISCARD_AF -> (_.copy(a = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant, r0 = Unimportant, r1 = Unimportant)),
|
DISCARD_AF -> (_.copy(a = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant, r0 = Unimportant, r1 = Unimportant)),
|
||||||
@ -128,6 +58,8 @@ object ReverseFlowAnalyzerPerOpcode {
|
|||||||
LDY -> (_.copy(y = Unimportant, n = Unimportant, z = Unimportant, w = Important)),
|
LDY -> (_.copy(y = Unimportant, n = Unimportant, z = Unimportant, w = Important)),
|
||||||
LDZ -> (_.copy(iz = Unimportant, n = Unimportant, z = Unimportant)),
|
LDZ -> (_.copy(iz = Unimportant, n = Unimportant, z = Unimportant)),
|
||||||
LAX -> (_.copy(a = Unimportant, x = Unimportant, n = Unimportant, z = Unimportant)),
|
LAX -> (_.copy(a = Unimportant, x = Unimportant, n = Unimportant, z = Unimportant)),
|
||||||
|
LXA -> (_.copy(a = Important, x = Unimportant, n = Unimportant, z = Unimportant)),
|
||||||
|
XAA -> (_.copy(a = Important, x = Important, n = Unimportant, z = Unimportant)),
|
||||||
|
|
||||||
ORA -> (currentImportance => {
|
ORA -> (currentImportance => {
|
||||||
val ignoreOutput = allLoadingAccuOutputsUnimportant(currentImportance)
|
val ignoreOutput = allLoadingAccuOutputsUnimportant(currentImportance)
|
||||||
@ -150,6 +82,27 @@ object ReverseFlowAnalyzerPerOpcode {
|
|||||||
n = Unimportant, z = Unimportant,
|
n = Unimportant, z = Unimportant,
|
||||||
m = Important)
|
m = Important)
|
||||||
}),
|
}),
|
||||||
|
SLO -> (currentImportance => {
|
||||||
|
val ignoreOutput = allLoadingAccuOutputsUnimportant(currentImportance)
|
||||||
|
currentImportance.copy(
|
||||||
|
a = if (ignoreOutput) Unimportant else Important,
|
||||||
|
n = Unimportant, z = Unimportant, c = Unimportant,
|
||||||
|
m = Important)
|
||||||
|
}),
|
||||||
|
SRE -> (currentImportance => {
|
||||||
|
val ignoreOutput = allLoadingAccuOutputsUnimportant(currentImportance)
|
||||||
|
currentImportance.copy(
|
||||||
|
a = if (ignoreOutput) Unimportant else Important,
|
||||||
|
n = Unimportant, z = Unimportant, c = Unimportant,
|
||||||
|
m = Important)
|
||||||
|
}),
|
||||||
|
RLA -> (currentImportance => {
|
||||||
|
val ignoreOutput = allLoadingAccuOutputsUnimportant(currentImportance)
|
||||||
|
currentImportance.copy(
|
||||||
|
a = if (ignoreOutput) Unimportant else Important,
|
||||||
|
n = Unimportant, z = Unimportant, c = Important,
|
||||||
|
m = Important)
|
||||||
|
}),
|
||||||
BIT -> (currentImportance => {
|
BIT -> (currentImportance => {
|
||||||
currentImportance.copy(
|
currentImportance.copy(
|
||||||
a = currentImportance.z,
|
a = currentImportance.z,
|
||||||
@ -158,6 +111,33 @@ object ReverseFlowAnalyzerPerOpcode {
|
|||||||
v = Unimportant,
|
v = Unimportant,
|
||||||
m = Important)
|
m = Important)
|
||||||
}),
|
}),
|
||||||
|
CMP -> (currentImportance => {
|
||||||
|
val ignoreOutput = allCompareOutputsAreUnimportant(currentImportance)
|
||||||
|
currentImportance.copy(
|
||||||
|
a = if (ignoreOutput) Unimportant else Important,
|
||||||
|
n = Unimportant, z = Unimportant, c = Unimportant,
|
||||||
|
m = Important)
|
||||||
|
}),
|
||||||
|
DCP -> (currentImportance => {
|
||||||
|
val ignoreOutput = allCompareOutputsAreUnimportant(currentImportance)
|
||||||
|
currentImportance.copy(
|
||||||
|
a = if (ignoreOutput) Unimportant else Important,
|
||||||
|
n = Unimportant, z = Unimportant, c = Unimportant)
|
||||||
|
}),
|
||||||
|
CPX -> (currentImportance => {
|
||||||
|
val ignoreOutput = allCompareOutputsAreUnimportant(currentImportance)
|
||||||
|
currentImportance.copy(
|
||||||
|
x = if (ignoreOutput) Unimportant else Important,
|
||||||
|
n = Unimportant, z = Unimportant, c = Unimportant,
|
||||||
|
w = Important)
|
||||||
|
}),
|
||||||
|
CPY -> (currentImportance => {
|
||||||
|
val ignoreOutput = allCompareOutputsAreUnimportant(currentImportance)
|
||||||
|
currentImportance.copy(
|
||||||
|
y = if (ignoreOutput) Unimportant else Important,
|
||||||
|
n = Unimportant, z = Unimportant, c = Unimportant,
|
||||||
|
w = Important)
|
||||||
|
}),
|
||||||
|
|
||||||
ADC -> (currentImportance => {
|
ADC -> (currentImportance => {
|
||||||
val ignoreOutput = allAddingOutputsUnimportant(currentImportance)
|
val ignoreOutput = allAddingOutputsUnimportant(currentImportance)
|
||||||
@ -196,49 +176,35 @@ object ReverseFlowAnalyzerPerOpcode {
|
|||||||
STZ -> (importance => importance.copy(iz = Important, m = Important)),
|
STZ -> (importance => importance.copy(iz = Important, m = Important)),
|
||||||
SAX -> (importance => importance.copy(a = Important, x = Important)),
|
SAX -> (importance => importance.copy(a = Important, x = Important)),
|
||||||
|
|
||||||
|
INC -> (importance => importance.copy(n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
DEC -> (importance => importance.copy(n = Unimportant, z = Unimportant, m = Important)),
|
||||||
|
ROL -> (importance => importance.copy(n = Unimportant, z = Unimportant, c = Important, m = Important)),
|
||||||
|
ROR -> (importance => importance.copy(n = Unimportant, z = Unimportant, c = Important, m = Important)),
|
||||||
|
ASL -> (importance => importance.copy(n = Unimportant, z = Unimportant, c = Unimportant, m = Important)),
|
||||||
|
LSR -> (importance => importance.copy(n = Unimportant, z = Unimportant, c = Unimportant, m = Important)),
|
||||||
|
|
||||||
|
|
||||||
|
SBX -> (importance => importance.copy(a = Important, x = Important, n = Unimportant, z = Unimportant, c = Unimportant, m = Important)),
|
||||||
|
ANC -> (currentImportance => {
|
||||||
|
val ignoreOutput = allAddingOutputsUnimportant(currentImportance)
|
||||||
|
currentImportance.copy(
|
||||||
|
a = if (ignoreOutput) Unimportant else Important,
|
||||||
|
n = Unimportant, z = Unimportant, c = Unimportant,
|
||||||
|
m = Important)
|
||||||
|
}),
|
||||||
|
ALR -> (currentImportance => {
|
||||||
|
val ignoreOutput = allAddingOutputsUnimportant(currentImportance)
|
||||||
|
currentImportance.copy(
|
||||||
|
a = if (ignoreOutput) Unimportant else Important,
|
||||||
|
n = Unimportant, z = Unimportant, c = Unimportant,
|
||||||
|
m = Important)
|
||||||
|
}),
|
||||||
|
|
||||||
STA_W -> (importance => importance.copy(a = Important, ah = Important, m = Important)),
|
STA_W -> (importance => importance.copy(a = Important, ah = Important, m = Important)),
|
||||||
STX_W -> (importance => importance.copy(x = Important, w = Important)),
|
STX_W -> (importance => importance.copy(x = Important, w = Important)),
|
||||||
STY_W -> (importance => importance.copy(y = Important, w = Important)),
|
STY_W -> (importance => importance.copy(y = Important, w = Important)),
|
||||||
STZ_W -> (importance => importance.copy(iz = Important, m = Important)),
|
STZ_W -> (importance => importance.copy(iz = Important, m = Important)),
|
||||||
|
|
||||||
DEX -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)),
|
|
||||||
DEY -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)),
|
|
||||||
DEZ -> (_.copy(iz = Important, n = Unimportant, z = Unimportant)),
|
|
||||||
|
|
||||||
INX -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)),
|
|
||||||
INY -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)),
|
|
||||||
INZ -> (_.copy(iz = Important, n = Unimportant, z = Unimportant)),
|
|
||||||
|
|
||||||
DEX_W -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)),
|
|
||||||
DEY_W -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)),
|
|
||||||
INX_W -> (_.copy(x = Important, n = Unimportant, z = Unimportant, w = Important)),
|
|
||||||
INY_W -> (_.copy(y = Important, n = Unimportant, z = Unimportant, w = Important)),
|
|
||||||
|
|
||||||
PHP -> (_.copy(n = Important, c = Important, d = Important, z = Important, v = Important, m = Important, w = Important)),
|
|
||||||
PLP -> (_.copy(n = Unimportant, c = Unimportant, d = Unimportant, z = Unimportant, v = Unimportant, m = Unimportant, w = Unimportant)),
|
|
||||||
|
|
||||||
PHA -> (_.copy(a = Important, m = Important)),
|
|
||||||
PLA -> (_.copy(a = Unimportant, m = Important, n = Unimportant, z = Unimportant)),
|
|
||||||
PHX -> (_.copy(x = Important, w = Important)),
|
|
||||||
PLX -> (_.copy(x = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
|
||||||
PHY -> (_.copy(y = Important, w = Important)),
|
|
||||||
PLY -> (_.copy(y = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
|
||||||
PHZ -> (_.copy(iz = Important, w = Important)),
|
|
||||||
PLZ -> (_.copy(iz = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
|
||||||
|
|
||||||
PHA_W -> (_.copy(a = Important, ah = Important, m = Important)),
|
|
||||||
PLA_W -> (_.copy(a = Unimportant, ah = Unimportant, m = Important, n = Unimportant, z = Unimportant)),
|
|
||||||
PHX_W -> (_.copy(x = Important, w = Important)),
|
|
||||||
PLX_W -> (_.copy(x = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
|
||||||
PHY_W -> (_.copy(y = Important, w = Important)),
|
|
||||||
PLY_W -> (_.copy(y = Unimportant, w = Important, n = Unimportant, z = Unimportant)),
|
|
||||||
|
|
||||||
CLC -> (_.copy(c = Unimportant)),
|
|
||||||
SEC -> (_.copy(c = Unimportant)),
|
|
||||||
CLD -> (_.copy(d = Unimportant)),
|
|
||||||
SED -> (_.copy(d = Unimportant)),
|
|
||||||
CLV -> (_.copy(v = Unimportant)),
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode)
|
def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode)
|
||||||
|
@ -847,6 +847,56 @@ case class RefersTo(identifier: String, offset: Int = 999) extends TrivialAssemb
|
|||||||
override def toString: String = s"<$identifier+$offset>"
|
override def toString: String = s"<$identifier+$offset>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class RefersToOrUses(identifier: String, offset: Int = 999) extends TrivialAssemblyLinePattern {
|
||||||
|
override def apply(line: AssemblyLine): Boolean = {
|
||||||
|
line.addrMode match {
|
||||||
|
case AddrMode.ZeroPage | AddrMode.Absolute | AddrMode.LongAbsolute | AddrMode.Indirect => line.parameter match {
|
||||||
|
case MemoryAddressConstant(th) =>
|
||||||
|
(offset == 999 || offset == 0) && th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(nn, _)) =>
|
||||||
|
(offset == 999 || offset == nn) && th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Plus, NumericConstant(nn, _), MemoryAddressConstant(th)) =>
|
||||||
|
(offset == 999 || offset == nn) && th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Minus, MemoryAddressConstant(th), NumericConstant(nn, _)) =>
|
||||||
|
(offset == 999 || offset == -nn) && th.name == identifier
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
case AddrMode.IndexedY | AddrMode.LongIndexedY | AddrMode.IndexedZ | AddrMode.LongIndexedZ => line.parameter match {
|
||||||
|
case MemoryAddressConstant(th) =>
|
||||||
|
(offset == 999 || offset == 0 || offset == 1) && th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(nn, _)) =>
|
||||||
|
(offset == 999 || offset == nn || offset == nn + 1) && th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Plus, NumericConstant(nn, _), MemoryAddressConstant(th)) =>
|
||||||
|
(offset == 999 || offset == nn || offset == nn + 1) && th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Minus, MemoryAddressConstant(th), NumericConstant(nn, _)) =>
|
||||||
|
(offset == 999 || offset == -nn || offset == -nn + 1) && th.name == identifier
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
case AddrMode.AbsoluteX | AddrMode.AbsoluteY | AddrMode.AbsoluteIndexedX => line.parameter match {
|
||||||
|
case MemoryAddressConstant(th) =>
|
||||||
|
(offset == 999 || offset >= 0 && offset <= 255) && th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(nn, _)) =>
|
||||||
|
(offset == 999 || offset >= nn && offset <= nn + 255) && th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Plus, NumericConstant(nn, _), MemoryAddressConstant(th)) =>
|
||||||
|
(offset == 999 || offset >= nn && offset <= nn + 255) && th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Minus, MemoryAddressConstant(th), NumericConstant(nn, _)) =>
|
||||||
|
(offset == 999 || offset >= -nn && offset <= -nn + 255) && th.name == identifier
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
case AddrMode.IndexedX => line.parameter match {
|
||||||
|
case MemoryAddressConstant(th) => th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(nn, _)) => th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Plus, NumericConstant(nn, _), MemoryAddressConstant(th)) => th.name == identifier
|
||||||
|
case CompoundConstant(MathOperator.Minus, MemoryAddressConstant(th), NumericConstant(nn, _)) => th.name == identifier
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def toString: String = s"<$identifier+$offset>"
|
||||||
|
}
|
||||||
|
|
||||||
case class CallsAnyOf(identifiers: Set[String]) extends TrivialAssemblyLinePattern {
|
case class CallsAnyOf(identifiers: Set[String]) extends TrivialAssemblyLinePattern {
|
||||||
override def apply(line: AssemblyLine): Boolean = {
|
override def apply(line: AssemblyLine): Boolean = {
|
||||||
(line.addrMode == AddrMode.Absolute ||
|
(line.addrMode == AddrMode.Absolute ||
|
||||||
|
@ -3,7 +3,7 @@ package millfork.assembly.mos.opt
|
|||||||
import millfork.assembly.mos.Opcode._
|
import millfork.assembly.mos.Opcode._
|
||||||
import millfork.assembly.mos.AddrMode._
|
import millfork.assembly.mos.AddrMode._
|
||||||
import millfork.assembly.AssemblyOptimization
|
import millfork.assembly.AssemblyOptimization
|
||||||
import millfork.assembly.mos.AssemblyLine
|
import millfork.assembly.mos.{AssemblyLine, State}
|
||||||
import millfork.env.{CompoundConstant, Constant, MathOperator}
|
import millfork.env.{CompoundConstant, Constant, MathOperator}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,7 +16,7 @@ object ZeropageRegisterOptimizations {
|
|||||||
val ConstantMultiplication = new RuleBasedAssemblyOptimization("Constant multiplication",
|
val ConstantMultiplication = new RuleBasedAssemblyOptimization("Constant multiplication",
|
||||||
needsFlowInfo = FlowInfoRequirement.ForwardFlow,
|
needsFlowInfo = FlowInfoRequirement.ForwardFlow,
|
||||||
(HasOpcode(STA) & RefersTo("__reg", 0) & MatchAddrMode(0) & MatchParameter(1) & MatchA(4)) ~
|
(HasOpcode(STA) & RefersTo("__reg", 0) & MatchAddrMode(0) & MatchParameter(1) & MatchA(4)) ~
|
||||||
(Linear & Not(RefersTo("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~
|
(Linear & Not(RefersToOrUses("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||||
(HasOpcode(STA) & RefersTo("__reg", 1) & MatchA(5)) ~
|
(HasOpcode(STA) & RefersTo("__reg", 1) & MatchA(5)) ~
|
||||||
(Elidable & HasOpcode(JSR) & RefersTo("__mul_u8u8u8", 0)) ~~> { (code, ctx) =>
|
(Elidable & HasOpcode(JSR) & RefersTo("__mul_u8u8u8", 0)) ~~> { (code, ctx) =>
|
||||||
val product = ctx.get[Int](4) * ctx.get[Int](5)
|
val product = ctx.get[Int](4) * ctx.get[Int](5)
|
||||||
@ -26,7 +26,7 @@ object ZeropageRegisterOptimizations {
|
|||||||
// TODO: constants other than power of 2:
|
// TODO: constants other than power of 2:
|
||||||
|
|
||||||
(Elidable & HasOpcode(STA) & RefersTo("__reg", 0) & MatchAddrMode(0) & MatchParameter(1)) ~
|
(Elidable & HasOpcode(STA) & RefersTo("__reg", 0) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||||
(Linear & Not(RefersTo("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~
|
(Linear & Not(RefersToOrUses("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||||
(HasOpcode(STA) & RefersTo("__reg", 1) & MatchA(4)) ~
|
(HasOpcode(STA) & RefersTo("__reg", 1) & MatchA(4)) ~
|
||||||
Where(ctx => {
|
Where(ctx => {
|
||||||
val constant = ctx.get[Int](4)
|
val constant = ctx.get[Int](4)
|
||||||
@ -46,7 +46,7 @@ object ZeropageRegisterOptimizations {
|
|||||||
val constant = ctx.get[Int](4)
|
val constant = ctx.get[Int](4)
|
||||||
(constant & (constant - 1)) == 0
|
(constant & (constant - 1)) == 0
|
||||||
}) ~
|
}) ~
|
||||||
(Linear & Not(RefersTo("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~
|
(Linear & Not(RefersToOrUses("__reg", 1)) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||||
(HasOpcode(STA) & RefersTo("__reg", 1)) ~
|
(HasOpcode(STA) & RefersTo("__reg", 1)) ~
|
||||||
(Elidable & HasOpcode(JSR) & RefersTo("__mul_u8u8u8", 0)) ~~> { (code, ctx) =>
|
(Elidable & HasOpcode(JSR) & RefersTo("__mul_u8u8u8", 0)) ~~> { (code, ctx) =>
|
||||||
val constant = ctx.get[Int](4)
|
val constant = ctx.get[Int](4)
|
||||||
@ -70,9 +70,18 @@ object ZeropageRegisterOptimizations {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val DeadRegStoreFromFlow = new RuleBasedAssemblyOptimization("Dead zeropage register store from flow",
|
val DeadRegStoreFromFlow = new RuleBasedAssemblyOptimization("Dead zeropage register store from flow",
|
||||||
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
|
needsFlowInfo = FlowInfoRequirement.BothFlows,
|
||||||
(Elidable & HasOpcode(STA) & RefersTo("__reg", 0) & DoesntMatterWhatItDoesWithReg(0)) ~~> (_.tail),
|
(Elidable & HasOpcode(STA) & RefersTo("__reg", 0) & DoesntMatterWhatItDoesWithReg(0)) ~~> (_.tail),
|
||||||
(Elidable & HasOpcode(STA) & RefersTo("__reg", 1) & DoesntMatterWhatItDoesWithReg(1)) ~~> (_.tail),
|
(Elidable & HasOpcode(STA) & RefersTo("__reg", 1) & DoesntMatterWhatItDoesWithReg(1)) ~~> (_.tail),
|
||||||
|
|
||||||
|
(Elidable & HasOpcode(LDY) & RefersTo("__reg", 0)) ~
|
||||||
|
(Linear & Not(ConcernsY) & Not(RefersToOrUses("__reg", 0))).*.capture(2) ~
|
||||||
|
(Elidable & (HasA(0) & HasOpcode(STA) | HasOpcode(STZ)) & RefersTo("__reg", 0) & DoesntMatterWhatItDoesWith(State.A)) ~
|
||||||
|
((Linear & Not(ConcernsY) & Not(RefersToOrUses("__reg", 0))).* ~
|
||||||
|
(Elidable & RefersToOrUses("__reg", 0) & HasAddrMode(IndexedY) & DoesntMatterWhatItDoesWithReg(0) & DoesntMatterWhatItDoesWith(State.Y))).capture(3) ~~> ((code, ctx) =>
|
||||||
|
ctx.get[List[AssemblyLine]](2) ++ List(AssemblyLine.immediate(LDY, 0)) ++ ctx.get[List[AssemblyLine]](3)
|
||||||
|
)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val All: List[AssemblyOptimization[AssemblyLine]] = List(
|
val All: List[AssemblyOptimization[AssemblyLine]] = List(
|
||||||
|
Loading…
Reference in New Issue
Block a user