mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-03 04:32:21 +00:00
6809: Improve flow analysis and add few more optimizations
This commit is contained in:
parent
2e592a2331
commit
307ad90ecf
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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)
|
||||
}
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user