mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-12 19:29:51 +00:00
Optimization fixes and improvements for Z80
This commit is contained in:
parent
ed067d3a67
commit
619bf8116a
@ -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.{TwoRegisters, ZLine, ZOpcode}
|
import millfork.assembly.z80.{OneRegister, TwoRegisters, ZLine, ZOpcode}
|
||||||
import millfork.assembly.z80.ZOpcode._
|
import millfork.assembly.z80.ZOpcode._
|
||||||
import millfork.env.{Constant, NumericConstant}
|
import millfork.env.{Constant, NumericConstant}
|
||||||
import millfork.node.ZRegister
|
import millfork.node.ZRegister
|
||||||
@ -69,6 +69,18 @@ object AlwaysGoodZ80Optimizations {
|
|||||||
(Linear & Not(Changes(register))).* ~
|
(Linear & Not(Changes(register))).* ~
|
||||||
(Elidable & Is16BitLoad(register, ZRegister.IMM_16) & MatchImmediate(0)) ~~> (_.init)
|
(Elidable & Is16BitLoad(register, ZRegister.IMM_16) & MatchImmediate(0)) ~~> (_.init)
|
||||||
),
|
),
|
||||||
|
|
||||||
|
(Elidable & Is8BitLoadTo(ZRegister.MEM_HL)) ~
|
||||||
|
(Linear & Not(ConcernsMemory) & Not(Changes(ZRegister.HL))).* ~
|
||||||
|
Is8BitLoadTo(ZRegister.MEM_HL) ~~> (_.tail),
|
||||||
|
|
||||||
|
(Elidable & Is8BitLoadTo(ZRegister.MEM_DE)) ~
|
||||||
|
(Linear & Not(ConcernsMemory) & Not(Changes(ZRegister.DE))).* ~
|
||||||
|
Is8BitLoadTo(ZRegister.MEM_DE) ~~> (_.tail),
|
||||||
|
|
||||||
|
(Elidable & Is8BitLoadTo(ZRegister.MEM_BC)) ~
|
||||||
|
(Linear & Not(ConcernsMemory) & Not(Changes(ZRegister.BC))).* ~
|
||||||
|
Is8BitLoadTo(ZRegister.MEM_BC) ~~> (_.tail),
|
||||||
)
|
)
|
||||||
|
|
||||||
private def simplifiable16BitAddWithSplitTarget(targetH: ZRegister.Value, targetL: ZRegister.Value, target: ZRegister.Value, source: ZRegister.Value) = MultipleAssemblyRules(List(
|
private def simplifiable16BitAddWithSplitTarget(targetH: ZRegister.Value, targetL: ZRegister.Value, target: ZRegister.Value, source: ZRegister.Value) = MultipleAssemblyRules(List(
|
||||||
@ -147,6 +159,23 @@ object AlwaysGoodZ80Optimizations {
|
|||||||
code.head.copy(opcode = LD, registers = TwoRegisters(ZRegister.A, ZRegister.MEM_ABS_8)),
|
code.head.copy(opcode = LD, registers = TwoRegisters(ZRegister.A, ZRegister.MEM_ABS_8)),
|
||||||
code(1).copy(registers = TwoRegisters(code(1).registers.asInstanceOf[TwoRegisters].target, ZRegister.A)),
|
code(1).copy(registers = TwoRegisters(code(1).registers.asInstanceOf[TwoRegisters].target, ZRegister.A)),
|
||||||
)),
|
)),
|
||||||
|
(Elidable & Is16BitLoad(ZRegister.HL, ZRegister.IMM_16)) ~
|
||||||
|
(Elidable & Is8BitLoad(ZRegister.D, ZRegister.H)) ~
|
||||||
|
(Elidable & Is8BitLoad(ZRegister.E, ZRegister.L) & DoesntMatterWhatItDoesWith(ZRegister.HL)) ~~> (code =>
|
||||||
|
List(
|
||||||
|
code.head.copy(registers = TwoRegisters(ZRegister.DE, ZRegister.IMM_16))
|
||||||
|
)),
|
||||||
|
(Elidable & Is16BitLoad(ZRegister.HL, ZRegister.IMM_16)) ~
|
||||||
|
(Elidable & Is8BitLoad(ZRegister.B, ZRegister.H)) ~
|
||||||
|
(Elidable & Is8BitLoad(ZRegister.C, ZRegister.L) & DoesntMatterWhatItDoesWith(ZRegister.HL)) ~~> (code =>
|
||||||
|
List(
|
||||||
|
code.head.copy(registers = TwoRegisters(ZRegister.BC, ZRegister.IMM_16))
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
|
||||||
|
val UnusedLabelRemoval = new RuleBasedAssemblyOptimization("Unused label removal",
|
||||||
|
needsFlowInfo = FlowInfoRequirement.JustLabels,
|
||||||
|
(Elidable & HasOpcode(LABEL) & HasCallerCount(0)) ~~> (_ => Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
val All: List[AssemblyOptimization[ZLine]] = List[AssemblyOptimization[ZLine]](
|
val All: List[AssemblyOptimization[ZLine]] = List[AssemblyOptimization[ZLine]](
|
||||||
@ -155,6 +184,7 @@ object AlwaysGoodZ80Optimizations {
|
|||||||
PointlessLoad,
|
PointlessLoad,
|
||||||
ReloadingKnownValueFromMemory,
|
ReloadingKnownValueFromMemory,
|
||||||
SimplifiableMaths,
|
SimplifiableMaths,
|
||||||
|
UnusedLabelRemoval,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package millfork.assembly.z80.opt
|
package millfork.assembly.z80.opt
|
||||||
|
|
||||||
import millfork.assembly.mos.{AssemblyLine, OpcodeClasses}
|
|
||||||
import millfork.assembly.opt.{AnyStatus, SingleStatus}
|
import millfork.assembly.opt.{AnyStatus, SingleStatus}
|
||||||
import millfork.assembly.z80.{OneRegister, TwoRegisters, ZLine, ZOpcodeClasses}
|
import millfork.assembly.z80.{OneRegister, TwoRegisters, ZLine, ZOpcodeClasses}
|
||||||
import millfork.env.{Label, MemoryAddressConstant, NormalFunction, NumericConstant}
|
import millfork.env.{Label, MemoryAddressConstant, NormalFunction, NumericConstant}
|
||||||
@ -35,6 +34,7 @@ object CoarseFlowAnalyzer {
|
|||||||
case ZLine(LABEL, _, MemoryAddressConstant(Label(l)), _) =>
|
case ZLine(LABEL, _, MemoryAddressConstant(Label(l)), _) =>
|
||||||
val L = l
|
val L = l
|
||||||
currentStatus = codeArray.indices.flatMap(j => codeArray(j) match {
|
currentStatus = codeArray.indices.flatMap(j => codeArray(j) match {
|
||||||
|
case ZLine(DJNZ, _, MemoryAddressConstant(Label(L)), _) => Some(flagArray(j).copy(b = AnyStatus))
|
||||||
case ZLine(_, _, MemoryAddressConstant(Label(L)), _) => Some(flagArray(j))
|
case ZLine(_, _, MemoryAddressConstant(Label(L)), _) => Some(flagArray(j))
|
||||||
case _ => None
|
case _ => None
|
||||||
}).fold(currentStatus)(_ ~ _)
|
}).fold(currentStatus)(_ ~ _)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package millfork.assembly.z80.opt
|
package millfork.assembly.z80.opt
|
||||||
|
|
||||||
import millfork.CompilationOptions
|
import millfork.CompilationOptions
|
||||||
import millfork.assembly.mos.{AssemblyLine, Opcode, State}
|
import millfork.assembly.z80.{ZLine, ZOpcode}
|
||||||
import millfork.assembly.z80.ZLine
|
|
||||||
import millfork.env.{Label, MemoryAddressConstant, NormalFunction}
|
import millfork.env.{Label, MemoryAddressConstant, NormalFunction}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,7 +43,7 @@ object FlowAnalyzer {
|
|||||||
val labelMap: (() => Option[Map[String, Int]]) = () => req match {
|
val labelMap: (() => Option[Map[String, Int]]) = () => req match {
|
||||||
case FlowInfoRequirement.NoRequirement => None
|
case FlowInfoRequirement.NoRequirement => None
|
||||||
case _ => Some(code.flatMap {
|
case _ => Some(code.flatMap {
|
||||||
case ZLine(op, _, MemoryAddressConstant(Label(l)), _) if op != Opcode.LABEL => Some(l)
|
case ZLine(op, _, MemoryAddressConstant(Label(l)), _) if op != ZOpcode.LABEL => Some(l)
|
||||||
case _ => None
|
case _ => None
|
||||||
}.groupBy(identity).mapValues(_.size))
|
}.groupBy(identity).mapValues(_.size))
|
||||||
}
|
}
|
||||||
|
@ -456,6 +456,11 @@ case class MatchParameter(i: Int) extends AssemblyLinePattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class MatchOpcode(i: Int) extends AssemblyLinePattern {
|
||||||
|
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: ZLine): Boolean =
|
||||||
|
ctx.addObject(i, line.opcode)
|
||||||
|
}
|
||||||
|
|
||||||
case class HasRegister(register: ZRegister.Value, value: Int) extends AssemblyLinePattern {
|
case class HasRegister(register: ZRegister.Value, value: Int) extends AssemblyLinePattern {
|
||||||
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
|
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
|
||||||
FlowInfoRequirement.assertForward(needsFlowInfo)
|
FlowInfoRequirement.assertForward(needsFlowInfo)
|
||||||
@ -615,7 +620,7 @@ case class Is16BitLoad(target:ZRegister.Value, source: ZRegister.Value) extends
|
|||||||
case class IsRegular8BitLoadFrom(source: ZRegister.Value) extends TrivialAssemblyLinePattern {
|
case class IsRegular8BitLoadFrom(source: ZRegister.Value) extends TrivialAssemblyLinePattern {
|
||||||
override def apply(line: ZLine): Boolean =
|
override def apply(line: ZLine): Boolean =
|
||||||
line.opcode == ZOpcode.LD && line.registers.asInstanceOf[TwoRegisters].source == source && (line.registers.asInstanceOf[TwoRegisters].target match {
|
line.opcode == ZOpcode.LD && line.registers.asInstanceOf[TwoRegisters].source == source && (line.registers.asInstanceOf[TwoRegisters].target match {
|
||||||
case ZRegister.I | ZRegister.MEM_ABS_8 | ZRegister.R => false
|
case ZRegister.I | ZRegister.MEM_ABS_8 | ZRegister.R | ZRegister.MEM_DE | ZRegister.MEM_BC => false
|
||||||
case _ => true
|
case _ => true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user