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

Z80: More optimizations

This commit is contained in:
Karol Stasiak 2018-08-01 10:22:34 +02:00
parent ec9dba9d27
commit bebb8c45a5
4 changed files with 79 additions and 2 deletions

View File

@ -14,6 +14,7 @@ object ZFlag extends Enumeration {
val Z, P, C, S, H, N = Value
val AllButSZ: Seq[Value] = Seq(P, C, H, N)
val AllButZ: Seq[Value] = Seq(P, C, H, N, S)
}
sealed trait ZRegisters

View File

@ -5,6 +5,7 @@ import millfork.assembly.z80._
import millfork.assembly.z80.ZOpcode._
import millfork.env.{CompoundConstant, Constant, MathOperator, NumericConstant}
import millfork.node.ZRegister
import ZRegister._
/**
* Optimizations valid for Intel8080, Z80, EZ80 and Sharp
@ -742,8 +743,61 @@ object AlwaysGoodI80Optimizations {
ZLine.implied(RLCA),
ZLine.imm8(AND, 7))
},
(Elidable & HasOpcode(RR) & HasRegisterParam(ZRegister.A) & DoesntMatterWhatItDoesWithFlagsExceptCarry) ~~> {_ =>
List(ZLine.implied(RRA))
},
(Elidable & HasOpcode(RRC) & HasRegisterParam(ZRegister.A) & DoesntMatterWhatItDoesWithFlagsExceptCarry) ~~> {_ =>
List(ZLine.implied(RRCA))
},
(Elidable & HasOpcode(RL) & HasRegisterParam(ZRegister.A) & DoesntMatterWhatItDoesWithFlagsExceptCarry) ~~> {_ =>
List(ZLine.implied(RLA))
},
(Elidable & HasOpcode(RLC) & HasRegisterParam(ZRegister.A) & DoesntMatterWhatItDoesWithFlagsExceptCarry) ~~> {_ =>
List(ZLine.implied(RLCA))
},
)
val PointlessExdehl = new RuleBasedAssemblyOptimization("Pointless EX DE,HL",
needsFlowInfo = FlowInfoRequirement.NoRequirement,
(Elidable & HasOpcode(EX_DE_HL)) ~
(Elidable & (
HasOpcode(LD_16) & (HasRegisters(TwoRegisters(DE, IMM_16)) | HasRegisters(TwoRegisters(HL, IMM_16)) | HasRegisters(TwoRegisters(BC, IMM_16))) |
Is8BitLoad(A, H) |
Is8BitLoad(A, L) |
Is8BitLoad(A, D) |
Is8BitLoad(A, E) |
Is8BitLoad(H, A) |
Is8BitLoad(L, A) |
Is8BitLoad(D, A) |
Is8BitLoad(E, A) |
HasOpcodeIn(Set(POP, PUSH, INC_16, DEC_16)) |
HasOpcodeIn(Set(INC, DEC, ADD, ADC, SUB, SBC, RLA, RLA, RRCA, RRCA, RL, RR, RRC, RLC, AND, XOR, OR, CP))
)).* ~
(Elidable & HasOpcode(EX_DE_HL)) ~~> { code =>
code.tail.init.map { line =>
line.registers match {
case OneRegister(HL) => line.copy(registers = OneRegister(DE))
case OneRegister(DE) => line.copy(registers = OneRegister(HL))
case TwoRegisters(HL, source) => line.copy(registers = TwoRegisters(DE, source))
case TwoRegisters(DE, source) => line.copy(registers = TwoRegisters(HL, source))
case TwoRegisters(H, r) => line.copy(registers = TwoRegisters(D, r))
case TwoRegisters(L, r) => line.copy(registers = TwoRegisters(E, r))
case TwoRegisters(D, r) => line.copy(registers = TwoRegisters(H, r))
case TwoRegisters(E, r) => line.copy(registers = TwoRegisters(L, r))
case TwoRegisters(r, H) => line.copy(registers = TwoRegisters(r, D))
case TwoRegisters(r, L) => line.copy(registers = TwoRegisters(r, E))
case TwoRegisters(r, D) => line.copy(registers = TwoRegisters(r, H))
case TwoRegisters(r, E) => line.copy(registers = TwoRegisters(r, L))
case _ => line
}
}
},
)
val All: List[AssemblyOptimization[ZLine]] = List[AssemblyOptimization[ZLine]](
BranchInPlaceRemoval,
FreeHL,

View File

@ -3,8 +3,9 @@ package millfork.assembly.z80.opt
import millfork.assembly.AssemblyOptimization
import millfork.assembly.z80._
import millfork.assembly.z80.ZOpcode._
import millfork.env.{CompoundConstant, Constant, MathOperator, NumericConstant}
import millfork.env.Constant
import millfork.node.ZRegister
import ZRegister._
/**
* Optimizations valid for Z80 and EZ80
@ -81,6 +82,17 @@ object AlwaysGoodZ80Optimizations {
(Elidable & HasOpcode(NEG)) ~
(Elidable & HasOpcode(ADD) & Has8BitImmediate(0xff) & DoesntMatterWhatItDoesWithFlags) ~~> (_ => List(ZLine.implied(CPL))),
(Elidable & HasOpcode(OR) & HasRegisters(OneRegister(A)) & HasRegister(BC, 0)) ~
(Elidable & HasOpcode(SBC_16) & HasRegisters(TwoRegisters(HL, BC)) & DoesntMatterWhatItDoesWithFlagsExceptZero) ~~> { code =>
List(ZLine.ld8(A, H), ZLine.register(OR, L))
},
(Elidable & HasOpcode(OR) & HasRegisters(OneRegister(A)) & HasRegister(DE, 0)) ~
(Elidable & HasOpcode(SBC_16) & HasRegisters(TwoRegisters(HL, DE)) & DoesntMatterWhatItDoesWithFlagsExceptZero) ~~> { code =>
List(ZLine.ld8(A, H), ZLine.register(OR, L))
},
)
val FreeHL = new RuleBasedAssemblyOptimization("Free HL (Z80)",

View File

@ -621,11 +621,21 @@ case object DoesntMatterWhatItDoesWithFlagsOtherThanSZ extends AssemblyLinePatte
override def toString: String = "[¯\\_(ツ)_/¯:NPVH]"
}
case object DoesntMatterWhatItDoesWithFlagsExceptCarry extends AssemblyLinePattern {
case object DoesntMatterWhatItDoesWithFlagsExceptZero extends AssemblyLinePattern {
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
FlowInfoRequirement.assertBackward(needsFlowInfo)
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: ZLine): Boolean =
ZFlag.AllButZ.forall(r => flowInfo.importanceAfter.getFlag(r) != Important)
override def toString: String = "[¯\\_(ツ)_/¯:NPVHS]"
}
case object DoesntMatterWhatItDoesWithFlagsExceptCarry extends AssemblyLinePattern {
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
FlowInfoRequirement.assertBackward(needsFlowInfo)
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: ZLine): Boolean =
ZFlag.values.forall(r => r == ZFlag.C || flowInfo.importanceAfter.getFlag(r) != Important)