diff --git a/src/main/scala/millfork/assembly/opt/Status.scala b/src/main/scala/millfork/assembly/opt/Status.scala index e01684a9..3a31e050 100644 --- a/src/main/scala/millfork/assembly/opt/Status.scala +++ b/src/main/scala/millfork/assembly/opt/Status.scala @@ -234,6 +234,19 @@ object Status { case _ => AnyStatus -> AnyStatus } + def sbb(value: Status[Int], carry: Status[Boolean]): (Status[Int], Status[Boolean]) = (inner, value) match { + case (SingleStatus(x), SingleStatus(v)) => carry match { + case SingleStatus(false) => SingleStatus((x - v) & 0xff) -> SingleStatus((x.&(0xff) - v.&(0xff)) < 0) + case SingleStatus(true) => SingleStatus((x - v - 1) & 0xff) -> SingleStatus((x.&(0xff) - v.&(0xff) - 1) < 0) + case _ => AnyStatus -> (if (v == 0) SingleFalse else AnyStatus) + } + case (_, SingleStatus(0)) => carry match { + case SingleStatus(false) => inner -> SingleFalse + case _ => AnyStatus -> AnyStatus + } + case _ => AnyStatus -> AnyStatus + } + def adc_w(value: Int, carry: Status[Boolean], decimal: Status[Boolean]): Status[Int] = inner match { case SingleStatus(x) => decimal match { case SingleStatus(false) => carry match { diff --git a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala index 4b73c01d..0b29f0ce 100644 --- a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala +++ b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala @@ -334,6 +334,22 @@ object AlwaysGoodI80Optimizations { (HasOpcode(CP) & MatchSoleRegisterAndOffset(1) & Not(Match8BitImmediate(2))) ~ (HasOpcodeIn(Set(JP, JR, RET)) & HasRegisters(IfFlagClear(ZFlag.Z))) ~ (Elidable & HasOpcode(LD) & HasTargetRegister(A) & MatchSourceRegisterAndOffset(1)) ~~> (_.init), + + // 69 + (Elidable & HasOpcode(LD) & HasTargetRegister(MEM_ABS_8) & MatchParameter(0)) ~ + (Linear & Not(ConcernsMemory)).* ~ + (HasOpcode(LD) & HasTargetRegister(MEM_ABS_8) & MatchParameter(0)) ~~> (_.tail), + + // 70 + (Elidable & HasOpcode(LD) & HasTargetRegister(MEM_HL)) ~ + (Linear & Not(ConcernsMemory) & Not(Changes(ZRegister.HL))).* ~ + (HasOpcode(LD) & HasTargetRegister(MEM_HL)) ~~> (_.tail), + + // 71 + (Elidable & HasOpcode(LD_16) & HasTargetRegister(MEM_ABS_16) & MatchParameter(0)) ~ + (Linear & Not(ConcernsMemory)).* ~ + (HasOpcode(LD_16) & HasTargetRegister(MEM_ABS_16) & MatchParameter(0)) ~~> (_.tail), + ) val PointlessStackStashing = new RuleBasedAssemblyOptimization("Pointless stack stashing", @@ -1706,8 +1722,30 @@ object AlwaysGoodI80Optimizations { ), ) + val ActuallyUnconditionalJump = new RuleBasedAssemblyOptimization("Actually unconditional jump", + needsFlowInfo = FlowInfoRequirement.ForwardFlow, + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagSet(ZFlag.C)) & HasSet(ZFlag.C)) ~~> (code => code.map(_.copy(opcode = JP, registers = NoRegisters))), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagClear(ZFlag.C)) & HasClear(ZFlag.C)) ~~> (code => code.map(_.copy(opcode = JP, registers = NoRegisters))), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagSet(ZFlag.Z)) & HasSet(ZFlag.Z)) ~~> (code => code.map(_.copy(opcode = JP, registers = NoRegisters))), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagClear(ZFlag.Z)) & HasClear(ZFlag.Z)) ~~> (code => code.map(_.copy(opcode = JP, registers = NoRegisters))), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagSet(ZFlag.S)) & HasSet(ZFlag.S)) ~~> (code => code.map(_.copy(opcode = JP, registers = NoRegisters))), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagClear(ZFlag.S)) & HasClear(ZFlag.S)) ~~> (code => code.map(_.copy(opcode = JP, registers = NoRegisters))), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagSet(ZFlag.P)) & HasSet(ZFlag.P)) ~~> (code => code.map(_.copy(opcode = JP, registers = NoRegisters))), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagClear(ZFlag.P)) & HasClear(ZFlag.P)) ~~> (code => code.map(_.copy(opcode = JP, registers = NoRegisters))), + + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagClear(ZFlag.C)) & HasSet(ZFlag.C)) ~~> (code => Nil), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagSet(ZFlag.C)) & HasClear(ZFlag.C)) ~~> (code => Nil), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagClear(ZFlag.Z)) & HasSet(ZFlag.Z)) ~~> (code => Nil), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagSet(ZFlag.Z)) & HasClear(ZFlag.Z)) ~~> (code => Nil), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagClear(ZFlag.S)) & HasSet(ZFlag.S)) ~~> (code => Nil), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagSet(ZFlag.S)) & HasClear(ZFlag.S)) ~~> (code => Nil), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagClear(ZFlag.P)) & HasSet(ZFlag.P)) ~~> (code => Nil), + (Elidable & HasOpcodeIn(Set(JP, JR)) & HasRegisters(IfFlagSet(ZFlag.P)) & HasClear(ZFlag.P)) ~~> (code => Nil), + ) + val All: List[AssemblyOptimization[ZLine]] = List[AssemblyOptimization[ZLine]]( + ActuallyUnconditionalJump, BranchInPlaceRemoval, ConstantDivision, ConstantMultiplication, diff --git a/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala b/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala index 43c6414b..8f2305e3 100644 --- a/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala +++ b/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala @@ -155,9 +155,22 @@ object CoarseFlowAnalyzer { currentStatus = currentStatus.copy(a = newA, nf = Status.SingleFalse, cf = newC, zf = newA.z(), sf = newA.n(), pf = AnyStatus, hf = AnyStatus) + case ZLine0(SUB, OneRegister(ZRegister.IMM_8), NumericConstant(n, _)) => + val (newA, newC) = currentStatus.a.sbb(SingleStatus(n.toInt & 0xff), Status.SingleFalse) + currentStatus = currentStatus.copy(a = newA, + nf = Status.SingleTrue, cf = newC, zf = newA.z(), sf = newA.n(), pf = AnyStatus, hf = AnyStatus) + case ZLine0(SBC,OneRegister(ZRegister.IMM_8), NumericConstant(n, _))=> + val (newA, newC) = currentStatus.a.sbb(SingleStatus(n.toInt & 0xff), currentStatus.cf) + currentStatus = currentStatus.copy(a = newA, + nf = Status.SingleTrue, cf = newC,zf = newA.z(), sf = newA.n(), pf = AnyStatus, hf = AnyStatus) case ZLine0(SUB, OneRegister(s), _) => - currentStatus = currentStatus.copy(a = (currentStatus.a <*> currentStatus.getRegister(s)) ((m, n) => (m - n) & 0xff), - nf = Status.SingleTrue, cf = AnyStatus, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus) + val (newA, newC) = currentStatus.a.sbb(currentStatus.getRegister(s), Status.SingleFalse) + currentStatus = currentStatus.copy(a = newA, + nf = Status.SingleTrue, cf = newC, zf = newA.z(), sf = newA.n(), pf = AnyStatus, hf = AnyStatus) + case ZLine0(SBC, OneRegister(s), _) => + val (newA, newC) = currentStatus.a.sbb(currentStatus.getRegister(s), currentStatus.cf) + currentStatus = currentStatus.copy(a = newA, + nf = Status.SingleTrue, cf = newC,zf = newA.z(), sf = newA.n(), pf = AnyStatus, hf = AnyStatus) case ZLine0(AND, OneRegister(s), _) => currentStatus = currentStatus.copy(a = (currentStatus.a <*> currentStatus.getRegister(s)) ((m, n) => (m & n) & 0xff), @@ -173,6 +186,13 @@ object CoarseFlowAnalyzer { currentStatus = currentStatus.copy(a = (currentStatus.a <*> currentStatus.getRegister(s)) ((m, n) => (m ^ n) & 0xff), nf = Status.SingleFalse, cf = Status.SingleFalse, zf = AnyStatus, sf = AnyStatus, pf = AnyStatus, hf = AnyStatus) + case ZLine0(CP, OneRegister(ZRegister.IMM_8), NumericConstant(n, _)) => + val (newA, newC) = currentStatus.a.sbb(SingleStatus(n.toInt & 0xff), Status.SingleFalse) + currentStatus = currentStatus.copy(nf = AnyStatus, cf = newC, zf = newA.z(), sf = newA.n(), pf = AnyStatus, hf = AnyStatus) + case ZLine0(CP, OneRegister(s), _) => + val (newA, newC) = currentStatus.a.sbb(currentStatus.getRegister(s), Status.SingleFalse) + currentStatus = currentStatus.copy(nf = AnyStatus, cf = newC, zf = newA.z(), sf = newA.n(), pf = AnyStatus, hf = AnyStatus) + case ZLine0(INC, OneRegister(r), _) => val newV = currentStatus.getRegister(r).map(i => i.+(1).&(0xff)) currentStatus = currentStatus.