package millfork.assembly.opt import java.util.concurrent.atomic.AtomicInteger import millfork.assembly.{AddrMode, AssemblyLine, Opcode, State} import millfork.assembly.Opcode._ import millfork.assembly.AddrMode._ import millfork.assembly.OpcodeClasses._ import millfork.env.{Constant, NormalFunction, NumericConstant} /** * @author Karol Stasiak */ object UndocumentedOptimizations { val counter = new AtomicInteger(30000) def getNextLabel(prefix: String) = f".${prefix}%s__${counter.getAndIncrement()}%05d" // TODO: test these private val LaxAddrModeRestriction = Not(HasAddrModeIn(Set(AbsoluteX, ZeroPageX, IndexedX, Immediate))) //noinspection ScalaUnnecessaryParentheses val UseLax = new RuleBasedAssemblyOptimization("Using undocumented instruction LAX", needsFlowInfo = FlowInfoRequirement.BackwardFlow, (HasOpcode(LDA) & Elidable & MatchAddrMode(0) & MatchParameter(1) & LaxAddrModeRestriction) ~ (LinearOrLabel & Not(ConcernsA) & Not(ChangesMemory) & Not(HasOpcode(LDX))).*.capture(2) ~ (HasOpcode(LDX) & Elidable & MatchAddrMode(0) & MatchParameter(1)) ~~> { (code, ctx) => ctx.get[List[AssemblyLine]](2) :+ code.head.copy(opcode = LAX) }, (HasOpcode(LDX) & Elidable & MatchAddrMode(0) & MatchParameter(1) & LaxAddrModeRestriction) ~ (LinearOrLabel & Not(ConcernsX) & Not(ChangesMemory) & Not(HasOpcode(LDA))).*.capture(2) ~ (HasOpcode(LDA) & Elidable & MatchAddrMode(0) & MatchParameter(1)) ~~> { (code, ctx) => ctx.get[List[AssemblyLine]](2) :+ code.head.copy(opcode = LAX) }, (HasOpcode(LDA) & Elidable & LaxAddrModeRestriction) ~ (LinearOrLabel & Not(ConcernsA) & Not(ChangesMemory) & Not(HasOpcode(TAX))).*.capture(2) ~ (HasOpcode(TAX) & Elidable) ~~> { (code, ctx) => ctx.get[List[AssemblyLine]](2) :+ code.head.copy(opcode = LAX) }, (HasOpcode(LDX) & Elidable & LaxAddrModeRestriction) ~ (LinearOrLabel & Not(ConcernsX) & Not(ChangesMemory) & Not(HasOpcode(TXA))).*.capture(2) ~ (HasOpcode(TXA) & Elidable) ~~> { (code, ctx) => ctx.get[List[AssemblyLine]](2) :+ code.head.copy(opcode = LAX) }, (HasOpcode(LDA) & Elidable & MatchAddrMode(0) & MatchParameter(1) & LaxAddrModeRestriction) ~ (LinearOrLabel & Not(ConcernsX) & Not(ChangesA) & Not(ChangesMemory) & Not(HasOpcode(LDX))).*.capture(2) ~ (HasOpcode(LDX) & Elidable & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> { (code, ctx) => code.head.copy(opcode = LAX) :: ctx.get[List[AssemblyLine]](2) }, (HasOpcode(LDX) & Elidable & MatchAddrMode(0) & MatchParameter(1) & LaxAddrModeRestriction) ~ (LinearOrLabel & Not(ConcernsA) & Not(ChangesX) & Not(ChangesMemory) & Not(HasOpcode(LDA))).*.capture(2) ~ (HasOpcode(LDA) & Elidable & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> { (code, ctx) => code.head.copy(opcode = LAX) :: ctx.get[List[AssemblyLine]](2) }, (HasOpcode(LDA) & Elidable & LaxAddrModeRestriction) ~ (LinearOrLabel & Not(ConcernsX) & Not(ChangesA) & Not(ChangesMemory) & Not(HasOpcode(TAX))).*.capture(2) ~ (HasOpcode(TAX) & Elidable & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> { (code, ctx) => code.head.copy(opcode = LAX) :: ctx.get[List[AssemblyLine]](2) }, (HasOpcode(LDX) & Elidable & LaxAddrModeRestriction) ~ (LinearOrLabel & Not(ConcernsA) & Not(ChangesX) & Not(ChangesMemory) & Not(HasOpcode(TXA))).*.capture(2) ~ (HasOpcode(TXA) & Elidable & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> { (code, ctx) => code.head.copy(opcode = LAX) :: ctx.get[List[AssemblyLine]](2) }, ) val SaxModes: Set[AddrMode.Value] = Set(ZeroPage, IndexedX, ZeroPageY, Absolute) val UseSax = new RuleBasedAssemblyOptimization("Using undocumented instruction SAX", needsFlowInfo = FlowInfoRequirement.NoRequirement, (HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ (Linear & Not(ConcernsA) & Not(ConcernsX)).?.capture(10) ~ (HasOpcode(AND) & Elidable & MatchAddrMode(2) & MatchParameter(3) & Not(ReadsX)) ~ (Linear & Not(ConcernsA) & Not(ConcernsX)).?.capture(11) ~ (HasOpcode(STA) & Elidable & MatchAddrMode(4) & MatchParameter(5) & HasAddrModeIn(SaxModes) & DontMatchParameter(0)) ~ (Linear & Not(ConcernsA) & Not(ConcernsX) & Not(ChangesMemory)).?.capture(12) ~ (HasOpcode(LDA) & Elidable & MatchAddrMode(0) & MatchParameter(1)) ~ (LinearOrLabel & Not(ConcernsX)).*.capture(13) ~ OverwritesX ~~> { (code, ctx) => val lda = code.head val ldx = AssemblyLine(LDX, ctx.get[AddrMode.Value](2), ctx.get[Constant](3)) val sax = AssemblyLine(SAX, ctx.get[AddrMode.Value](4), ctx.get[Constant](5)) val fragment0 = lda :: ctx.get[List[AssemblyLine]](10) val fragment1 = ldx :: ctx.get[List[AssemblyLine]](11) val fragment2 = sax :: ctx.get[List[AssemblyLine]](12) val fragment3 = ctx.get[List[AssemblyLine]](13) List(fragment0, fragment1, fragment2, fragment3).flatten }, ) def andConstant(const: Constant, mask: Int): Option[Long] = const match { case NumericConstant(n, _) => Some(n & mask) case _ => None } val UseAnc = new RuleBasedAssemblyOptimization("Using undocumented instruction ANC", needsFlowInfo = FlowInfoRequirement.BothFlows, (Elidable & HasOpcode(LDA) & HasImmediate(0)) ~ (Elidable & HasOpcode(CLC)) ~~> (_ => List(AssemblyLine.immediate(ANC, 0))), (Elidable & HasOpcode(LDA) & HasImmediate(0) & HasClear(State.C)) ~~> (_ => List(AssemblyLine.immediate(ANC, 0))), (Elidable & HasOpcode(AND) & MatchImmediate(0)) ~ Where(c => andConstant(c.get[Constant](0), 0x80).contains(0)) ~ (Elidable & HasOpcode(CLC)) ~~> ((_, ctx) => List(AssemblyLine.immediate(ANC, ctx.get[Int](0)))), (Elidable & HasOpcode(AND) & MatchImmediate(0)) ~ Where(c => andConstant(c.get[Constant](0), 0x80).contains(0x80)) ~ (Elidable & HasOpcode(SEC)) ~~> ((_, ctx) => List(AssemblyLine.immediate(ANC, ctx.get[Int](0)))), (Elidable & HasOpcode(AND) & MatchImmediate(0)) ~ (Elidable & HasOpcode(CMP) & HasImmediate(0x80) & DoesntMatterWhatItDoesWith(State.Z, State.N)) ~~> ((_, ctx) => List(AssemblyLine.immediate(ANC, ctx.get[Int](0)))), (Elidable & HasOpcode(AND) & MatchImmediate(0)) ~ (Elidable & HasOpcode(CMP) & HasImmediate(0x80) & DoesntMatterWhatItDoesWith(State.Z, State.N)) ~~> ((_, ctx) => List(AssemblyLine.immediate(ANC, ctx.get[Int](0)))), (Elidable & HasOpcode(AND) & MatchImmediate(0) & HasClear(State.C)) ~ Where(c => andConstant(c.get[Constant](0), 0x80).contains(0)) ~~> ((_, ctx) => List(AssemblyLine.immediate(ANC, ctx.get[Int](0)))), (Elidable & HasOpcode(AND) & MatchImmediate(0) & HasSet(State.C)) ~ Where(c => andConstant(c.get[Constant](0), 0x80).contains(0)) ~~> ((_, ctx) => List(AssemblyLine.immediate(ANC, ctx.get[Int](0)))), (Elidable & HasOpcode(AND) & MatchImmediate(0)) ~ (Elidable & HasOpcodeIn(Set(ROL, ASL)) & HasAddrMode(Implied) & DoesntMatterWhatItDoesWith(State.Z, State.N, State.A)) ~~> ((_, ctx) => List(AssemblyLine.immediate(ANC, ctx.get[Int](0)))), ) val UseSbx = new RuleBasedAssemblyOptimization("Using undocumented instruction SBX", needsFlowInfo = FlowInfoRequirement.BothFlows, (Elidable & HasOpcode(DEX) & DoesntMatterWhatItDoesWith(State.A, State.C)).+.captureLength(0) ~ Where(_.get[Int](0) > 2) ~~> ((_, ctx) => List( AssemblyLine.implied(TXA), AssemblyLine.immediate(SBX, ctx.get[Int](0)), )), (Elidable & HasOpcode(INX) & DoesntMatterWhatItDoesWith(State.A, State.C)).+.captureLength(0) ~ Where(_.get[Int](0) > 2) ~~> ((_, ctx) => List( AssemblyLine.implied(TXA), AssemblyLine.immediate(SBX, 256 - ctx.get[Int](0)), )), HasOpcode(TXA) ~ (Elidable & HasOpcode(CLC)).? ~ (Elidable & HasClear(State.C) & HasClear(State.D) & HasOpcode(ADC) & MatchImmediate(0)) ~ (Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.C, State.A)) ~~> ((code, ctx) => List( code.head, AssemblyLine.immediate(SBX, 256 - ctx.get[Int](0)), )), HasOpcode(TXA) ~ (Elidable & HasOpcode(SEC)).? ~ (Elidable & HasSet(State.C) & HasClear(State.D) & HasOpcode(SBC) & MatchImmediate(0)) ~ (Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.C, State.A)) ~~> ((code, ctx) => List( code.head, AssemblyLine.immediate(SBX, ctx.get[Int](0)), )), ) val UseAlr = new RuleBasedAssemblyOptimization("Using undocumented instruction ALR", needsFlowInfo = FlowInfoRequirement.NoRequirement, (Elidable & HasOpcode(AND) & HasAddrMode(Immediate)) ~ (Elidable & HasOpcode(LSR) & HasAddrMode(Implied)) ~~> { (code, ctx) => List(AssemblyLine.immediate(ALR, code.head.parameter)) }, (Elidable & HasOpcode(LSR) & HasAddrMode(Implied)) ~ (Elidable & HasOpcode(CLC)) ~~> { (code, ctx) => List(AssemblyLine.immediate(ALR, 0xFE)) }, ) 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, ctx) => List(AssemblyLine.immediate(ARR, code.head.parameter)) }, ) private def trivialSequence1(o1: Opcode.Value, o2: Opcode.Value, extra: AssemblyLinePattern, combined: Opcode.Value) = (Elidable & HasOpcode(o1) & HasAddrMode(Absolute) & MatchAddrMode(0) & MatchParameter(1)) ~ (Linear & DoesNotConcernMemoryAt(0, 1) & extra).* ~ (Elidable & HasOpcode(o2) & HasAddrMode(Absolute) & MatchParameter(1)) ~~> { (code, ctx) => code.tail.init :+ AssemblyLine(combined, Absolute, ctx.get[Constant](1)) } private def trivialSequence2(o1: Opcode.Value, o2: Opcode.Value, extra: AssemblyLinePattern, combined: Opcode.Value) = (Elidable & HasOpcode(o1) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~ (Linear & DoesNotConcernMemoryAt(0, 1) & extra).* ~ (Elidable & HasOpcode(o2) & MatchAddrMode(0) & MatchParameter(1)) ~~> { (code, ctx) => code.tail.init :+ AssemblyLine(combined, ctx.get[AddrMode.Value](0), ctx.get[Constant](1)) } // ROL c LDA c AND d => LDA d RLA c private def trivialCommutativeSequence(o1: Opcode.Value, o2: Opcode.Value, combined: Opcode.Value) = { (Elidable & HasOpcode(o1) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~ (Elidable & HasOpcode(LDA) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~ (Elidable & HasOpcode(o2) & MatchAddrMode(2) & MatchParameter(3)) ~~> { code => List(code(2).copy(opcode = LDA), code(1).copy(opcode = combined)) } } val UseSlo = new RuleBasedAssemblyOptimization("Using undocumented instruction SLO", needsFlowInfo = FlowInfoRequirement.NoRequirement, trivialSequence1(ASL, ORA, Not(ConcernsC), SLO), trivialSequence2(ASL, ORA, Not(ConcernsC), SLO), trivialCommutativeSequence(ASL, ORA, SLO), (Elidable & HasOpcode(ASL) & MatchAddrMode(0) & MatchParameter(1)) ~ (Linear & Not(ConcernsMemory)).* ~ (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~~> { (code, ctx) => code.tail.init ++ List(AssemblyLine.immediate(LDA, 0), AssemblyLine(SLO, ctx.get[AddrMode.Value](0), ctx.get[Constant](1))) }, (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ (Linear & Not(ConcernsMemory) & Not(ChangesA)).*.capture(2) ~ (Elidable & HasOpcode(ASL) & HasAddrMode(Implied)) ~ (Linear & Not(ConcernsMemory) & Not(ChangesA) & Not(ReadsC) & Not(ReadsNOrZ)).*.capture(3) ~ (Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1)) ~~> { (code, ctx) => List(AssemblyLine.immediate(LDA, 0), AssemblyLine(SRE, ctx.get[AddrMode.Value](0), ctx.get[Constant](1))) ++ ctx.get[List[AssemblyLine]](2) ++ ctx.get[List[AssemblyLine]](3) }, ) val UseSre = new RuleBasedAssemblyOptimization("Using undocumented instruction SRE", needsFlowInfo = FlowInfoRequirement.NoRequirement, trivialSequence1(LSR, EOR, Not(ConcernsC), SRE), trivialSequence2(LSR, EOR, Not(ConcernsC), SRE), trivialCommutativeSequence(LSR, EOR, SRE), (Elidable & HasOpcode(LSR) & MatchAddrMode(0) & MatchParameter(1)) ~ (Linear & Not(ConcernsMemory)).* ~ (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~~> { (code, ctx) => code.tail.init ++ List(AssemblyLine.immediate(LDA, 0), AssemblyLine(SRE, ctx.get[AddrMode.Value](0), ctx.get[Constant](1))) }, (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ (Linear & Not(ConcernsMemory) & Not(ChangesA)).*.capture(2) ~ (Elidable & HasOpcode(LSR) & HasAddrMode(Implied)) ~ (Linear & Not(ConcernsMemory) & Not(ChangesA) & Not(ReadsC) & Not(ReadsNOrZ)).*.capture(3) ~ (Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1)) ~~> { (code, ctx) => List(AssemblyLine.immediate(LDA, 0), AssemblyLine(SRE, ctx.get[AddrMode.Value](0), ctx.get[Constant](1))) ++ ctx.get[List[AssemblyLine]](2) ++ ctx.get[List[AssemblyLine]](3) }, ) val UseRla = new RuleBasedAssemblyOptimization("Using undocumented instruction RLA", needsFlowInfo = FlowInfoRequirement.NoRequirement, trivialSequence1(ROL, AND, Not(ConcernsC), RLA), trivialSequence2(ROL, AND, Not(ConcernsC), RLA), trivialCommutativeSequence(ROL, AND, RLA), ) val UseRra = new RuleBasedAssemblyOptimization("Using undocumented instruction RRA", needsFlowInfo = FlowInfoRequirement.NoRequirement, // TODO: is it ok? carry flag and stuff? trivialSequence1(ROR, ADC, Not(ConcernsC), RRA), trivialSequence2(ROR, ADC, Not(ConcernsC), RRA), trivialCommutativeSequence(ROR, ADC, RRA), ) val UseDcp = new RuleBasedAssemblyOptimization("Using undocumented instruction DCP", needsFlowInfo = FlowInfoRequirement.BothFlows, trivialSequence1(DEC, CMP, Not(ConcernsC), DCP), trivialSequence2(DEC, CMP, Not(ConcernsC), DCP), (Elidable & HasOpcode(LDA) & HasAddrModeIn(Set(IndexedX, ZeroPageX, AbsoluteX))) ~ (Elidable & HasOpcode(TAX)) ~ (Elidable & HasOpcode(DEC) & HasAddrMode(AbsoluteX) & DoesntMatterWhatItDoesWith(State.A, State.Y, State.X, State.C, State.Z, State.N, State.V)) ~~> { code => List(code.head.copy(opcode = LDY), code.last.copy(opcode = DCP, addrMode = AbsoluteY)) }, (Elidable & HasOpcode(DEC) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~ (Elidable & HasOpcode(LDA) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~ (Elidable & HasOpcode(CMP) & MatchAddrMode(2) & MatchParameter(3) & DoesntMatterWhatItDoesWith(State.V, State.C, State.N, State.A)) ~~> { code => List(code(2).copy(opcode = LDA), code(1).copy(opcode = DCP)) } ) val UseIsc = new RuleBasedAssemblyOptimization("Using undocumented instruction ISC", needsFlowInfo = FlowInfoRequirement.BothFlows, trivialSequence1(INC, SBC, Not(ReadsC), ISC), trivialSequence2(INC, SBC, Not(ReadsC), ISC), (Elidable & HasOpcode(LDA) & HasImmediate(0) & HasClear(State.D)) ~ (Elidable & HasOpcode(ADC) & MatchAddrMode(1) & MatchParameter(2) & HasAddrModeIn(Set(IndexedX, IndexedY, AbsoluteY))) ~ (Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchParameter(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code => val label = getNextLabel("is") List( AssemblyLine.relative(BCC, label), code.last.copy(opcode = ISC), AssemblyLine.label(label)) }, (Elidable & HasOpcode(LDA) & MatchAddrMode(1) & MatchParameter(2) & HasAddrModeIn(Set(IndexedX, IndexedY, AbsoluteY))) ~ (Elidable & HasOpcode(ADC) & HasImmediate(0) & HasClear(State.D)) ~ (Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchParameter(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code => val label = getNextLabel("is") List( AssemblyLine.relative(BCC, label), code.last.copy(opcode = ISC), AssemblyLine.label(label)) }, (Elidable & HasOpcode(CLC)).? ~ (Elidable & HasOpcode(LDA) & HasImmediate(1) & HasClear(State.D) & HasClear(State.C)) ~ (Elidable & HasOpcode(ADC) & MatchAddrMode(1) & MatchParameter(2) & HasAddrModeIn(Set(IndexedX, IndexedY, AbsoluteY))) ~ (Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchParameter(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code => List(code.last.copy(opcode = ISC)) }, (Elidable & HasOpcode(CLC)).? ~ (Elidable & HasOpcode(LDA) & MatchAddrMode(1) & HasClear(State.D) & HasClear(State.C) & MatchAddrMode(2) & HasAddrModeIn(Set(IndexedX, IndexedY, AbsoluteY))) ~ (Elidable & HasOpcode(ADC) & HasImmediate(1)) ~ (Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchAddrMode(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code => List(code.last.copy(opcode = ISC)) }, (Elidable & HasOpcode(SEC)).? ~ (Elidable & HasOpcode(LDA) & HasImmediate(0) & HasClear(State.D) & HasSet(State.C)) ~ (Elidable & HasOpcode(ADC) & MatchAddrMode(1) & MatchParameter(2) & HasAddrModeIn(Set(IndexedX, IndexedY, AbsoluteY))) ~ (Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchParameter(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code => List(code.last.copy(opcode = ISC)) }, (Elidable & HasOpcode(SEC)).? ~ (Elidable & HasOpcode(LDA) & MatchAddrMode(1) & HasClear(State.D) & HasSet(State.C) & MatchAddrMode(2) & HasAddrModeIn(Set(IndexedX, IndexedY, AbsoluteY))) ~ (Elidable & HasOpcode(ADC) & HasImmediate(0)) ~ (Elidable & HasOpcode(STA) & MatchAddrMode(1) & MatchAddrMode(2) & DoesntMatterWhatItDoesWith(State.A, State.C, State.Z, State.N, State.V)) ~~> { code => List(code.last.copy(opcode = ISC)) }, (Elidable & HasOpcode(LDA) & HasAddrModeIn(Set(IndexedX, ZeroPageX, AbsoluteX))) ~ (Elidable & HasOpcode(TAX)) ~ (Elidable & HasOpcode(INC) & HasAddrMode(AbsoluteX) & DoesntMatterWhatItDoesWith(State.A, State.Y, State.X, State.C, State.Z, State.N, State.V)) ~~> { code => List(code.head.copy(opcode = LDY), code.last.copy(opcode = ISC, addrMode = AbsoluteY)) }, (Elidable & HasOpcode(INC) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~ (Elidable & HasOpcode(LDA) & Not(HasAddrMode(Immediate)) & MatchAddrMode(0) & MatchParameter(1)) ~ (Elidable & HasOpcode(CMP) & HasClear(State.D) & MatchAddrMode(2) & MatchParameter(3) & DoesntMatterWhatItDoesWith(State.V, State.C, State.N, State.A)) ~~> { code => List(code(2).copy(opcode = LDA), AssemblyLine.implied(SEC), code(1).copy(opcode = ISC)) } ) val All: List[AssemblyOptimization] = List( UseLax, UseSax, UseSbx, UseAnc, UseSlo, UseSre, UseAlr, UseArr, UseRla, UseRra, UseIsc, UseDcp, ) }