diff --git a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala index 7cddd967..5eeca983 100644 --- a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala +++ b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala @@ -1,7 +1,7 @@ package millfork.assembly.z80.opt import millfork.assembly.AssemblyOptimization -import millfork.assembly.z80.{opt, _} +import millfork.assembly.z80._ import millfork.assembly.z80.ZOpcode._ import millfork.env.{CompoundConstant, Constant, MathOperator, NumericConstant} import millfork.node.ZRegister @@ -786,6 +786,25 @@ object AlwaysGoodI80Optimizations { (Elidable & Is8BitLoadTo(ZRegister.C) & MatchImmediate(0)) ~~> { (code, ctx) => List(ZLine.ldImm16(ZRegister.BC, (ctx.get[Constant](0) + ctx.get[Constant](1).asl(8)).quickSimplify)) }, + + // TODO: this is a bit controversial + // 41 cycles 6 bytes → 24 cycles 8 bytes + MultipleAssemblyRules(Seq(BC, DE).map{ reg => + (Elidable & HasOpcode(PUSH) & HasRegisterParam(reg)) ~ + (Elidable & HasOpcode(LD_16) & HasRegisters(TwoRegisters(reg, IMM_16)) & MatchParameter(0)) ~ + (Elidable & HasOpcode(ADD_16) & HasRegisters(TwoRegisters(HL, reg))) ~ + (Elidable & HasOpcode(POP) & HasRegisterParam(reg) & DoesntMatterWhatItDoesWithFlagsExceptCarry & DoesntMatterWhatItDoesWith(A)) ~~> { (code, ctx) => + val offset = ctx.get[Constant](0) + List( + ZLine.ld8(A, L), + ZLine.imm8(ADD, offset.loByte), + ZLine.ld8(L, A), + ZLine.ld8(A, H), + ZLine.imm8(ADC, offset.hiByte), + ZLine.ld8(H, A) + ) + } + }) ) val UnusedCodeRemoval = new RuleBasedAssemblyOptimization("Unreachable code removal", diff --git a/src/main/scala/millfork/assembly/z80/opt/WordVariableToRegisterOptimization.scala b/src/main/scala/millfork/assembly/z80/opt/WordVariableToRegisterOptimization.scala index b91278d5..82edcaa7 100644 --- a/src/main/scala/millfork/assembly/z80/opt/WordVariableToRegisterOptimization.scala +++ b/src/main/scala/millfork/assembly/z80/opt/WordVariableToRegisterOptimization.scala @@ -124,7 +124,7 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] { case (v, range, _) => log.debug(s"Inlining $v to register pair HL") val oldCode = vs.codeWithFlow.slice(range.start, range.end) - val newCode = inlineVars(v, "", "", oldCode.map(_._2)) + val newCode = inlineVars(v, "", "", oldCode) reportOptimizedBlock(oldCode, newCode) output ++= newCode i = range.end @@ -138,7 +138,7 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] { case (v, range, _) => log.debug(s"Inlining $v to register pair BC") val oldCode = vs.codeWithFlow.slice(range.start, range.end) - val newCode = inlineVars("", v, "", oldCode.map(_._2)) + val newCode = inlineVars("", v, "", oldCode) reportOptimizedBlock(oldCode, newCode) output ++= newCode i = range.end @@ -153,7 +153,7 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] { case (v, range, _) => log.debug(s"Inlining $v to register pair DE") val oldCode = vs.codeWithFlow.slice(range.start, range.end) - val newCode = inlineVars("", "", v, oldCode.map(_._2)) + val newCode = inlineVars("", "", v, oldCode) reportOptimizedBlock(oldCode, newCode) output ++= newCode i = range.end @@ -192,15 +192,16 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] { None } code match { - case (_, ZLine(LD_16, TwoRegisters(BC, IMM_16), _, true)):: (i, ZLine(ADD_16, TwoRegisters(HL, BC), _, true)) :: xs if target == BC => - if (i.importanceAfter.getRegister(BC) == Important || i.importanceAfter.getRegister(DE) == Important) fail(22) + if (i.importanceAfter.getRegister(BC) == Important) fail(22) + else if(i.importanceAfter.getRegister(DE) == Important) canBeInlined(vname, synced, target, xs).map(add(CyclesAndBytes(-21, -2))) else canBeInlined(vname, synced = true, target, xs) case (_, ZLine(LD_16, TwoRegisters(DE, IMM_16), _, true)):: (i, ZLine(ADD_16, TwoRegisters(HL, DE), _, true)) :: xs if target == DE => - if (i.importanceAfter.getRegister(BC) == Important || i.importanceAfter.getRegister(DE) == Important) fail(23) + if (i.importanceAfter.getRegister(DE) == Important) fail(23) + else if (i.importanceAfter.getRegister(BC) == Important) canBeInlined(vname, synced, target, xs).map(add(CyclesAndBytes(-21, -2))) else canBeInlined(vname, synced = true, target, xs) case (_, ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th1), true)) :: @@ -292,28 +293,36 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] { } } - def inlineVars(hl: String, bc: String, de: String, code: List[ZLine]): List[ZLine] = { -// if (code.nonEmpty) println(code.head) + def inlineVars(hl: String, bc: String, de: String, code: List[(FlowInfo, ZLine)]): List[ZLine] = { + // if (code.nonEmpty) println(code.head) code match { - case (load@ZLine(LD_16, TwoRegisters(BC, IMM_16), _, _)) :: - ZLine(ADD_16, TwoRegisters(HL, BC), _, _) :: + case (_, load@ZLine(LD_16, TwoRegisters(BC, IMM_16), _, _)) :: + (f, add@ZLine(ADD_16, TwoRegisters(HL, BC), _, _)) :: xs if bc != "" => - load.copy(registers = TwoRegisters(DE, IMM_16)) :: - ZLine.registers(ADD_16, HL, DE) :: - inlineVars(hl, bc, de, xs) + if (f.importanceAfter.getRegister(DE) == Important) { + ZLine.register(PUSH, BC) :: load :: add :: ZLine.register(POP, BC) :: inlineVars(hl, bc, de, xs) + } else { + load.copy(registers = TwoRegisters(DE, IMM_16)) :: + ZLine.registers(ADD_16, HL, DE) :: + inlineVars(hl, bc, de, xs) + } - case (load@ZLine(LD_16, TwoRegisters(DE, IMM_16), _, _)) :: - ZLine(ADD_16, TwoRegisters(HL, DE), _, _) :: + case (_, load@ZLine(LD_16, TwoRegisters(DE, IMM_16), _, _)) :: + (f, add@ZLine(ADD_16, TwoRegisters(HL, DE), _, _)) :: xs if de != "" => - load.copy(registers = TwoRegisters(BC, IMM_16)) :: - ZLine.registers(ADD_16, HL, BC) :: - inlineVars(hl, bc, de, xs) + if (f.importanceAfter.getRegister(BC) == Important) { + ZLine.register(PUSH, DE) :: load :: add :: ZLine.register(POP, DE) :: inlineVars(hl, bc, de, xs) + } else { + load.copy(registers = TwoRegisters(BC, IMM_16)) :: + ZLine.registers(ADD_16, HL, BC) :: + inlineVars(hl, bc, de, xs) + } - case ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), a1@MemoryAddressConstant(th1), _) :: - ZLine(ADD_16, TwoRegisters(HL, reg@(DE | BC)), _, _) :: - ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), a2@MemoryAddressConstant(th2), _) :: - xs if hl != "" && th1.name != hl && th2.name != hl => + case (_, ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), a1@MemoryAddressConstant(th1), _)) :: + (_, ZLine(ADD_16, TwoRegisters(HL, reg@(DE | BC)), _, _)) :: + (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), a2@MemoryAddressConstant(th2), _)) :: + xs if hl != "" && th1.name != hl && th2.name != hl=> // bytes before: 3 + 1 + 3 = 7 // cycles before: 16 + 11 + 16 = 43 // bytes after: 3 + 1 + 3 + 3 + 1 + 3 = 14 @@ -330,99 +339,105 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] { ZLine.ldAbs8(a2 + 1, A) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) :: - (loadConst@ZLine(LD_16, TwoRegisters(BC, constSource), _, _)) :: - (add@ZLine(ADD_16, TwoRegisters(HL, BC), _, _)) :: xs if th.name == bc => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _)) :: + (_, loadConst@ZLine(LD_16, TwoRegisters(BC, constSource), _, _)) :: + (_, add@ZLine(ADD_16, TwoRegisters(HL, BC), _, _)) :: xs if th.name == bc => ZLine.ld8(B, H) :: ZLine.ld8(C, L) :: loadConst.copy(registers = TwoRegisters(HL, constSource)) :: add.copy(registers = TwoRegisters(HL, BC)) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) :: - (loadConst@ZLine(LD_16, TwoRegisters(DE, constSource), _, _)) :: - (add@ZLine(ADD_16, TwoRegisters(HL, DE), _, _)) :: xs if th.name == de => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _)) :: + (_, loadConst@ZLine(LD_16, TwoRegisters(DE, constSource), _, _)) :: + (_, add@ZLine(ADD_16, TwoRegisters(HL, DE), _, _)) :: xs if th.name == de => ZLine.ld8(D, H) :: ZLine.ld8(E, L) :: loadConst.copy(registers = TwoRegisters(HL, constSource)) :: add.copy(registers = TwoRegisters(HL, DE)) :: inlineVars(hl, bc, de, xs) // TODO: above with regs swapped - case (loadConst@ZLine(LD_16, TwoRegisters(t, constSource), _, _)) :: - ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) :: - (add@ZLine(ADD_16, TwoRegisters(HL, t2), _, _)) :: xs if th.name == bc && t == t2 && t != HL => + case (_, loadConst@ZLine(LD_16, TwoRegisters(t, constSource), _, _)) :: + (_, ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _)) :: + (_, add@ZLine(ADD_16, TwoRegisters(HL, t2), _, _)) :: xs if th.name == bc && t == t2 && t != HL => loadConst.copy(registers = TwoRegisters(HL, constSource)) :: add.copy(registers = TwoRegisters(HL, BC)) :: inlineVars(hl, bc, de, xs) - case (loadConst@ZLine(LD_16, TwoRegisters(t, constSource),_,_)) :: - ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) :: - (add@ZLine(ADD_16, TwoRegisters(HL, t2), _, _)) :: xs if th.name == de && t == t2 && t != HL => + case (_, loadConst@ZLine(LD_16, TwoRegisters(t, constSource),_,_)) :: + (_, ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _)) :: + (_, add@ZLine(ADD_16, TwoRegisters(HL, t2), _, _)) :: xs if th.name == de && t == t2 && t != HL => loadConst.copy(registers = TwoRegisters(HL, constSource)) :: add.copy(registers = TwoRegisters(HL, DE)) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) :: xs if th.name == hl => + case (_, ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) ) :: xs if th.name == hl => inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) :: xs if th.name == hl => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) ) :: xs if th.name == hl => inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) :: xs if th.name == bc => + case (_, ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) ) :: xs if th.name == bc => ZLine.ld8(H, B) :: ZLine.ld8(L, C) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) :: xs if th.name == bc => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) ) :: xs if th.name == bc => ZLine.ld8(B, H) :: ZLine.ld8(C, L) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) :: xs if th.name == de => + case (_, ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) ) :: xs if th.name == de => ZLine.ld8(H, D) :: ZLine.ld8(L, E) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) :: xs if th.name == de => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) ) :: xs if th.name == de => ZLine.ld8(D, H) :: ZLine.ld8(E, L) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(DE, MEM_ABS_16), MemoryAddressConstant(th), _) :: xs if th.name == de => + case (_, ZLine(LD_16, TwoRegisters(DE, MEM_ABS_16), MemoryAddressConstant(th), _) ) :: xs if th.name == de => inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, DE), MemoryAddressConstant(th), _) :: xs if th.name == de => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, DE), MemoryAddressConstant(th), _) ) :: xs if th.name == de => inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(DE, MEM_ABS_16), MemoryAddressConstant(th), _) :: xs if th.name == bc => + case (_, ZLine(LD_16, TwoRegisters(DE, MEM_ABS_16), MemoryAddressConstant(th), _) ) :: xs if th.name == bc => ZLine.ld8(D, B) :: ZLine.ld8(E, C) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, DE), MemoryAddressConstant(th), _) :: xs if th.name == bc => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, DE), MemoryAddressConstant(th), _) ) :: xs if th.name == bc => ZLine.ld8(B, D) :: ZLine.ld8(C, E) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(DE, MEM_ABS_16), MemoryAddressConstant(th), _) :: xs if th.name == hl => + case (_, ZLine(LD_16, TwoRegisters(DE, MEM_ABS_16), MemoryAddressConstant(th), _) ) :: xs if th.name == hl => ZLine.ld8(D, H) :: ZLine.ld8(E, L) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, DE), MemoryAddressConstant(th), _) :: xs if th.name == hl => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, DE), MemoryAddressConstant(th), _) ) :: xs if th.name == hl => ZLine.ld8(H, D) :: ZLine.ld8(L, E) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(BC, MEM_ABS_16), MemoryAddressConstant(th), _) :: xs if th.name == bc => + case (_, ZLine(LD_16, TwoRegisters(BC, MEM_ABS_16), MemoryAddressConstant(th), _) ) :: xs if th.name == bc => inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, BC), MemoryAddressConstant(th), _) :: xs if th.name == bc => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, BC), MemoryAddressConstant(th), _) ) :: xs if th.name == bc => inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(BC, MEM_ABS_16), MemoryAddressConstant(th), _) :: xs if th.name == hl => + case (_, ZLine(LD_16, TwoRegisters(BC, MEM_ABS_16), MemoryAddressConstant(th), _) ) :: xs if th.name == hl => ZLine.ld8(B, H) :: ZLine.ld8(C, L) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, BC), MemoryAddressConstant(th), _) :: xs if th.name == hl => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, BC), MemoryAddressConstant(th), _) ) :: xs if th.name == hl => ZLine.ld8(H, B) :: ZLine.ld8(L, C) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(BC, MEM_ABS_16), MemoryAddressConstant(th), _) :: xs if th.name == de => + case (_, ZLine(LD_16, TwoRegisters(BC, MEM_ABS_16), MemoryAddressConstant(th), _) ) :: xs if th.name == de => ZLine.ld8(B, D) :: ZLine.ld8(C, E) :: inlineVars(hl, bc, de, xs) - case ZLine(LD_16, TwoRegisters(MEM_ABS_16, BC), MemoryAddressConstant(th), _) :: xs if th.name == de => + case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, BC), MemoryAddressConstant(th), _) ) :: xs if th.name == de => ZLine.ld8(D, B) :: ZLine.ld8(E, C) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(A, MEM_ABS_8), MemoryAddressConstant(th), _) :: xs if th.name == hl => + case (_, ZLine(LD, TwoRegisters(A, MEM_ABS_8), MemoryAddressConstant(th), _) ) :: xs if th.name == hl => ZLine.ld8(A, L) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(MEM_ABS_8, A), MemoryAddressConstant(th), _) :: xs if th.name == hl => + case (_, ZLine(LD, TwoRegisters(MEM_ABS_8, A), MemoryAddressConstant(th), _) ) :: xs if th.name == hl => ZLine.ld8(L, A) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(A, MEM_ABS_8), MemoryAddressConstant(th), _) :: xs if th.name == bc => + case (_, ZLine(LD, TwoRegisters(A, MEM_ABS_8), MemoryAddressConstant(th), _) ) :: xs if th.name == bc => ZLine.ld8(A, C) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(MEM_ABS_8, A), MemoryAddressConstant(th), _) :: xs if th.name == bc => + case (_, ZLine(LD, TwoRegisters(MEM_ABS_8, A), MemoryAddressConstant(th), _) ) :: xs if th.name == bc => ZLine.ld8(C, A) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(A, MEM_ABS_8), MemoryAddressConstant(th), _) :: xs if th.name == de => + case (_, ZLine(LD, TwoRegisters(A, MEM_ABS_8), MemoryAddressConstant(th), _) ) :: xs if th.name == de => ZLine.ld8(A, E) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(MEM_ABS_8, A), MemoryAddressConstant(th), _) :: xs if th.name == de => + case (_, ZLine(LD, TwoRegisters(MEM_ABS_8, A), MemoryAddressConstant(th), _) ) :: xs if th.name == de => ZLine.ld8(E, A) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(A, MEM_ABS_8), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) :: xs if th.name == hl => + case (_, ZLine(LD, TwoRegisters(A, MEM_ABS_8), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) ) :: xs if th.name == hl => ZLine.ld8(A, H) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(MEM_ABS_8, A), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) :: xs if th.name == hl => + case (_, ZLine(LD, TwoRegisters(MEM_ABS_8, A), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) ) :: xs if th.name == hl => ZLine.ld8(H, A) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(A, MEM_ABS_8), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) :: xs if th.name == bc => + case (_, ZLine(LD, TwoRegisters(A, MEM_ABS_8), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) ) :: xs if th.name == bc => ZLine.ld8(A, B) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(MEM_ABS_8, A), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) :: xs if th.name == bc => + case (_, ZLine(LD, TwoRegisters(MEM_ABS_8, A), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) ) :: xs if th.name == bc => ZLine.ld8(B, A) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(A, MEM_ABS_8), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) :: xs if th.name == de => + case (_, ZLine(LD, TwoRegisters(A, MEM_ABS_8), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) ) :: xs if th.name == de => ZLine.ld8(A, D) :: inlineVars(hl, bc, de, xs) - case ZLine(LD, TwoRegisters(MEM_ABS_8, A), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) :: xs if th.name == de => + case (_, ZLine(LD, TwoRegisters(MEM_ABS_8, A), CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(1, _)), _) ) :: xs if th.name == de => ZLine.ld8(D, A) :: inlineVars(hl, bc, de, xs) - case (x@ZLine(CALL, _, _, _)) :: xs => + case (_, l1@ZLine(LD_16, TwoRegisters(BC, IMM_16), _, _)) :: (_, l2@ZLine(ADD_16, TwoRegisters(HL, BC), _, _)) :: xs if bc != "" => + ZLine.register(PUSH, BC) :: l1 :: l2 :: ZLine.register(POP, BC) :: inlineVars(hl, bc, de, xs) + + case (_, l1@ZLine(LD_16, TwoRegisters(DE, IMM_16), _, _)) :: (_, l2@ZLine(ADD_16, TwoRegisters(HL, DE), _, _)) :: xs if de != "" => + ZLine.register(PUSH, DE) :: l1 :: l2 :: ZLine.register(POP, DE) :: inlineVars(hl, bc, de, xs) + + case (_, x@ZLine(CALL, _, _, _)) :: xs => if (bc != "") { ZLine.register(PUSH, BC) :: x :: ZLine.register(POP, BC) :: inlineVars(hl, bc, de, xs) } else if (de != "") { @@ -432,18 +447,18 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] { } - case x :: ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) :: xs if x.changesRegister(HL) && th.name == hl => - x :: inlineVars(hl, bc, de, xs) - case x :: ZLine(LD_16, TwoRegisters(MEM_ABS_16, BC), MemoryAddressConstant(th), _) :: xs if x.changesRegister(BC) && th.name == bc => - x :: inlineVars(hl, bc, de, xs) - case x :: ZLine(LD_16, TwoRegisters(MEM_ABS_16, DE), MemoryAddressConstant(th), _) :: xs if x.changesRegister(DE) && th.name == de => - x :: inlineVars(hl, bc, de, xs) + case x :: (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _)) :: xs if x._2.changesRegister(HL) && th.name == hl => + x._2 :: inlineVars(hl, bc, de, xs) + case x :: (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, BC), MemoryAddressConstant(th), _)) :: xs if x._2.changesRegister(BC) && th.name == bc => + x._2 :: inlineVars(hl, bc, de, xs) + case x :: (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, DE), MemoryAddressConstant(th), _)) :: xs if x._2.changesRegister(DE) && th.name == de => + x._2 :: inlineVars(hl, bc, de, xs) - case x :: _ if bc != "" && x.changesRegister(BC) => throw new IllegalStateException() - case x :: _ if de != "" && x.changesRegister(DE) => throw new IllegalStateException() - case x :: _ if hl != "" && x.changesRegister(HL) => throw new IllegalStateException() + case x :: _ if bc != "" && x._2.changesRegister(BC) => throw new IllegalStateException() + case x :: _ if de != "" && x._2.changesRegister(DE) => throw new IllegalStateException() + case x :: _ if hl != "" && x._2.changesRegister(HL) => throw new IllegalStateException() - case x :: xs => x :: inlineVars(hl, bc, de, xs) + case x :: xs => x._2 :: inlineVars(hl, bc, de, xs) case Nil => Nil } }