1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-05 09:28:54 +00:00

Z80: Better inlining of variables into register pairs

This commit is contained in:
Karol Stasiak 2018-08-08 17:52:08 +02:00
parent 019547aae8
commit 0cb91c0f68
2 changed files with 110 additions and 76 deletions

View File

@ -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",

View File

@ -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
}
}