diff --git a/src/main/scala/millfork/assembly/opt/AlwaysGoodOptimizations.scala b/src/main/scala/millfork/assembly/opt/AlwaysGoodOptimizations.scala index 453c8928..2f9722bc 100644 --- a/src/main/scala/millfork/assembly/opt/AlwaysGoodOptimizations.scala +++ b/src/main/scala/millfork/assembly/opt/AlwaysGoodOptimizations.scala @@ -528,10 +528,10 @@ object AlwaysGoodOptimizations { val PointlessLoadBeforeTransfer = new RuleBasedAssemblyOptimization("Pointless load before transfer", needsFlowInfo = FlowInfoRequirement.BackwardFlow, - loadBeforeTransfer(LDX, LDA, ConcernsX, State.X, TXA, Set(ZeroPage, Absolute, IndexedY, AbsoluteY)), - loadBeforeTransfer(LDA, LDX, ConcernsA, State.A, TAX, Set(ZeroPage, Absolute, IndexedY, AbsoluteY)), - loadBeforeTransfer(LDY, LDA, ConcernsY, State.Y, TYA, Set(ZeroPage, Absolute, ZeroPageX, IndexedX, AbsoluteX)), - loadBeforeTransfer(LDA, LDY, ConcernsA, State.A, TAY, Set(ZeroPage, Absolute, ZeroPageX, IndexedX, AbsoluteX)), + loadBeforeTransfer(LDX, LDA, ConcernsX, State.X, TXA, Set(Immediate, ZeroPage, Absolute, IndexedY, AbsoluteY)), + loadBeforeTransfer(LDA, LDX, ConcernsA, State.A, TAX, Set(Immediate, ZeroPage, Absolute, IndexedY, AbsoluteY)), + loadBeforeTransfer(LDY, LDA, ConcernsY, State.Y, TYA, Set(Immediate, ZeroPage, Absolute, ZeroPageX, IndexedX, AbsoluteX)), + loadBeforeTransfer(LDA, LDY, ConcernsA, State.A, TAY, Set(Immediate, ZeroPage, Absolute, ZeroPageX, IndexedX, AbsoluteX)), ) private def immediateLoadBeforeTwoTransfers(ld1: Opcode.Value, ld2: Opcode.Value, concerns1: AssemblyLinePattern, overwrites1: State.Value, t12: Opcode.Value, t21: Opcode.Value) = @@ -916,9 +916,21 @@ object AlwaysGoodOptimizations { (Elidable & (HasOpcode(ORA) | HasOpcode(ADC) & HasClear(State.C) & HasClear(State.D)) & MatchAddrMode(0) & MatchParameter(1)) ~ (Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.C, State.N, State.Z, State.V, State.A)) ~~> { (code, ctx) => ctx.get[List[AssemblyLine]](3) ++ - List(AssemblyLine.implied(ROR), code.head.copy(opcode = ROL)) ++ + List(AssemblyLine.implied(LSR), code.head.copy(opcode = ROL)) ++ ctx.get[List[AssemblyLine]](2) }, + (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ + (Elidable & HasOpcodeIn(Set(ROL, ASL)) & DoesntMatterWhatItDoesWith(State.A)) ~ + (Linear & DoesNotConcernMemoryAt(0, 1)).* ~ + (Elidable & HasOpcodeIn(Set(ROL, ASL)) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code => + code.last :: code.drop(2).init + }, + (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ + (Elidable & HasOpcodeIn(Set(ROR, LSR)) & DoesntMatterWhatItDoesWith(State.A)) ~ + (Linear & DoesNotConcernMemoryAt(0, 1)).* ~ + (Elidable & HasOpcodeIn(Set(ROR, LSR)) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code => + code.last :: code.drop(2).init + }, ) private def blockIsIdempotentWhenItComesToIndexRegisters(i: Int) = Where(ctx => { diff --git a/src/test/scala/millfork/test/BitPackingSuite.scala b/src/test/scala/millfork/test/BitPackingSuite.scala index ea08f0e4..d0e530ed 100644 --- a/src/test/scala/millfork/test/BitPackingSuite.scala +++ b/src/test/scala/millfork/test/BitPackingSuite.scala @@ -1,6 +1,5 @@ package millfork.test -import millfork.error.ErrorReporting import millfork.test.emu.EmuBenchmarkRun import org.scalatest.{FunSuite, Matchers} @@ -126,4 +125,26 @@ class BitPackingSuite extends FunSuite with Matchers { m.readByte(0xc000) should equal(0x56) } } + + test("Reverse byte") { + EmuBenchmarkRun(""" + | word output_addr @$C000 + | void main () { + | byte i + | byte input + | byte output + | output_addr = output.addr + | input = $5A + | output = 0 + | for i,0,paralleluntil,8 { + | output <<= 1 + | output |= input & 1 + | input >>= 1 + | } + | } + """.stripMargin){m => + val addr = m.readWord(0xc000) + m.readByte(addr) should equal(0x5A) + } + } }