mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-23 23:30:22 +00:00
Track equality of S and X. Add relevant optimizations.
This commit is contained in:
parent
bc21e5befc
commit
456c674a0c
@ -217,6 +217,20 @@ object AlwaysGoodOptimizations {
|
||||
pointlessImmediateStoreToTheSameVariable(MatchX(0), STX, MatchY(0), STY),
|
||||
pointlessImmediateStoreToTheSameVariable(MatchY(0), STY, MatchY(0), STY),
|
||||
|
||||
(HasOpcode(PHA)) ~
|
||||
(Linear & Not(ChangesA) & Not(ChangesStack) & Not(ChangesMemory)).* ~
|
||||
(Elidable & XContainsStackPointer & HasOpcode(STA) & HasAddrMode(AbsoluteX) & HasParameterWhere(p => p.quickSimplify match {
|
||||
case NumericConstant(n, _) => n == 0x101
|
||||
case _ => false
|
||||
})) ~~> (_.init),
|
||||
|
||||
(HasOpcode(PHA)) ~
|
||||
(Linear & Not(ChangesA) & Not(ChangesStack) & Not(ChangesMemory)).* ~
|
||||
(Elidable & HasOpcode(STA) & HasAddrMode(Stack) & HasParameterWhere(p => p.quickSimplify match {
|
||||
case NumericConstant(n, _) => n == 1
|
||||
case _ => false
|
||||
})) ~~> (_.init)
|
||||
|
||||
)
|
||||
|
||||
val PointlessStashingForLaterStore = new RuleBasedAssemblyOptimization("Pointless stashing for later store",
|
||||
@ -1093,6 +1107,18 @@ object AlwaysGoodOptimizations {
|
||||
HasOpcodeIn(Set(TYA, TAY)) ~
|
||||
(Not(Set(TYA, TAY)) & Linear & Not(ChangesA) & Not(ChangesY)).* ~
|
||||
(Elidable & HasOpcodeIn(Set(TYA, TAY)) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(Set(STA, LDA)) & HasAddrModeIn(Set(ZeroPage, Absolute)) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(HasOpcode(TAX)) & Not(ChangesA) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
HasOpcode(TAX) ~
|
||||
(LinearOrBranch & Not(ChangesX) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Elidable & HasOpcode(LDX) & HasAddrModeIn(Set(ZeroPage, Absolute)) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
|
||||
(HasOpcodeIn(Set(STA, LDA)) & HasAddrModeIn(Set(ZeroPage, Absolute)) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(Linear & Not(HasOpcode(TAY)) & Not(ChangesA) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
HasOpcode(TAY) ~
|
||||
(LinearOrBranch & Not(ChangesY) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(Elidable & HasOpcode(LDY) & HasAddrModeIn(Set(ZeroPage, Absolute)) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
|
||||
)
|
||||
|
||||
val RearrangableLoadFromTheSameLocation = new RuleBasedAssemblyOptimization("Rearrangable load from the same location",
|
||||
|
@ -62,7 +62,7 @@ object CoarseFlowAnalyzer {
|
||||
|
||||
case AssemblyLine(opcode, addrMode, _, _) =>
|
||||
currentStatus = currentStatus.copy(src = AnyStatus)
|
||||
if (OpcodeClasses.ChangesX(opcode)) currentStatus = currentStatus.copy(x = AnyStatus)
|
||||
if (OpcodeClasses.ChangesX(opcode)) currentStatus = currentStatus.copy(x = AnyStatus, eqSX = false)
|
||||
if (OpcodeClasses.ChangesY(opcode)) currentStatus = currentStatus.copy(y = AnyStatus)
|
||||
if (OpcodeClasses.ChangesAAlways(opcode)) currentStatus = currentStatus.copy(a = AnyStatus, a0 = AnyStatus, a7 = AnyStatus)
|
||||
if (addrMode == Implied && OpcodeClasses.ChangesAIfImplied(opcode)) currentStatus = currentStatus.copy(a = AnyStatus, a0 = AnyStatus, a7 = AnyStatus)
|
||||
@ -71,6 +71,7 @@ object CoarseFlowAnalyzer {
|
||||
if (OpcodeClasses.ChangesNAndZ(opcode)) currentStatus = currentStatus.nz
|
||||
if (OpcodeClasses.ChangesC(opcode)) currentStatus = currentStatus.copy(c = AnyStatus)
|
||||
if (OpcodeClasses.ChangesV(opcode)) currentStatus = currentStatus.copy(v = AnyStatus)
|
||||
if (OpcodeClasses.ChangesStack(opcode) || OpcodeClasses.ChangesS(opcode)) currentStatus = currentStatus.copy(eqSX = false)
|
||||
}
|
||||
}
|
||||
// flagArray.zip(codeArray).foreach{
|
||||
|
@ -48,6 +48,7 @@ case class CpuStatus(a: Status[Int] = UnknownStatus,
|
||||
y: Status[Int] = UnknownStatus,
|
||||
iz: Status[Int] = UnknownStatus,
|
||||
src: Status[SourceOfNZ] = UnknownStatus,
|
||||
eqSX: Boolean = false,
|
||||
z: Status[Boolean] = UnknownStatus,
|
||||
n: Status[Boolean] = UnknownStatus,
|
||||
c: Status[Boolean] = UnknownStatus,
|
||||
@ -115,6 +116,7 @@ case class CpuStatus(a: Status[Int] = UnknownStatus,
|
||||
y = this.y ~ that.y,
|
||||
iz = this.iz ~ that.iz,
|
||||
src = this.src ~ that.src,
|
||||
eqSX = this.eqSX && that.eqSX,
|
||||
z = this.z ~ that.z,
|
||||
n = this.n ~ that.n,
|
||||
c = this.c ~ that.c,
|
||||
|
@ -15,7 +15,7 @@ object FlowAnalyzerForImmediate {
|
||||
if ((nn & 1) != 0) currentStatus = currentStatus.copy(c = Status.SingleFalse)
|
||||
if ((nn & 2) != 0) currentStatus = currentStatus.copy(z = Status.SingleFalse)
|
||||
if ((nn & 8) != 0) currentStatus = currentStatus.copy(d = Status.SingleFalse)
|
||||
if ((nn & 0x10) != 0) currentStatus = currentStatus.copy(w = Status.SingleFalse)
|
||||
if ((nn & 0x10) != 0) currentStatus = currentStatus.copy(w = Status.SingleFalse, eqSX = false)
|
||||
if ((nn & 0x20) != 0) currentStatus = currentStatus.copy(m = Status.SingleFalse)
|
||||
if ((nn & 0x40) != 0) currentStatus = currentStatus.copy(v = Status.SingleFalse)
|
||||
if ((nn & 0x80) != 0) currentStatus = currentStatus.copy(n = Status.SingleFalse)
|
||||
@ -26,7 +26,7 @@ object FlowAnalyzerForImmediate {
|
||||
if ((nn & 1) != 0) currentStatus = currentStatus.copy(c = Status.SingleTrue)
|
||||
if ((nn & 2) != 0) currentStatus = currentStatus.copy(z = Status.SingleTrue)
|
||||
if ((nn & 8) != 0) currentStatus = currentStatus.copy(d = Status.SingleTrue)
|
||||
if ((nn & 0x10) != 0) currentStatus = currentStatus.copy(w = Status.SingleTrue)
|
||||
if ((nn & 0x10) != 0) currentStatus = currentStatus.copy(w = Status.SingleTrue, eqSX = false)
|
||||
if ((nn & 0x20) != 0) currentStatus = currentStatus.copy(m = Status.SingleTrue)
|
||||
if ((nn & 0x40) != 0) currentStatus = currentStatus.copy(v = Status.SingleTrue)
|
||||
if ((nn & 0x80) != 0) currentStatus = currentStatus.copy(n = Status.SingleTrue)
|
||||
@ -34,7 +34,7 @@ object FlowAnalyzerForImmediate {
|
||||
},
|
||||
LDX -> {(nn, currentStatus) =>
|
||||
val n = nn & 0xff
|
||||
currentStatus.nz(n).copy(x = SingleStatus(n), src = SourceOfNZ.X)
|
||||
currentStatus.nz(n).copy(x = SingleStatus(n), src = SourceOfNZ.X, eqSX = false)
|
||||
},
|
||||
LDY -> {(nn, currentStatus) =>
|
||||
val n = nn & 0xff
|
||||
@ -54,7 +54,7 @@ object FlowAnalyzerForImmediate {
|
||||
},
|
||||
LDX_W -> {(nn, currentStatus) =>
|
||||
val n = nn & 0xff
|
||||
currentStatus.nzw(nn).copy(x = SingleStatus(n), src = AnyStatus)
|
||||
currentStatus.nzw(nn).copy(x = SingleStatus(n), src = AnyStatus, eqSX = false)
|
||||
},
|
||||
LDY_W -> {(nn, currentStatus) =>
|
||||
val n = nn & 0xff
|
||||
@ -251,6 +251,17 @@ object FlowAnalyzerForImmediate {
|
||||
z = currentStatus.iz.map(v => (v & 0xff) == (nn & 0xff)),
|
||||
src = if (nn == 0) SourceOfNZ.Z else AnyStatus)
|
||||
},
|
||||
|
||||
SBX -> { (nn, currentStatus) =>
|
||||
val newX = (currentStatus.x <*> currentStatus.a) { (x, a) => (x - (x & a)) & 0xff }
|
||||
currentStatus.copy(
|
||||
x = newX,
|
||||
n = newX.n(),
|
||||
z = newX.z(),
|
||||
c = AnyStatus,
|
||||
eqSX = false,
|
||||
src = SourceOfNZ.X)
|
||||
}
|
||||
)
|
||||
|
||||
def hasDefinition(opcode: Opcode.Value): Boolean = map.contains(opcode)
|
||||
|
@ -15,28 +15,30 @@ object FlowAnalyzerForImplied {
|
||||
RTI -> identity,
|
||||
SEI -> identity,
|
||||
CLI -> identity,
|
||||
TXS -> identity,
|
||||
PHP -> identity,
|
||||
PHA -> identity,
|
||||
PHA_W -> identity,
|
||||
PHX -> identity,
|
||||
PHX_W -> identity,
|
||||
PHY -> identity,
|
||||
PHY_W -> identity,
|
||||
PHZ -> identity,
|
||||
PHD -> identity,
|
||||
PHK -> identity,
|
||||
PHB -> identity,
|
||||
TXS -> (_.copy(eqSX = true)),
|
||||
PHP -> (_.copy(eqSX = false)),
|
||||
PHA -> (_.copy(eqSX = false)),
|
||||
PHA_W -> (_.copy(eqSX = false)),
|
||||
PHX -> (_.copy(eqSX = false)),
|
||||
PHX_W -> (_.copy(eqSX = false)),
|
||||
PHY -> (_.copy(eqSX = false)),
|
||||
PHY_W -> (_.copy(eqSX = false)),
|
||||
PHZ -> (_.copy(eqSX = false)),
|
||||
PHD -> (_.copy(eqSX = false)),
|
||||
PHK -> (_.copy(eqSX = false)),
|
||||
PHB -> (_.copy(eqSX = false)),
|
||||
SED -> (_.copy(d = Status.SingleTrue)),
|
||||
CLD -> (_.copy(d = Status.SingleFalse)),
|
||||
CLC -> (_.copy(c = Status.SingleFalse)),
|
||||
SEC -> (_.copy(c = Status.SingleTrue)),
|
||||
CLV -> (_.copy(v = Status.SingleFalse)),
|
||||
XCE -> (_.copy(c = AnyStatus, m = AnyStatus, x = AnyStatus)),
|
||||
PLA -> (_.copy(src = SourceOfNZ.A, a = AnyStatus, n = AnyStatus, z = AnyStatus)),
|
||||
PLX -> (_.copy(src = SourceOfNZ.X, x = AnyStatus, n = AnyStatus, z = AnyStatus)),
|
||||
PLY -> (_.copy(src = SourceOfNZ.Y, y = AnyStatus, n = AnyStatus, z = AnyStatus)),
|
||||
PLZ -> (_.copy(src = SourceOfNZ.Z, iz = AnyStatus, n = AnyStatus, z = AnyStatus)),
|
||||
XCE -> (_.copy(c = AnyStatus, m = AnyStatus, w = AnyStatus, x = AnyStatus, y = AnyStatus, eqSX = false)),
|
||||
PLA -> (_.copy(src = SourceOfNZ.A, a = AnyStatus, n = AnyStatus, z = AnyStatus, eqSX = false)),
|
||||
PLX -> (_.copy(src = SourceOfNZ.X, x = AnyStatus, n = AnyStatus, z = AnyStatus, eqSX = false)),
|
||||
PLX_W -> (_.copy(src = SourceOfNZ.X, x = AnyStatus, n = AnyStatus, z = AnyStatus, eqSX = false)),
|
||||
PLY -> (_.copy(src = SourceOfNZ.Y, y = AnyStatus, n = AnyStatus, z = AnyStatus, eqSX = false)),
|
||||
PLY_W -> (_.copy(src = SourceOfNZ.Y, y = AnyStatus, n = AnyStatus, z = AnyStatus, eqSX = false)),
|
||||
PLZ -> (_.copy(src = SourceOfNZ.Z, iz = AnyStatus, n = AnyStatus, z = AnyStatus, eqSX = false)),
|
||||
XBA -> (currentStatus => currentStatus.copy(
|
||||
a = currentStatus.ah,
|
||||
a0 = currentStatus.ah.bit0,
|
||||
@ -51,6 +53,7 @@ object FlowAnalyzerForImplied {
|
||||
n = newX.n(),
|
||||
z = newX.z(),
|
||||
x = newX,
|
||||
eqSX = false,
|
||||
src = SourceOfNZ.X)
|
||||
}),
|
||||
DEX -> (currentStatus => {
|
||||
@ -59,6 +62,7 @@ object FlowAnalyzerForImplied {
|
||||
n = newX.n(),
|
||||
z = newX.z(),
|
||||
x = newX,
|
||||
eqSX = false,
|
||||
src = SourceOfNZ.X)
|
||||
}),
|
||||
INY -> (currentStatus => {
|
||||
@ -129,6 +133,7 @@ object FlowAnalyzerForImplied {
|
||||
n = AnyStatus,
|
||||
z = newX.z().withHiddenHi,
|
||||
x = newX,
|
||||
eqSX = false,
|
||||
src = AnyStatus)
|
||||
}),
|
||||
DEX_W -> (currentStatus => {
|
||||
@ -137,6 +142,7 @@ object FlowAnalyzerForImplied {
|
||||
n = AnyStatus,
|
||||
z = newX.z().withHiddenHi,
|
||||
x = newX,
|
||||
eqSX = false,
|
||||
src = AnyStatus)
|
||||
}),
|
||||
INY_W -> (currentStatus => {
|
||||
@ -182,6 +188,7 @@ object FlowAnalyzerForImplied {
|
||||
TAX -> (currentStatus => {
|
||||
currentStatus.copy(
|
||||
x = currentStatus.a,
|
||||
eqSX = false,
|
||||
n = currentStatus.a.n(),
|
||||
z = currentStatus.a.z(),
|
||||
src = SourceOfNZ.AX)
|
||||
@ -221,6 +228,7 @@ object FlowAnalyzerForImplied {
|
||||
TYX -> (currentStatus => {
|
||||
currentStatus.copy(
|
||||
x = currentStatus.y,
|
||||
eqSX = false,
|
||||
n = currentStatus.y.n(),
|
||||
z = currentStatus.y.z(),
|
||||
src = SourceOfNZ.XY)
|
||||
@ -246,6 +254,7 @@ object FlowAnalyzerForImplied {
|
||||
a = currentStatus.x,
|
||||
a0 = currentStatus.x.bit0,
|
||||
a7 = currentStatus.x.bit7,
|
||||
eqSX = false,
|
||||
x = currentStatus.a)
|
||||
}),
|
||||
SAY -> (currentStatus => {
|
||||
@ -258,6 +267,7 @@ object FlowAnalyzerForImplied {
|
||||
SXY -> (currentStatus => {
|
||||
currentStatus.copy(
|
||||
y = currentStatus.x,
|
||||
eqSX = false,
|
||||
x = currentStatus.y)
|
||||
}),
|
||||
ASL -> (currentStatus => {
|
||||
@ -362,6 +372,7 @@ object FlowAnalyzerForImplied {
|
||||
TSX -> (currentStatus => {
|
||||
currentStatus.copy(
|
||||
x = AnyStatus,
|
||||
eqSX = true,
|
||||
src = SourceOfNZ.X)
|
||||
}),
|
||||
)
|
||||
|
@ -558,6 +558,14 @@ case class HasSet(state: State.Value) extends AssemblyLinePattern {
|
||||
flowInfo.hasSet(state)
|
||||
}
|
||||
|
||||
case object XContainsStackPointer extends AssemblyLinePattern {
|
||||
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
|
||||
FlowInfoRequirement.assertForward(needsFlowInfo)
|
||||
|
||||
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: AssemblyLine): Boolean =
|
||||
flowInfo.statusBefore.eqSX
|
||||
}
|
||||
|
||||
case class HasSourceOfNZ(state: State.Value) extends AssemblyLinePattern {
|
||||
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
|
||||
FlowInfoRequirement.assertForward(needsFlowInfo)
|
||||
|
Loading…
Reference in New Issue
Block a user