1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-10-25 05:24:11 +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 package millfork.assembly.z80.opt
import millfork.assembly.AssemblyOptimization import millfork.assembly.AssemblyOptimization
import millfork.assembly.z80.{opt, _} import millfork.assembly.z80._
import millfork.assembly.z80.ZOpcode._ import millfork.assembly.z80.ZOpcode._
import millfork.env.{CompoundConstant, Constant, MathOperator, NumericConstant} import millfork.env.{CompoundConstant, Constant, MathOperator, NumericConstant}
import millfork.node.ZRegister import millfork.node.ZRegister
@ -786,6 +786,25 @@ object AlwaysGoodI80Optimizations {
(Elidable & Is8BitLoadTo(ZRegister.C) & MatchImmediate(0)) ~~> { (code, ctx) => (Elidable & Is8BitLoadTo(ZRegister.C) & MatchImmediate(0)) ~~> { (code, ctx) =>
List(ZLine.ldImm16(ZRegister.BC, (ctx.get[Constant](0) + ctx.get[Constant](1).asl(8)).quickSimplify)) 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", val UnusedCodeRemoval = new RuleBasedAssemblyOptimization("Unreachable code removal",

View File

@ -124,7 +124,7 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] {
case (v, range, _) => case (v, range, _) =>
log.debug(s"Inlining $v to register pair HL") log.debug(s"Inlining $v to register pair HL")
val oldCode = vs.codeWithFlow.slice(range.start, range.end) val oldCode = vs.codeWithFlow.slice(range.start, range.end)
val newCode = inlineVars(v, "", "", oldCode.map(_._2)) val newCode = inlineVars(v, "", "", oldCode)
reportOptimizedBlock(oldCode, newCode) reportOptimizedBlock(oldCode, newCode)
output ++= newCode output ++= newCode
i = range.end i = range.end
@ -138,7 +138,7 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] {
case (v, range, _) => case (v, range, _) =>
log.debug(s"Inlining $v to register pair BC") log.debug(s"Inlining $v to register pair BC")
val oldCode = vs.codeWithFlow.slice(range.start, range.end) val oldCode = vs.codeWithFlow.slice(range.start, range.end)
val newCode = inlineVars("", v, "", oldCode.map(_._2)) val newCode = inlineVars("", v, "", oldCode)
reportOptimizedBlock(oldCode, newCode) reportOptimizedBlock(oldCode, newCode)
output ++= newCode output ++= newCode
i = range.end i = range.end
@ -153,7 +153,7 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] {
case (v, range, _) => case (v, range, _) =>
log.debug(s"Inlining $v to register pair DE") log.debug(s"Inlining $v to register pair DE")
val oldCode = vs.codeWithFlow.slice(range.start, range.end) val oldCode = vs.codeWithFlow.slice(range.start, range.end)
val newCode = inlineVars("", "", v, oldCode.map(_._2)) val newCode = inlineVars("", "", v, oldCode)
reportOptimizedBlock(oldCode, newCode) reportOptimizedBlock(oldCode, newCode)
output ++= newCode output ++= newCode
i = range.end i = range.end
@ -192,15 +192,16 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] {
None None
} }
code match { code match {
case (_, ZLine(LD_16, TwoRegisters(BC, IMM_16), _, true)):: case (_, ZLine(LD_16, TwoRegisters(BC, IMM_16), _, true))::
(i, ZLine(ADD_16, TwoRegisters(HL, BC), _, true)) :: xs if target == BC => (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) else canBeInlined(vname, synced = true, target, xs)
case (_, ZLine(LD_16, TwoRegisters(DE, IMM_16), _, true)):: case (_, ZLine(LD_16, TwoRegisters(DE, IMM_16), _, true))::
(i, ZLine(ADD_16, TwoRegisters(HL, DE), _, true)) :: xs if target == DE => (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) else canBeInlined(vname, synced = true, target, xs)
case (_, ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th1), true)) :: 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] = { def inlineVars(hl: String, bc: String, de: String, code: List[(FlowInfo, ZLine)]): List[ZLine] = {
// if (code.nonEmpty) println(code.head) // if (code.nonEmpty) println(code.head)
code match { code match {
case (load@ZLine(LD_16, TwoRegisters(BC, IMM_16), _, _)) :: case (_, load@ZLine(LD_16, TwoRegisters(BC, IMM_16), _, _)) ::
ZLine(ADD_16, TwoRegisters(HL, BC), _, _) :: (f, add@ZLine(ADD_16, TwoRegisters(HL, BC), _, _)) ::
xs if bc != "" => xs if bc != "" =>
load.copy(registers = TwoRegisters(DE, IMM_16)) :: if (f.importanceAfter.getRegister(DE) == Important) {
ZLine.registers(ADD_16, HL, DE) :: ZLine.register(PUSH, BC) :: load :: add :: ZLine.register(POP, BC) :: inlineVars(hl, bc, de, xs)
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), _, _)) :: case (_, load@ZLine(LD_16, TwoRegisters(DE, IMM_16), _, _)) ::
ZLine(ADD_16, TwoRegisters(HL, DE), _, _) :: (f, add@ZLine(ADD_16, TwoRegisters(HL, DE), _, _)) ::
xs if de != "" => xs if de != "" =>
load.copy(registers = TwoRegisters(BC, IMM_16)) :: if (f.importanceAfter.getRegister(BC) == Important) {
ZLine.registers(ADD_16, HL, BC) :: ZLine.register(PUSH, DE) :: load :: add :: ZLine.register(POP, DE) :: inlineVars(hl, bc, de, xs)
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), _) :: case (_, ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), a1@MemoryAddressConstant(th1), _)) ::
ZLine(ADD_16, TwoRegisters(HL, reg@(DE | BC)), _, _) :: (_, ZLine(ADD_16, TwoRegisters(HL, reg@(DE | BC)), _, _)) ::
ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), a2@MemoryAddressConstant(th2), _) :: (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), a2@MemoryAddressConstant(th2), _)) ::
xs if hl != "" && th1.name != hl && th2.name != hl => xs if hl != "" && th1.name != hl && th2.name != hl=>
// bytes before: 3 + 1 + 3 = 7 // bytes before: 3 + 1 + 3 = 7
// cycles before: 16 + 11 + 16 = 43 // cycles before: 16 + 11 + 16 = 43
// bytes after: 3 + 1 + 3 + 3 + 1 + 3 = 14 // bytes after: 3 + 1 + 3 + 3 + 1 + 3 = 14
@ -330,99 +339,105 @@ object WordVariableToRegisterOptimization extends AssemblyOptimization[ZLine] {
ZLine.ldAbs8(a2 + 1, A) :: ZLine.ldAbs8(a2 + 1, A) ::
inlineVars(hl, bc, de, xs) inlineVars(hl, bc, de, xs)
case ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) :: case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _)) ::
(loadConst@ZLine(LD_16, TwoRegisters(BC, constSource), _, _)) :: (_, loadConst@ZLine(LD_16, TwoRegisters(BC, constSource), _, _)) ::
(add@ZLine(ADD_16, TwoRegisters(HL, BC), _, _)) :: xs if th.name == bc => (_, add@ZLine(ADD_16, TwoRegisters(HL, BC), _, _)) :: xs if th.name == bc =>
ZLine.ld8(B, H) :: ZLine.ld8(C, L) :: ZLine.ld8(B, H) :: ZLine.ld8(C, L) ::
loadConst.copy(registers = TwoRegisters(HL, constSource)) :: loadConst.copy(registers = TwoRegisters(HL, constSource)) ::
add.copy(registers = TwoRegisters(HL, BC)) :: inlineVars(hl, bc, de, xs) add.copy(registers = TwoRegisters(HL, BC)) :: inlineVars(hl, bc, de, xs)
case ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _) :: case (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _)) ::
(loadConst@ZLine(LD_16, TwoRegisters(DE, constSource), _, _)) :: (_, loadConst@ZLine(LD_16, TwoRegisters(DE, constSource), _, _)) ::
(add@ZLine(ADD_16, TwoRegisters(HL, DE), _, _)) :: xs if th.name == de => (_, add@ZLine(ADD_16, TwoRegisters(HL, DE), _, _)) :: xs if th.name == de =>
ZLine.ld8(D, H) :: ZLine.ld8(E, L) :: ZLine.ld8(D, H) :: ZLine.ld8(E, L) ::
loadConst.copy(registers = TwoRegisters(HL, constSource)) :: loadConst.copy(registers = TwoRegisters(HL, constSource)) ::
add.copy(registers = TwoRegisters(HL, DE)) :: inlineVars(hl, bc, de, xs) add.copy(registers = TwoRegisters(HL, DE)) :: inlineVars(hl, bc, de, xs)
// TODO: above with regs swapped // TODO: above with regs swapped
case (loadConst@ZLine(LD_16, TwoRegisters(t, constSource), _, _)) :: case (_, loadConst@ZLine(LD_16, TwoRegisters(t, constSource), _, _)) ::
ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) :: (_, 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 => (_, add@ZLine(ADD_16, TwoRegisters(HL, t2), _, _)) :: xs if th.name == bc && t == t2 && t != HL =>
loadConst.copy(registers = TwoRegisters(HL, constSource)) :: loadConst.copy(registers = TwoRegisters(HL, constSource)) ::
add.copy(registers = TwoRegisters(HL, BC)) :: inlineVars(hl, bc, de, xs) add.copy(registers = TwoRegisters(HL, BC)) :: inlineVars(hl, bc, de, xs)
case (loadConst@ZLine(LD_16, TwoRegisters(t, constSource),_,_)) :: case (_, loadConst@ZLine(LD_16, TwoRegisters(t, constSource),_,_)) ::
ZLine(LD_16, TwoRegisters(HL, MEM_ABS_16), MemoryAddressConstant(th), _) :: (_, 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 => (_, add@ZLine(ADD_16, TwoRegisters(HL, t2), _, _)) :: xs if th.name == de && t == t2 && t != HL =>
loadConst.copy(registers = TwoRegisters(HL, constSource)) :: loadConst.copy(registers = TwoRegisters(HL, constSource)) ::
add.copy(registers = TwoRegisters(HL, DE)) :: inlineVars(hl, bc, de, xs) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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 != "") { if (bc != "") {
ZLine.register(PUSH, BC) :: x :: ZLine.register(POP, BC) :: inlineVars(hl, bc, de, xs) ZLine.register(PUSH, BC) :: x :: ZLine.register(POP, BC) :: inlineVars(hl, bc, de, xs)
} else if (de != "") { } 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 => case x :: (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, HL), MemoryAddressConstant(th), _)) :: xs if x._2.changesRegister(HL) && th.name == hl =>
x :: inlineVars(hl, bc, de, xs) x._2 :: 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 => case x :: (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, BC), MemoryAddressConstant(th), _)) :: xs if x._2.changesRegister(BC) && th.name == bc =>
x :: inlineVars(hl, bc, de, xs) x._2 :: 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 => case x :: (_, ZLine(LD_16, TwoRegisters(MEM_ABS_16, DE), MemoryAddressConstant(th), _)) :: xs if x._2.changesRegister(DE) && th.name == de =>
x :: inlineVars(hl, bc, de, xs) x._2 :: inlineVars(hl, bc, de, xs)
case x :: _ if bc != "" && x.changesRegister(BC) => throw new IllegalStateException() case x :: _ if bc != "" && x._2.changesRegister(BC) => throw new IllegalStateException()
case x :: _ if de != "" && x.changesRegister(DE) => throw new IllegalStateException() case x :: _ if de != "" && x._2.changesRegister(DE) => throw new IllegalStateException()
case x :: _ if hl != "" && x.changesRegister(HL) => 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 case Nil => Nil
} }
} }