1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-05-31 18:41:30 +00:00

6809: Improve flow analysis and add few more optimizations

This commit is contained in:
Karol Stasiak 2021-06-21 14:15:40 +02:00
parent 2e592a2331
commit 307ad90ecf
11 changed files with 384 additions and 31 deletions

View File

@ -3,7 +3,7 @@
#warn m6809_math module should be used only on 6809-like targets
#endif
noinline asm word __mul_u16u16u16(word register(x) x, word register(d) d) {
noinline asm word __mul_u16u16u16(word register(x) x, word register(d) d) !preserves_y !preserves_u {
pshs d,x
exg d,x
lda ,s
@ -26,7 +26,7 @@ noinline asm word __mul_u16u16u16(word register(x) x, word register(d) d) {
}
// returns p/q: quotient in A, remainder in B
noinline asm word __divmod_u8u8u8u8(word register(a) p, word register(b) q) {
noinline asm word __divmod_u8u8u8u8(word register(a) p, word register(b) q) !preserves_x !preserves_y !preserves_u {
pshs b,cc
ldb #8
stb ,-s
@ -47,7 +47,7 @@ noinline asm word __divmod_u8u8u8u8(word register(a) p, word register(b) q) {
}
// returns p/q: quotient in X, remainder in D
noinline asm word __divmod_u16u16u16u16(word register(x) p, word register(d) q) {
noinline asm word __divmod_u16u16u16u16(word register(x) p, word register(d) q) !preserves_y !preserves_u {
pshs x,d,cc
ldb #16
pshs b

View File

@ -254,9 +254,10 @@ case class MLine(opcode: MOpcode.Value, addrMode: MAddrMode, parameter: Constant
case MUL => overlaps(D)
case ABX => reg == X || overlaps(B)
case NOP | SWI | SWI2 | SWI3 | SYNC => false
case LDB | LDA | LDX | LDY | LDU => false
case INC | DEC | ROL | ROR | ASL | ASR | LSR | CLR | COM | NEG | TST => false // variants for A and B handled before
case op if Branching(op) => false
case JMP => false
case JMP | RTS => false
case _ => true // TODO
}
}

View File

@ -3,7 +3,7 @@ package millfork.assembly.m6809.opt
import millfork.assembly.AssemblyOptimization
import millfork.assembly.m6809.MOpcode._
import millfork.assembly.m6809.{Absolute, DAccumulatorIndexed, Immediate, InherentA, InherentB, LongRelative, MAddrMode, MLine, MState, PostIncremented, RegisterSet}
import millfork.assembly.m6809.{Absolute, DAccumulatorIndexed, Immediate, Indexed, InherentA, InherentB, LongRelative, MAddrMode, MLine, MState, PostIncremented, RegisterSet}
import millfork.env.{CompoundConstant, Constant, MathOperator}
import millfork.node.M6809Register
@ -253,6 +253,36 @@ object AlwaysGoodMOptimizations {
)
val SimplifiableAddressing = new RuleBasedAssemblyOptimization("Simplifiable addressing",
needsFlowInfo = FlowInfoRequirement.ForwardFlow,
(NotFixed & MatchX(0) & HasAddrMode(Indexed(M6809Register.X, indirect = false)) & Not(HasOpcodeIn(LEAX, LEAY, LEAS, LEAU))) ~~> { (code, ctx) =>
val x = ctx.get[Constant](0)
code.map(l => l.copy(addrMode = Absolute(indirect = false), parameter = (x + l.parameter).quickSimplify))
},
(NotFixed & MatchY(0) & HasAddrMode(Indexed(M6809Register.Y, indirect = false)) & Not(HasOpcodeIn(LEAX, LEAY, LEAS, LEAU))) ~~> { (code, ctx) =>
val y = ctx.get[Constant](0)
code.map(l => l.copy(addrMode = Absolute(indirect = false), parameter = (y + l.parameter).quickSimplify))
},
(NotFixed & MatchX(0) & HasAddrMode(Indexed(M6809Register.X, indirect = false)) & HasOpcodeIn(LEAX, LEAY, LEAS, LEAU)) ~~> { (code, ctx) =>
val x = ctx.get[Constant](0)
code.map(l => l.copy(opcode = l.opcode match {
case LEAX => LDX
case LEAY => LDY
case LEAU => LDU
case LEAS => LDS
}, addrMode = Immediate, parameter = (x + l.parameter).quickSimplify))
},
(NotFixed & MatchY(0) & HasAddrMode(Indexed(M6809Register.X, indirect = false)) & HasOpcodeIn(LEAX, LEAY, LEAS, LEAU)) ~~> { (code, ctx) =>
val y = ctx.get[Constant](0)
code.map(l => l.copy(opcode = l.opcode match {
case LEAX => LDX
case LEAY => LDY
case LEAU => LDU
case LEAS => LDS
}, addrMode = Immediate, parameter = (y + l.parameter).quickSimplify))
},
)
val UnusedLabelRemoval = new RuleBasedAssemblyOptimization("Unused label removal",
needsFlowInfo = FlowInfoRequirement.JustLabels,
(Elidable & HasOpcode(LABEL) & HasCallerCount(0) & ParameterIsLocalLabel) ~~> (_ => Nil)
@ -263,6 +293,7 @@ object AlwaysGoodMOptimizations {
PointlessLoad,
PointlessCompare,
PointlessRegisterTransfers,
SimplifiableAddressing,
SimplifiableArithmetics,
SimplifiableComparison,
SimplifiableJumps,

View File

@ -35,6 +35,11 @@ case class CpuStatus(a: Status[Int] = UnknownStatus,
def nzB(i: Long): CpuStatus =
this.copy(n = SingleStatus((i & 0x80) != 0), z = SingleStatus((i & 0xff) == 0))
def nzB(i: Status[Int]): CpuStatus = i match {
case SingleStatus(j) => this.copy(n = SingleStatus((j & 0x80) != 0), z = SingleStatus((j & 0xff) == 0))
case _ => this.copy(n = AnyStatus, z = AnyStatus)
}
def nzW(i: Long): CpuStatus =
this.copy(n = SingleStatus((i & 0x8000) != 0), z = SingleStatus((i & 0xffff) == 0))
@ -44,6 +49,11 @@ case class CpuStatus(a: Status[Int] = UnknownStatus,
case _ => this.nz
}
def nzW(i: Status[Int]): CpuStatus = i match {
case SingleStatus(j) => this.copy(n = SingleStatus((j & 0x8000) != 0), z = SingleStatus((j & 0xffff) == 0))
case _ => this.copy(n = AnyStatus, z = AnyStatus)
}
def ~(that: CpuStatus) = new CpuStatus(
a = this.a ~ that.a,
b = this.b ~ that.b,

View File

@ -2,10 +2,11 @@ package millfork.assembly.m6809.opt
import millfork.CompilationFlag
import millfork.assembly.OptimizationContext
import millfork.assembly.m6809.{Immediate, MLine, MLine0}
import millfork.assembly.m6809.{Absolute, Immediate, Inherent, InherentA, InherentB, MLine, MLine0, TwoRegisters}
import millfork.assembly.opt.Status.SingleFalse
import millfork.assembly.opt.{AnyStatus, FlowCache, SingleStatus, Status}
import millfork.env._
import millfork.node.M6809NiceFunctionProperty.{DoesntChangeA, DoesntChangeB, DoesntChangeU, DoesntChangeX, DoesntChangeY}
import millfork.node.{M6809Register, NiceFunctionProperty}
import scala.util.control.Breaks._
@ -62,33 +63,108 @@ object ForwardFlowAnalysis {
case _ => None
}).fold(currentStatus)(_ ~ _)
case MLine0(JSR, _, MemoryAddressConstant(th)) =>
case MLine0(JSR, am, MemoryAddressConstant(th)) =>
var prU = bpInU
var prY = bpInY
var prA = false
var prB = false
var prX = false
(am, th) match {
case (Absolute(false), fun: FunctionInMemory) =>
val nfp = optimizationContext.niceFunctionProperties
val fn = fun.name
if (nfp(DoesntChangeX -> fn)) prX = true
if (nfp(DoesntChangeY -> fn)) prY = true
if (nfp(DoesntChangeU -> fn)) prU = true
if (nfp(DoesntChangeA -> fn)) prA = true
if (nfp(DoesntChangeB -> fn)) prB = true
case _ =>
}
currentStatus = initialStatus.copy(
memStack = currentStatus.memStack,
u = if (bpInU) currentStatus.u else AnyStatus,
y = if (bpInY) currentStatus.y else AnyStatus
u = if (prU) currentStatus.u else AnyStatus,
x = if (prX) currentStatus.x else AnyStatus,
y = if (prY) currentStatus.y else AnyStatus,
a = if (prA) currentStatus.a else AnyStatus,
b = if (prB) currentStatus.b else AnyStatus
)
case MLine0(JSR | BYTE, _, _) =>
currentStatus = initialStatus
case MLine0(NOP, _, _) =>
()
case MLine0(op, Immediate, constant) if ForwardFlowAnalysisForImmediate.hasDefinition(op) =>
ForwardFlowAnalysisForImmediate.get(op)(constant, currentStatus)
case MLine0(op, Inherent, _) if ForwardFlowAnalysisForInherent.hasDefinition(op) =>
ForwardFlowAnalysisForInherent.get(op)(currentStatus)
case MLine0(op, InherentA, _) if ForwardFlowAnalysisForInherentA.hasDefinition(op) =>
ForwardFlowAnalysisForInherentA.get(op)(currentStatus)
case MLine0(op, InherentB, _) if ForwardFlowAnalysisForInherentB.hasDefinition(op) =>
ForwardFlowAnalysisForInherentB.get(op)(currentStatus)
case MLine0(LDA, Immediate, NumericConstant(n, _)) =>
currentStatus = currentStatus.copy(a = SingleStatus(n.toInt & 0xff), v = SingleFalse).nzB(n)
case MLine0(LDB, Immediate, NumericConstant(n, _)) =>
currentStatus = currentStatus.copy(b = SingleStatus(n.toInt & 0xff), v = SingleFalse).nzB(n)
case MLine0(LDD, Immediate, NumericConstant(n, _)) =>
currentStatus = currentStatus.copy(
a = SingleStatus(n.toInt.>>(8) & 0xff),
b = SingleStatus(n.toInt & 0xff),
v = SingleFalse
).nzW(n)
case MLine0(LDX, Immediate, c) =>
currentStatus = currentStatus.copy(x = SingleStatus(c), v = SingleFalse).nzW(c)
case MLine0(LDY, Immediate, c) =>
currentStatus = currentStatus.copy(y = SingleStatus(c), v = SingleFalse).nzW(c)
case MLine0(LDA, _, _) =>
currentStatus = currentStatus.copy(a = AnyStatus, n = AnyStatus, z = AnyStatus, v = SingleFalse)
case MLine0(LDB, _, _) =>
currentStatus = currentStatus.copy(b = AnyStatus, n = AnyStatus, z = AnyStatus, v = SingleFalse)
case MLine0(LDD, _, _) =>
currentStatus = currentStatus.copy(a = AnyStatus, b = AnyStatus, n = AnyStatus, z = AnyStatus, v = SingleFalse)
case MLine0(LDX, _, _) =>
currentStatus = currentStatus.copy(x = AnyStatus, n = AnyStatus, z = AnyStatus, v = SingleFalse)
case MLine0(LDY, _, _) =>
currentStatus = currentStatus.copy(y = AnyStatus, n = AnyStatus, z = AnyStatus, v = SingleFalse)
case MLine0(STA | STB | STD | STX | STU | STY | STS, _, _) =>
// don't change
case MLine0(TFR, TwoRegisters(source, target), _) =>
import M6809Register._
(source, target) match {
case (A, B) => currentStatus = currentStatus.copy(b = currentStatus.a)
case (B, A) => currentStatus = currentStatus.copy(a = currentStatus.b)
case (CC, A) => currentStatus = currentStatus.copy(a = AnyStatus)
case (CC, B) => currentStatus = currentStatus.copy(b = AnyStatus)
case (A, CC) | (B, CC) => currentStatus = currentStatus.copy(c = AnyStatus, z = AnyStatus, n = AnyStatus, v = AnyStatus)
case (S, D) => currentStatus = currentStatus.copy(a = AnyStatus, b = AnyStatus)
case (S, X) => currentStatus = currentStatus.copy(x = AnyStatus)
case (S, Y) => currentStatus = currentStatus.copy(y = AnyStatus)
case (S, U) => currentStatus = currentStatus.copy(u = AnyStatus)
case (D, X) => currentStatus = currentStatus.copy(x = currentStatus.d.map(n => NumericConstant(n, 2)))
case (D, Y) => currentStatus = currentStatus.copy(y = currentStatus.d.map(n => NumericConstant(n, 2)))
case (D, U) => currentStatus = currentStatus.copy(u = currentStatus.d.map(n => NumericConstant(n, 2)))
case (X, Y) => currentStatus = currentStatus.copy(y = currentStatus.x)
case (X, U) => currentStatus = currentStatus.copy(u = currentStatus.x)
case (Y, X) => currentStatus = currentStatus.copy(x = currentStatus.y)
case (Y, U) => currentStatus = currentStatus.copy(u = currentStatus.y)
case (U, X) => currentStatus = currentStatus.copy(x = currentStatus.u)
case (U, Y) => currentStatus = currentStatus.copy(y = currentStatus.u)
case (X, D) =>
val (h, l) = currentStatus.x.toHiLo
currentStatus = currentStatus.copy(a = h, b = l)
case (Y, D) =>
val (h, l) = currentStatus.y.toHiLo
currentStatus = currentStatus.copy(a = h, b = l)
case (U, D) =>
val (h, l) = currentStatus.u.toHiLo
currentStatus = currentStatus.copy(a = h, b = l)
case _ => currentStatus = initialStatus
}
case MLine0(EXG, TwoRegisters(source, target), _) =>
import M6809Register._
(source, target) match {
case (A, B) | (B, A) => currentStatus = currentStatus.copy(a = currentStatus.b, b = currentStatus.a)
case (A, CC) | (CC, A) => currentStatus = currentStatus.copy(a = AnyStatus, c = AnyStatus, v = AnyStatus, n = AnyStatus, z = AnyStatus)
case (B, CC) | (CC, B) => currentStatus = currentStatus.copy(b = AnyStatus, c = AnyStatus, v = AnyStatus, n = AnyStatus, z = AnyStatus)
case (X, Y) | (Y, X) => currentStatus = currentStatus.copy(y = currentStatus.x, x = currentStatus.y)
case (U, Y) | (Y, U) => currentStatus = currentStatus.copy(y = currentStatus.u, u = currentStatus.y)
case (X, U) | (U, X) => currentStatus = currentStatus.copy(u = currentStatus.x, x = currentStatus.u)
case (X, D) | (D, X) =>
val (h, l) = currentStatus.x.toHiLo
currentStatus = currentStatus.copy(a = h, b = l, x = currentStatus.d.map(n => NumericConstant(n, 2)))
case (Y, D) | (D, Y) =>
val (h, l) = currentStatus.y.toHiLo
currentStatus = currentStatus.copy(a = h, b = l, y = currentStatus.d.map(n => NumericConstant(n, 2)))
case (U, D) | (D, U) =>
val (h, l) = currentStatus.u.toHiLo
currentStatus = currentStatus.copy(a = h, b = l, u = currentStatus.d.map(n => NumericConstant(n, 2)))
case _ => currentStatus = initialStatus
}
case MLine0(opcode, addrMode, _) =>
// TODO

View File

@ -0,0 +1,80 @@
package millfork.assembly.m6809.opt
import millfork.assembly.m6809.MOpcode
import millfork.assembly.m6809.MOpcode._
import millfork.assembly.opt.{AnyStatus, SingleStatus, Status}
import millfork.assembly.opt.Status.SingleFalse
import millfork.env.Constant
/**
* @author Karol Stasiak
*/
object ForwardFlowAnalysisForImmediate {
private val map: Map[MOpcode.Value, (Constant, CpuStatus) => CpuStatus] = Map(
LDX -> {(c, currentStatus) =>
currentStatus.copy(x = SingleStatus(c), v = SingleFalse).nzW(c)
},
LDY -> {(c, currentStatus) =>
currentStatus.copy(y = SingleStatus(c), v = SingleFalse).nzW(c)
},
LDU -> {(c, currentStatus) =>
currentStatus.copy(u = SingleStatus(c), v = SingleFalse).nzW(c)
},
LDA -> {(c, currentStatus) =>
val value = Status.fromByte(c)
currentStatus.copy(a = value, v = SingleFalse).nzB(value)
},
LDB -> {(c, currentStatus) =>
val value = Status.fromByte(c)
currentStatus.copy(a = value, v = SingleFalse).nzB(value)
},
LDD -> {(c, currentStatus) =>
val value = Status.fromByte(c)
currentStatus.copy(a = value.hi, b = value.lo, v = SingleFalse).nzW(value)
},
ORA -> { (c, currentStatus) =>
val newValue = (currentStatus.a <*> Status.fromByte(c)) { (x, y) => (x | y) & 0xff }
currentStatus.copy(a = newValue, v = SingleFalse).nzB(newValue)
},
ORB -> { (c, currentStatus) =>
val newValue = (currentStatus.b <*> Status.fromByte(c)) { (x, y) => (x | y) & 0xff }
currentStatus.copy(b = newValue, v = SingleFalse).nzB(newValue)
},
EORA -> { (c, currentStatus) =>
val newValue = (currentStatus.a <*> Status.fromByte(c)) { (x, y) => (x ^ y) & 0xff }
currentStatus.copy(a = newValue, v = SingleFalse).nzB(newValue)
},
EORB -> { (c, currentStatus) =>
val newValue = (currentStatus.b <*> Status.fromByte(c)) { (x, y) => (x ^ y) & 0xff }
currentStatus.copy(b = newValue, v = SingleFalse).nzB(newValue)
},
ANDA -> { (c, currentStatus) =>
val newValue = (currentStatus.a <*> Status.fromByte(c)) { (x, y) => (x & y) & 0xff }
currentStatus.copy(a = newValue, v = SingleFalse).nzB(newValue)
},
ANDB -> { (c, currentStatus) =>
val newValue = (currentStatus.b <*> Status.fromByte(c)) { (x, y) => (x & y) & 0xff }
currentStatus.copy(b = newValue, v = SingleFalse).nzB(newValue)
},
ADDA -> { (c, currentStatus) =>
val (newValue, newCarry) = currentStatus.a.adc(Status.fromByte(c), SingleFalse)
currentStatus.copy(a = newValue, v = AnyStatus, c = newCarry).nzB(newValue)
},
ADDB -> { (c, currentStatus) =>
val (newValue, newCarry) = currentStatus.b.adc(Status.fromByte(c), SingleFalse)
currentStatus.copy(b = newValue, v = AnyStatus, c = newCarry).nzB(newValue)
},
ADCA -> { (c, currentStatus) =>
val (newValue, newCarry) = currentStatus.a.adc(Status.fromByte(c), currentStatus.c)
currentStatus.copy(a = newValue, v = AnyStatus, c = newCarry).nzB(newValue)
},
ADCB -> { (c, currentStatus) =>
val (newValue, newCarry) = currentStatus.b.adc(Status.fromByte(c), currentStatus.c)
currentStatus.copy(b = newValue, v = AnyStatus, c = newCarry).nzB(newValue)
},
)
def hasDefinition(opcode: MOpcode.Value): Boolean = map.contains(opcode)
def get(opcode: MOpcode.Value): (Constant, CpuStatus) => CpuStatus = map(opcode)
}

View File

@ -0,0 +1,28 @@
package millfork.assembly.m6809.opt
import millfork.assembly.m6809.MOpcode
import millfork.assembly.m6809.MOpcode._
import millfork.assembly.opt.Status.SingleFalse
import millfork.assembly.opt.{AnyStatus, SingleStatus, Status}
import millfork.env.Constant
/**
* @author Karol Stasiak
*/
object ForwardFlowAnalysisForInherent {
private val map: Map[MOpcode.Value, CpuStatus => CpuStatus] = Map(
NOP -> identity,
MUL -> { currentStatus =>
val newD = (currentStatus.a <*> currentStatus.b) { (a, b) => ((a & 0xff) * (b & 0xff)) & 0xff }
currentStatus.copy(c = AnyStatus, z = AnyStatus, a = newD.hi, b = newD.hi)
},
SEX -> { currentStatus =>
val newA = currentStatus.b.map{ n => if (n.&(0x80) == 0) 0 else 0xff }
currentStatus.copy(v = Status.SingleFalse, n = AnyStatus, z = AnyStatus, a = newA)
},
)
def hasDefinition(opcode: MOpcode.Value): Boolean = map.contains(opcode)
def get(opcode: MOpcode.Value): CpuStatus => CpuStatus = map(opcode)
}

View File

@ -0,0 +1,47 @@
package millfork.assembly.m6809.opt
import millfork.assembly.m6809.MOpcode
import millfork.assembly.m6809.MOpcode._
import millfork.assembly.opt.{AnyStatus, SingleStatus, Status}
/**
* @author Karol Stasiak
*/
object ForwardFlowAnalysisForInherentA {
private val map: Map[MOpcode.Value, CpuStatus => CpuStatus] = Map(
ASL -> { currentStatus =>
val newValue = currentStatus.a.map(n => n.<<(1).&(0xff))
currentStatus.copy(a = newValue, c = currentStatus.a.bit7, v = AnyStatus).nzB(newValue)
},
LSR -> { currentStatus =>
val newValue = currentStatus.a.map(n => n.>>(1).&(0x7f))
currentStatus.copy(a = newValue, c = currentStatus.a.bit0, v = AnyStatus).nzB(newValue)
},
CLR -> { currentStatus =>
currentStatus.copy(a = Status.SingleZero, c = Status.SingleFalse, v = Status.SingleFalse, n = Status.SingleFalse, z = Status.SingleFalse)
},
COM -> { currentStatus =>
val newValue = currentStatus.a.map(n => n.^(0xff).&(0xff))
currentStatus.copy(a = newValue, c = Status.SingleTrue, v = Status.SingleFalse).nzB(newValue)
},
DEC -> { currentStatus =>
val newValue = currentStatus.a.map(n => n.+(1).&(0xff))
currentStatus.copy(a = newValue, v = AnyStatus).nzB(newValue)
},
INC -> { currentStatus =>
val newValue = currentStatus.a.map(n => n.-(1).&(0xff))
currentStatus.copy(a = newValue, v = AnyStatus).nzB(newValue)
},
NEG -> { currentStatus =>
val newValue = currentStatus.a.map(n => (-n).&(0xff))
currentStatus.copy(a = newValue, c = AnyStatus, v = AnyStatus).nzB(newValue)
},
TST -> { currentStatus =>
currentStatus.copy(v = Status.SingleFalse).nzB(currentStatus.a)
},
)
def hasDefinition(opcode: MOpcode.Value): Boolean = map.contains(opcode)
def get(opcode: MOpcode.Value): CpuStatus => CpuStatus = map(opcode)
}

View File

@ -0,0 +1,47 @@
package millfork.assembly.m6809.opt
import millfork.assembly.m6809.MOpcode
import millfork.assembly.m6809.MOpcode._
import millfork.assembly.opt.{AnyStatus, Status}
/**
* @author Karol Stasiak
*/
object ForwardFlowAnalysisForInherentB {
private val map: Map[MOpcode.Value, CpuStatus => CpuStatus] = Map(
ASL -> { currentStatus =>
val newValue = currentStatus.b.map(n => n.<<(1).&(0xff))
currentStatus.copy(b = newValue, c = currentStatus.b.bit7, v = AnyStatus).nzB(newValue)
},
LSR -> { currentStatus =>
val newValue = currentStatus.b.map(n => n.>>(1).&(0x7f))
currentStatus.copy(b = newValue, c = currentStatus.b.bit0, v = AnyStatus).nzB(newValue)
},
CLR -> { currentStatus =>
currentStatus.copy(b = Status.SingleZero, c = Status.SingleFalse, v = Status.SingleFalse, n = Status.SingleFalse, z = Status.SingleFalse)
},
COM -> { currentStatus =>
val newValue = currentStatus.b.map(n => n.^(0xff).&(0xff))
currentStatus.copy(b = newValue, c = Status.SingleTrue, v = Status.SingleFalse).nzB(newValue)
},
DEC -> { currentStatus =>
val newValue = currentStatus.b.map(n => n.+(1).&(0xff))
currentStatus.copy(b = newValue, v = AnyStatus).nzB(newValue)
},
INC -> { currentStatus =>
val newValue = currentStatus.b.map(n => n.-(1).&(0xff))
currentStatus.copy(b = newValue, v = AnyStatus).nzB(newValue)
},
NEG -> { currentStatus =>
val newValue = currentStatus.b.map(n => (-n).&(0xff))
currentStatus.copy(b = newValue, c = AnyStatus, v = AnyStatus).nzB(newValue)
},
TST -> { currentStatus =>
currentStatus.copy(v = Status.SingleFalse).nzB(currentStatus.b)
},
)
def hasDefinition(opcode: MOpcode.Value): Boolean = map.contains(opcode)
def get(opcode: MOpcode.Value): CpuStatus => CpuStatus = map(opcode)
}

View File

@ -1,6 +1,7 @@
package millfork.assembly.m6809.opt
import jdk.jfr.BooleanFlag
import millfork.CompilationFlag
import millfork.assembly._
import millfork.assembly.m6809.{Absolute, MLine, MLine0, MOpcode, MState}
import millfork.assembly.opt.FlowCache
@ -82,6 +83,7 @@ object ReverseFlowAnalyzer {
val readsB: Set[String] = Set("call")
val readsX: Set[String] = Set("call")
val readsY: Set[String] = Set("")
val preservesX: Set[String] = Set("__divmod_u8u8u8u8")
val cache = new FlowCache[MLine, CpuImportance]("m6809 reverse")
private val importanceBeforeJsr: CpuImportance = CpuImportance(
@ -97,7 +99,7 @@ object ReverseFlowAnalyzer {
hf = Unimportant)
private val finalImportance: CpuImportance = CpuImportance(
a = Important, b = Important,
x = Important, y = Important, u = Important,
x = Important, y = Important, u = Important, // TODO: correctly check which registers are important given the function and the compilation options
cf = Unimportant, vf = Unimportant, hf = Unimportant, zf = Unimportant, nf = Unimportant)
//noinspection RedundantNewCaseClass
@ -109,11 +111,23 @@ object ReverseFlowAnalyzer {
var changed = true
changed = true
val actualFinalImportance = f.returnType match {
case FlagBooleanType(_, _, _) => finalImportance.copy(cf = Important, zf = Important, nf = Important, vf = Important)
case t if t.size == 1 => finalImportance.copy(a = Unimportant)
case t if t.size == 0 => finalImportance.copy(a = Unimportant, b = Unimportant)
case _ => finalImportance
val actualFinalImportance = {
var tmp = f.returnType match {
case FlagBooleanType(_, _, _) => finalImportance.copy(cf = Important, zf = Important, nf = Important, vf = Important)
case t if t.size == 1 => finalImportance.copy(a = Unimportant)
case t if t.size == 0 => finalImportance.copy(a = Unimportant, b = Unimportant)
case _ => finalImportance
}
if (!f.inAssembly) {
tmp = tmp.copy(x = Unimportant)
if (!optimizationContext.options.flag(CompilationFlag.UseUForStack)) {
tmp = tmp.copy(u = Unimportant)
}
if (!optimizationContext.options.flag(CompilationFlag.UseYForStack)) {
tmp = tmp.copy(y = Unimportant)
}
}
tmp
}
while (changed) {
changed = false
@ -179,6 +193,7 @@ object ReverseFlowAnalyzer {
if (readsB(fun.name)) result = result.copy(b = Important)
if (readsX(fun.name)) result = result.copy(x = Important)
if (readsY(fun.name)) result = result.copy(y = Important)
if (preservesX(fun.name)) result = result.copy(x = currentImportance.x)
currentImportance = result.copy(
a = if (niceFunctionProperties(DoesntChangeA -> fun.name)) currentImportance.a ~ result.a else result.a,
b = if (niceFunctionProperties(DoesntChangeB -> fun.name)) currentImportance.b ~ result.b else result.b,

View File

@ -1,6 +1,7 @@
package millfork.assembly.opt
import millfork.assembly.mos.opt.SourceOfNZ
import millfork.env.{Constant, NumericConstant}
/**
* @author Karol Stasiak
@ -78,6 +79,16 @@ object Status {
val SingleZero: Status[Int] = SingleStatus(0)
val SingleFF: Status[Int] = SingleStatus(0xff)
def fromByte(c: Constant): Status[Int] = c.loByte match {
case NumericConstant(n, _) => SingleStatus(n.toInt & 0xff)
case _ => AnyStatus
}
def fromWord(c: Constant): Status[Int] = c match {
case NumericConstant(n, _) => SingleStatus(n.toInt & 0xffff)
case _ => AnyStatus
}
@inline
private def wrapBool(b: Boolean): Status[Boolean] = if (b) SingleTrue else SingleFalse
@ -109,6 +120,13 @@ object Status {
case x => x
}
}
implicit class ConstantStatusOps(val inner: Status[Constant]) extends AnyVal {
def toHiLo: (Status[Int], Status[Int]) = inner match {
case SingleStatus(NumericConstant(n, _)) => SingleStatus(n.toInt.>>(8).&(0xff)) -> SingleStatus(n.toInt.&(0xff))
case _ => AnyStatus -> AnyStatus
}
}
implicit class SourceOfNZStatusOps(val inner: Status[SourceOfNZ]) extends AnyVal {
def isFromA: Boolean = inner match {
case SingleStatus(v) => v.a