mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-09 09:41:23 +00:00
6502: Fix optimization bug (fixes #41) and add more optimizations involving ARR
This commit is contained in:
parent
d6fd1e8b77
commit
5c40d581c0
src
main/scala/millfork/assembly/mos/opt
test/scala/millfork/test
@ -1839,8 +1839,8 @@ object AlwaysGoodOptimizations {
|
||||
val ifSet = Elidable & HasOpcode(LDA) & HasImmediate(if (zeroIfSet) 0 else nonZero)
|
||||
val ifClear = Elidable & HasOpcode(LDA) & HasImmediate(if (zeroIfSet) nonZero else 0)
|
||||
val jump = Elidable & HasOpcodeIn(Set(JMP, if (firstSet) BCS else BCC, if (zeroIfSet) BEQ else BNE)) & MatchParameter(1)
|
||||
val elseLabel = Elidable & HasOpcode(LABEL) & MatchParameter(0)
|
||||
val afterLabel = Elidable & HasOpcode(LABEL) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z)
|
||||
val elseLabel = (Elidable & HasOpcode(LABEL) & MatchParameter(0)).capture(10)
|
||||
val afterLabel = Elidable & HasOpcode(LABEL) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z) & IsNotALabelUsedManyTimes
|
||||
val store = Elidable & (Not(ReadsC) & Linear | HasOpcodeIn(RTS, JSR, RTI, RTL, BSR))
|
||||
val secondReturn = (Elidable & (HasOpcodeIn(RTS, RTI) | NoopDiscardsFlags)).*.capture(6)
|
||||
val where = Where { ctx =>
|
||||
@ -1851,13 +1851,22 @@ object AlwaysGoodOptimizations {
|
||||
if (firstSet) test ~ ifSet ~ store.*.capture(4) ~ jump ~ elseLabel ~ ifClear ~ store.*.capture(5) ~ afterLabel ~ secondReturn ~ where
|
||||
else test ~ ifClear ~ store.*.capture(4) ~ jump ~ elseLabel ~ ifSet ~ store.*.capture(5) ~ afterLabel ~ secondReturn ~ where
|
||||
pattern ~~> { (_, ctx) =>
|
||||
val elseLabelUseCount = ctx.get[Constant](0) match {
|
||||
case MemoryAddressConstant(Label(label)) => ctx.labelUseCount(label)
|
||||
case _ => 9999
|
||||
}
|
||||
List(
|
||||
AssemblyLine.immediate(LDA, 0),
|
||||
AssemblyLine.implied(if (shift >= 4) ROR else ROL)) ++
|
||||
(if (shift >= 4) List.fill(7 - shift)(AssemblyLine.implied(LSR)) else List.fill(shift)(AssemblyLine.implied(ASL))) ++
|
||||
(if (zeroIfSet) List(AssemblyLine.immediate(EOR, nonZero)) else Nil) ++
|
||||
ctx.get[List[AssemblyLine]](5) ++
|
||||
ctx.get[List[AssemblyLine]](6)
|
||||
ctx.get[List[AssemblyLine]](6) ++ (
|
||||
if (elseLabelUseCount == 1) Nil
|
||||
else ctx.get[List[AssemblyLine]](10) ++ List(
|
||||
AssemblyLine.immediate(LDA, if (firstSet) (if (zeroIfSet) nonZero else 0) else (if (zeroIfSet) 0 else nonZero))
|
||||
) ++ ctx.get[List[AssemblyLine]](5) ++ ctx.get[List[AssemblyLine]](6)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,9 +178,13 @@ object UndocumentedOptimizations {
|
||||
val UseArr = new RuleBasedAssemblyOptimization("Using undocumented instruction ARR",
|
||||
needsFlowInfo = FlowInfoRequirement.BothFlows,
|
||||
(HasClear(State.D) & Elidable & HasOpcode(AND) & HasAddrMode(Immediate)) ~
|
||||
(Elidable & HasOpcode(ROR) & HasAddrMode(Implied) & DoesntMatterWhatItDoesWith(State.C, State.V)) ~~> { code =>
|
||||
(Elidable & HasOpcode(ROR) & HasAddrMode(Implied) & DoesntMatterWhatItDoesWith(State.C, State.V, State.N, State.Z)) ~~> { code =>
|
||||
List(AssemblyLine.immediate(ARR, code.head.parameter))
|
||||
},
|
||||
(HasClear(State.D) & Elidable & HasOpcode(LDA) & HasAddrMode(Immediate) & HasImmediate(0)) ~
|
||||
(Elidable & HasOpcode(ROR) & HasAddrMode(Implied) & DoesntMatterWhatItDoesWith(State.C, State.V, State.N, State.Z)) ~~> { code =>
|
||||
List(AssemblyLine.immediate(ARR, 0))
|
||||
},
|
||||
)
|
||||
|
||||
private def extraRmw(legal: Opcode.Value, illegal: Opcode.Value) =
|
||||
|
@ -816,4 +816,33 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers {
|
||||
m.readByte(0xc000) should equal(51)
|
||||
}
|
||||
}
|
||||
|
||||
test("Test bug #41") {
|
||||
val code =
|
||||
"""
|
||||
|struct Entity {
|
||||
| byte x,
|
||||
| byte y
|
||||
|}
|
||||
|
|
||||
|array(Entity) entities [2]
|
||||
|
|
||||
|byte output @$c000
|
||||
|
|
||||
|void main() {
|
||||
| if test(0, 200) {
|
||||
| output = 1
|
||||
| }
|
||||
|}
|
||||
|
|
||||
|inline bool test(byte i, byte y) {
|
||||
| return y >= entities[i].y && y <= entities[i].y + 8
|
||||
|}
|
||||
|
|
||||
|""".stripMargin
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(code) { m =>
|
||||
|
||||
}
|
||||
EmuUndocumentedRun(code)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user