From 6b02c5178a7c1d807cb4f56fc43cf6b0e6f6301b Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Wed, 1 Aug 2018 15:32:11 +0200 Subject: [PATCH] Z80: More arithmetic optimizations --- .../z80/opt/AlwaysGoodI80Optimizations.scala | 28 +++++++++++++++++-- .../assembly/z80/opt/CoarseFlowAnalyzer.scala | 7 +++++ .../opt/RuleBasedAssemblyOptimization.scala | 2 +- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala index 5c12b93e..a8d64807 100644 --- a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala +++ b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala @@ -377,7 +377,7 @@ object AlwaysGoodI80Optimizations { (Elidable & HasOpcodeIn(Set(ADD, OR, XOR, SUB)) & Has8BitImmediate(0) & DoesntMatterWhatItDoesWithFlags) ~~> (_ => Nil), (Elidable & HasOpcode(AND) & Has8BitImmediate(0xff) & DoesntMatterWhatItDoesWithFlags) ~~> (_ => Nil), (Elidable & HasOpcode(AND) & Has8BitImmediate(0) & DoesntMatterWhatItDoesWithFlags) ~~> (_ => List(ZLine.ldImm8(ZRegister.A, 0))), - (Elidable & HasOpcode(AND) & Has8BitImmediate(0) & DoesntMatterWhatItDoesWithFlags) ~~> (_ => List(ZLine.ldImm8(ZRegister.A, 0))), + (Elidable & HasOpcode(XOR) & Has8BitImmediate(0xff) & DoesntMatterWhatItDoesWithFlags) ~~> (_ => List(ZLine.implied(CPL))), (Elidable & HasOpcode(OR) & Match8BitImmediate(1) & MatchRegister(ZRegister.A, 0)) ~ @@ -467,7 +467,31 @@ object AlwaysGoodI80Optimizations { (Elidable & Is8BitLoadTo(ZRegister.A)) ~ (Elidable & HasOpcode(SBC)) ~~> { code => List(code(1), code.last.copy(opcode = SUB)) - } + }, + + (Elidable & HasOpcode(ADD) & Has8BitImmediate(0) & DoesntMatterWhatItDoesWithFlagsExceptCarry) ~~> { _ => + List(ZLine.register(OR, A)) + }, + + (Elidable & HasOpcode(SUB) & Has8BitImmediate(0) & DoesntMatterWhatItDoesWithFlagsExceptCarry) ~~> { _ => + List(ZLine.register(OR, A)) + }, + + (Elidable & HasOpcode(ADC) & Has8BitImmediate(0) & HasClear(ZFlag.C) & DoesntMatterWhatItDoesWithFlagsExceptCarry) ~~> { _ => + List(ZLine.register(OR, A)) + }, + + (Elidable & HasOpcode(ADC) & HasClear(ZFlag.C)) ~~> { code => + code.map(_.copy(opcode = ADD)) + }, + + (Elidable & HasOpcode(SBC) & HasClear(ZFlag.C)) ~~> { code => + code.map(_.copy(opcode = SUB)) + }, + + (Elidable & HasOpcodeIn(Set(OR, XOR)) & Has8BitImmediate(0) & DoesntMatterWhatItDoesWithFlags) ~~> ( _ => Nil), + + (Elidable & HasOpcode(OR) & HasRegisterParam(A) & DoesntMatterWhatItDoesWithFlags) ~~> (_ => Nil), ) diff --git a/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala b/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala index 1c449fc1..448082b1 100644 --- a/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala +++ b/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala @@ -51,6 +51,10 @@ object CoarseFlowAnalyzer { case ZLine(AND, OneRegister(s), _, _) => currentStatus = currentStatus.copy(a = (currentStatus.a <*> currentStatus.getRegister(s)) ((m, n) => (m & n) & 0xff), cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus) + case ZLine(OR, OneRegister(ZRegister.A), _, _) => + currentStatus = currentStatus.copy(cf = Status.SingleFalse, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus) + case ZLine(XOR, OneRegister(ZRegister.A), _, _) => + currentStatus = currentStatus.copy(a = Status.SingleZero, cf = Status.SingleFalse, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus) case ZLine(OR, OneRegister(s), _, _) => currentStatus = currentStatus.copy(a = (currentStatus.a <*> currentStatus.getRegister(s)) ((m, n) => (m | n) & 0xff), cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus) @@ -122,6 +126,9 @@ object CoarseFlowAnalyzer { zf = AnyStatus, pf = AnyStatus, hf = Status.SingleFalse) + case ZLine(SCF, _, _, _) => currentStatus.copy(cf = Status.SingleTrue) + case ZLine(CCF, _, _, _) => currentStatus.copy(cf = currentStatus.cf.negate) + case ZLine(opcode, registers, _, _) => currentStatus = currentStatus.copy(cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus) if (ZOpcodeClasses.ChangesAAlways(opcode)) currentStatus = currentStatus.copy(a = AnyStatus) diff --git a/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala b/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala index bdef7997..22b77dd7 100644 --- a/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala +++ b/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala @@ -655,7 +655,7 @@ case class HasClear(flag: ZFlag.Value) extends AssemblyLinePattern { FlowInfoRequirement.assertForward(needsFlowInfo) override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: ZLine): Boolean = - flowInfo.statusBefore.getFlag(flag).exists(_ == true) + flowInfo.statusBefore.getFlag(flag).exists(_ == false) } case object Anything extends TrivialAssemblyLinePattern {