mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-11 08:37:00 +00:00
Improve interprocedural optimizations
This commit is contained in:
parent
35fbdcdbb1
commit
bb63a73f15
@ -3,8 +3,10 @@ package millfork.assembly.mos.opt
|
||||
import millfork.assembly.OptimizationContext
|
||||
import millfork.{CompilationFlag, CompilationOptions}
|
||||
import millfork.assembly.mos.{AssemblyLine, AssemblyLine0, OpcodeClasses}
|
||||
import millfork.assembly.opt.{AnyStatus, FlowCache}
|
||||
import millfork.assembly.opt.{AnyStatus, FlowCache, SingleStatus, Status}
|
||||
import millfork.env._
|
||||
import millfork.node.NiceFunctionProperty
|
||||
import scala.util.control.Breaks._
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
@ -17,6 +19,20 @@ object CoarseFlowAnalyzer {
|
||||
cache.get(code).foreach(return _)
|
||||
val compilationOptions = optimizationContext.options
|
||||
val niceFunctionProperties = optimizationContext.niceFunctionProperties
|
||||
def extractNiceConstant[T](callee: String)(matcher: NiceFunctionProperty => Option[T]): Status[T] = {
|
||||
var result: Status[T] = AnyStatus
|
||||
breakable {
|
||||
niceFunctionProperties.foreach{ np =>
|
||||
if (np._2 == callee) matcher(np._1) match {
|
||||
case Some(x) =>
|
||||
result = SingleStatus(x)
|
||||
break
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
val ceFlag = compilationOptions.flag(CompilationFlag.Emit65CE02Opcodes)
|
||||
val cmosFlag = compilationOptions.flag(CompilationFlag.EmitCmosOpcodes)
|
||||
val initialStatus =
|
||||
@ -58,12 +74,37 @@ object CoarseFlowAnalyzer {
|
||||
|
||||
case AssemblyLine0(JSR, _, MemoryAddressConstant(th)) =>
|
||||
currentStatus = initialStatus.copy(
|
||||
a = if (niceFunctionProperties(DoesntChangeA -> th.name)) currentStatus.a else AnyStatus,
|
||||
a =
|
||||
if (niceFunctionProperties(DoesntChangeA -> th.name)) currentStatus.a
|
||||
else extractNiceConstant(th.name){
|
||||
case SetsATo(x) => Some(x)
|
||||
case _ => None
|
||||
},
|
||||
ah = if (niceFunctionProperties(DoesntChangeAH -> th.name)) currentStatus.ah else AnyStatus,
|
||||
x = if (niceFunctionProperties(DoesntChangeX -> th.name)) currentStatus.x else AnyStatus,
|
||||
x = if (niceFunctionProperties(DoesntChangeX -> th.name)) currentStatus.x
|
||||
else extractNiceConstant(th.name){
|
||||
case SetsXTo(x) => Some(x)
|
||||
case _ => None
|
||||
},
|
||||
eqSX = if (niceFunctionProperties(DoesntChangeX -> th.name)) currentStatus.eqSX else false,
|
||||
eqSpX = if (niceFunctionProperties(DoesntChangeX -> th.name)) currentStatus.eqSpX else false,
|
||||
y = if (niceFunctionProperties(DoesntChangeY -> th.name)) currentStatus.y else AnyStatus,
|
||||
y = if (niceFunctionProperties(DoesntChangeY -> th.name)) currentStatus.y
|
||||
else extractNiceConstant(th.name){
|
||||
case SetsYTo(x) => Some(x)
|
||||
case _ => None
|
||||
},
|
||||
a0 = extractNiceConstant(th.name){
|
||||
case Bit0OfA(x) => Some(x)
|
||||
case _ => None
|
||||
},
|
||||
a7 = extractNiceConstant(th.name){
|
||||
case Bit7OfA(x) => Some(x)
|
||||
case _ => None
|
||||
},
|
||||
src = extractNiceConstant(th.name){
|
||||
case SetsSourceOfNZ(x) => Some(x)
|
||||
case _ => None
|
||||
},
|
||||
iz = if (niceFunctionProperties(DoesntChangeIZ -> th.name)) currentStatus.iz else AnyStatus,
|
||||
c = if (niceFunctionProperties(DoesntChangeC -> th.name)) currentStatus.c else AnyStatus
|
||||
)
|
||||
|
@ -1,10 +1,14 @@
|
||||
package millfork.assembly.z80.opt
|
||||
|
||||
import millfork.assembly.OptimizationContext
|
||||
import millfork.assembly.opt.{AnyStatus, FlowCache, SingleStatus, Status}
|
||||
import millfork.assembly.z80._
|
||||
import millfork.env._
|
||||
import millfork.node.ZRegister
|
||||
import millfork.{CompilationFlag, CompilationOptions, Cpu}
|
||||
import millfork.node.Z80NiceFunctionProperty.{DoesntChangeBC, DoesntChangeDE, DoesntChangeHL, SetsATo}
|
||||
import millfork.node.{NiceFunctionProperty, ZRegister}
|
||||
import millfork.CompilationFlag
|
||||
|
||||
import scala.util.control.Breaks._
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
@ -13,14 +17,30 @@ object CoarseFlowAnalyzer {
|
||||
|
||||
val cache = new FlowCache[ZLine, CpuStatus]("z80 forward")
|
||||
|
||||
def analyze(f: NormalFunction, code: List[ZLine], compilationOptions: CompilationOptions): List[CpuStatus] = {
|
||||
def analyze(f: NormalFunction, code: List[ZLine], optimizationContext: OptimizationContext): List[CpuStatus] = {
|
||||
cache.get(code).foreach(return _)
|
||||
val initialStatus = CpuStatus()
|
||||
val functionStartStatus = CpuStatus()
|
||||
val emptyStatus = CpuStatus()
|
||||
val flagArray = Array.fill[CpuStatus](code.length)(emptyStatus)
|
||||
val codeArray = code.toArray
|
||||
val compilationOptions = optimizationContext.options
|
||||
val z80 = compilationOptions.flag(CompilationFlag.EmitZ80Opcodes)
|
||||
val niceFunctionProperties = optimizationContext.niceFunctionProperties
|
||||
def extractNiceConstant[T](callee: String)(matcher: NiceFunctionProperty => Option[T]): Status[T] = {
|
||||
var result: Status[T] = AnyStatus
|
||||
breakable {
|
||||
niceFunctionProperties.foreach{ np =>
|
||||
if (np._2 == callee) matcher(np._1) match {
|
||||
case Some(x) =>
|
||||
result = SingleStatus(x)
|
||||
break
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
val preservesB: Set[String] = Set("__mul_u8u8u8")
|
||||
val preservesC: Set[String] = if (z80) Set("__mul_u8u8u8") else Set()
|
||||
@ -65,12 +85,17 @@ object CoarseFlowAnalyzer {
|
||||
if (mayBeCalled) {
|
||||
val result = if (preservesStackVariables) initialStatus.copy(memIx = currentStatus.memIx) else initialStatus
|
||||
currentStatus = result.copy(
|
||||
b = if (preservesB(n)) currentStatus.b else result.b,
|
||||
c = if (preservesC(n)) currentStatus.c else result.c,
|
||||
d = if (preservesD(n)) currentStatus.d else result.d,
|
||||
e = if (preservesE(n)) currentStatus.e else result.e,
|
||||
h = if (preservesH(n)) currentStatus.h else result.h,
|
||||
l = if (preservesL(n)) currentStatus.l else result.l
|
||||
b = if (preservesB(n) || niceFunctionProperties(DoesntChangeBC -> n)) currentStatus.b else result.b,
|
||||
c = if (preservesC(n) || niceFunctionProperties(DoesntChangeBC -> n)) currentStatus.c else result.c,
|
||||
d = if (preservesD(n) || niceFunctionProperties(DoesntChangeDE -> n)) currentStatus.d else result.d,
|
||||
e = if (preservesE(n) || niceFunctionProperties(DoesntChangeDE-> n)) currentStatus.e else result.e,
|
||||
h = if (preservesH(n) || niceFunctionProperties(DoesntChangeHL -> n)) currentStatus.h else result.h,
|
||||
l = if (preservesL(n) || niceFunctionProperties(DoesntChangeHL -> n)) currentStatus.l else result.l,
|
||||
hl = if (preservesH(n) && preservesL(n) || niceFunctionProperties(DoesntChangeHL -> n)) currentStatus.hl else result.hl,
|
||||
a = extractNiceConstant(n){
|
||||
case SetsATo(a) => Some(a)
|
||||
case _ => None
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package millfork.assembly.z80.opt
|
||||
|
||||
import millfork.CompilationOptions
|
||||
import millfork.assembly.OptimizationContext
|
||||
import millfork.assembly.z80.{ZLine, ZLine0, ZOpcode}
|
||||
import millfork.env.{Label, MemoryAddressConstant, NormalFunction}
|
||||
|
||||
@ -31,10 +32,10 @@ object FlowAnalyzer {
|
||||
private val EmptyCpuStatus = CpuStatus()
|
||||
private val EmptyCpuImportance = CpuImportance()
|
||||
|
||||
def analyze(f: NormalFunction, code: List[ZLine], options: CompilationOptions, req: FlowInfoRequirement.Value): List[(FlowInfo, ZLine)] = {
|
||||
def analyze(f: NormalFunction, code: List[ZLine], optimizationContext: OptimizationContext, req: FlowInfoRequirement.Value): List[(FlowInfo, ZLine)] = {
|
||||
val forwardFlow = req match {
|
||||
case FlowInfoRequirement.BothFlows | FlowInfoRequirement.ForwardFlow =>
|
||||
() => CoarseFlowAnalyzer.analyze(f, code, options)
|
||||
() => CoarseFlowAnalyzer.analyze(f, code, optimizationContext)
|
||||
case FlowInfoRequirement.BackwardFlow | FlowInfoRequirement.JustLabels | FlowInfoRequirement.NoRequirement =>
|
||||
() => List.fill(code.size)(EmptyCpuStatus)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class RuleBasedAssemblyOptimization(val name: String, val needsFlowInfo: FlowInf
|
||||
actualRules.foreach(_.pattern.validate(needsFlowInfo))
|
||||
|
||||
override def optimize(f: NormalFunction, code: List[ZLine], optimizationContext: OptimizationContext): List[ZLine] = {
|
||||
val taggedCode = FlowAnalyzer.analyze(f, code, optimizationContext.options, needsFlowInfo)
|
||||
val taggedCode = FlowAnalyzer.analyze(f, code, optimizationContext, needsFlowInfo)
|
||||
val (changed, optimized) = optimizeImpl(f, taggedCode, optimizationContext)
|
||||
if (changed) optimized else code
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ class VariableStatus(val paramVariables: Set[String],
|
||||
|
||||
object VariableStatus {
|
||||
def apply(f: NormalFunction, code: List[ZLine], optimizationContext: OptimizationContext, typFilter: Type => Boolean): Option[VariableStatus] = {
|
||||
val flow = FlowAnalyzer.analyze(f, code, optimizationContext.options, FlowInfoRequirement.BothFlows)
|
||||
val flow = FlowAnalyzer.analyze(f, code, optimizationContext, FlowInfoRequirement.BothFlows)
|
||||
import millfork.node.ZRegister._
|
||||
val paramVariables = f.params match {
|
||||
case NormalParamSignature(List(MemoryVariable(_, typ, _))) if typ.size == 1 =>
|
||||
|
@ -2,6 +2,7 @@ package millfork.node
|
||||
|
||||
import millfork.assembly.Elidability
|
||||
import millfork.assembly.m6809.{MAddrMode, MOpcode}
|
||||
import millfork.assembly.mos.opt.SourceOfNZ
|
||||
import millfork.assembly.mos.{AddrMode, Opcode}
|
||||
import millfork.assembly.z80.{ZOpcode, ZRegisters}
|
||||
import millfork.env.{Constant, ParamPassingConvention, Type}
|
||||
@ -182,6 +183,12 @@ object MosNiceFunctionProperty {
|
||||
case object DoesntChangeC extends NiceFunctionProperty("C")
|
||||
case object DoesntConcernD extends NiceFunctionProperty("D")
|
||||
case object DoesntChangeZpRegister extends NiceFunctionProperty("reg")
|
||||
case class SetsSourceOfNZ(sourceOfNZ: SourceOfNZ) extends NiceFunctionProperty(sourceOfNZ + "NZ")
|
||||
case class SetsXTo(value: Int) extends NiceFunctionProperty("Y=" + value)
|
||||
case class SetsYTo(value: Int) extends NiceFunctionProperty("Z=" + value)
|
||||
case class SetsATo(value: Int) extends NiceFunctionProperty("A=" + value)
|
||||
case class Bit0OfA(value: Boolean) extends NiceFunctionProperty("A0=" + value)
|
||||
case class Bit7OfA(value: Boolean) extends NiceFunctionProperty("A7=" + value)
|
||||
}
|
||||
|
||||
object Z80NiceFunctionProperty {
|
||||
@ -189,6 +196,7 @@ object Z80NiceFunctionProperty {
|
||||
case object DoesntChangeDE extends NiceFunctionProperty("DE")
|
||||
case object DoesntChangeHL extends NiceFunctionProperty("HL")
|
||||
case object DoesntChangeIY extends NiceFunctionProperty("IY")
|
||||
case class SetsATo(value: Int) extends NiceFunctionProperty("A=" + value)
|
||||
}
|
||||
|
||||
object MosRegister extends Enumeration {
|
||||
|
@ -243,7 +243,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
||||
log.debug("Inlining " + f, function.position)
|
||||
inlinedFunctions += f -> c
|
||||
val tmp = mutable.Set[(NiceFunctionProperty, String)]()
|
||||
gatherNiceFunctionProperties(tmp, f, c)
|
||||
gatherNiceFunctionProperties(options, tmp, function, c)
|
||||
if (tmp.exists(_._1 == IsLeaf)) {
|
||||
functionsThatCanBeCalledFromInlinedFunctions += function.name
|
||||
}
|
||||
@ -254,7 +254,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
||||
compiledFunctions(f) = NormalCompiledFunction(function.declaredBank.getOrElse(platform.defaultCodeBank), code, function.address.isDefined, function.alignment)
|
||||
optimizedCodeSize += code.map(_.sizeInBytes).sum
|
||||
if (options.flag(CompilationFlag.InterproceduralOptimization)) {
|
||||
gatherNiceFunctionProperties(niceFunctionProperties, f, code)
|
||||
gatherNiceFunctionProperties(options, niceFunctionProperties, function, code)
|
||||
}
|
||||
}
|
||||
function.environment.removedThings.foreach(env.removeVariable)
|
||||
@ -625,7 +625,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
|
||||
|
||||
def quickSimplify(code: List[T]): List[T]
|
||||
|
||||
def gatherNiceFunctionProperties(niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], functionName: String, code: List[T]): Unit
|
||||
def gatherNiceFunctionProperties(options: CompilationOptions, niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], function: NormalFunction, code: List[T]): Unit
|
||||
|
||||
def performFinalOptimizationPass(f: NormalFunction, actuallyOptimize: Boolean, options: CompilationOptions, code: List[T]): List[T]
|
||||
|
||||
|
@ -23,7 +23,7 @@ class M6809Assembler(program: Program,
|
||||
|
||||
override def quickSimplify(code: List[MLine]): List[MLine] = code
|
||||
|
||||
override def gatherNiceFunctionProperties(niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], functionName: String, code: List[MLine]): Unit = ()
|
||||
override def gatherNiceFunctionProperties(options: CompilationOptions, niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], function: NormalFunction, code: List[MLine]): Unit = ()
|
||||
|
||||
override def performFinalOptimizationPass(f: NormalFunction, actuallyOptimize: Boolean, options: CompilationOptions, code: List[MLine]): List[MLine] = code
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
package millfork.output
|
||||
|
||||
import millfork.assembly.mos.opt.{HudsonOptimizations, JumpFixing, JumpFollowing, JumpShortening}
|
||||
import millfork.assembly.mos.opt.{CoarseFlowAnalyzer, CpuStatus, HudsonOptimizations, JumpFixing, JumpFollowing, JumpShortening, SourceOfNZ}
|
||||
import millfork.assembly._
|
||||
import millfork.env._
|
||||
import millfork.error.{ConsoleLogger, FatalErrorReporting}
|
||||
import millfork.node.{MosNiceFunctionProperty, NiceFunctionProperty, Program}
|
||||
import millfork._
|
||||
import millfork.assembly.mos._
|
||||
import millfork.assembly.opt.{SingleStatus, Status}
|
||||
import millfork.compiler.mos.MosCompiler
|
||||
|
||||
import scala.annotation.tailrec
|
||||
@ -105,16 +106,44 @@ class MosAssembler(program: Program,
|
||||
|
||||
override def quickSimplify(code: List[AssemblyLine]): List[AssemblyLine] = code.map(a => a.copy(parameter = a.parameter.quickSimplify))
|
||||
|
||||
override def gatherNiceFunctionProperties(niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], functionName: String, code: List[AssemblyLine]): Unit = {
|
||||
override def gatherNiceFunctionProperties(options: CompilationOptions, niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], function: NormalFunction, code: List[AssemblyLine]): Unit = {
|
||||
import Opcode._
|
||||
import AddrMode._
|
||||
import MosNiceFunctionProperty._
|
||||
import NiceFunctionProperty._
|
||||
val functionName = function.name
|
||||
if (isNaughty(code)) return
|
||||
val localLabels = code.flatMap {
|
||||
case AssemblyLine0(LABEL, _, MemoryAddressConstant(Label(l))) => Some(l)
|
||||
case _ => None
|
||||
}.toSet
|
||||
if (code.exists {
|
||||
case AssemblyLine0(op, _, MemoryAddressConstant(Label(l))) if OpcodeClasses.AllDirectJumps(op) => !localLabels(l)
|
||||
case AssemblyLine0(op, _, _) if OpcodeClasses.AllDirectJumps(op) => true
|
||||
case AssemblyLine0(BRK | RTI, _, _) => true
|
||||
case _ => false
|
||||
}) return
|
||||
val optimizationContext = OptimizationContext(options, Map(), function.environment.maybeGet[ThingInMemory]("__reg"), Set())
|
||||
val flow = CoarseFlowAnalyzer.analyze(function, code, optimizationContext)
|
||||
def rtsPropertyScan[T](extractor: CpuStatus => Status[T])(niceFunctionProperty: Status[T] => Option[NiceFunctionProperty]): Unit = {
|
||||
val statuses = code.zipWithIndex.flatMap{
|
||||
case (AssemblyLine0(RTS, _, _), ix) => Some(extractor(flow(ix)))
|
||||
case _ => None
|
||||
}.toSet
|
||||
statuses.toSeq match {
|
||||
case Seq(only) =>
|
||||
niceFunctionProperty(only).foreach { np =>
|
||||
niceFunctionProperties += (np -> functionName)
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
def simpleRtsPropertyScan[T](extractor: CpuStatus => Status[T])(niceFunctionProperty: T => NiceFunctionProperty): Unit = {
|
||||
rtsPropertyScan(extractor) {
|
||||
case SingleStatus(x) => Some(niceFunctionProperty(x))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
def genericPropertyScan(niceFunctionProperty: NiceFunctionProperty)(predicate: AssemblyLine => Boolean): Unit = {
|
||||
val preserved = code.forall {
|
||||
case AssemblyLine0(JSR | BSR | JMP, Absolute | LongAbsolute, MemoryAddressConstant(th)) => niceFunctionProperties(niceFunctionProperty -> th.name)
|
||||
@ -171,6 +200,12 @@ class MosAssembler(program: Program,
|
||||
case AssemblyLine0(JMP, Absolute, th:Thing) => th.name.startsWith(".")
|
||||
case _ => true
|
||||
}
|
||||
simpleRtsPropertyScan(_.src)(SetsSourceOfNZ)
|
||||
simpleRtsPropertyScan(_.a0)(Bit0OfA)
|
||||
simpleRtsPropertyScan(_.a7)(Bit7OfA)
|
||||
simpleRtsPropertyScan(_.a)(SetsATo)
|
||||
simpleRtsPropertyScan(_.x)(SetsXTo)
|
||||
simpleRtsPropertyScan(_.y)(SetsYTo)
|
||||
}
|
||||
|
||||
override def bytePseudoopcode: String = "!byte"
|
||||
|
@ -1,12 +1,16 @@
|
||||
package millfork.output
|
||||
|
||||
import millfork.assembly.OptimizationContext
|
||||
import millfork.assembly.opt.{SingleStatus, Status}
|
||||
import millfork.{CompilationFlag, CompilationOptions, Cpu, Platform}
|
||||
import millfork.assembly.z80.{ZOpcode, _}
|
||||
import millfork.assembly.z80.opt.{ConditionalInstructions, JumpFollowing, JumpShortening}
|
||||
import millfork.assembly.z80.opt.{CoarseFlowAnalyzer, ConditionalInstructions, CpuStatus, JumpFollowing, JumpShortening}
|
||||
import millfork.compiler.z80.Z80Compiler
|
||||
import millfork.env._
|
||||
import millfork.node.Z80NiceFunctionProperty.{DoesntChangeBC, DoesntChangeDE, DoesntChangeHL, DoesntChangeIY, SetsATo}
|
||||
import millfork.node.{NiceFunctionProperty, Program, ZRegister}
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.mutable
|
||||
|
||||
/**
|
||||
@ -693,8 +697,68 @@ class Z80Assembler(program: Program,
|
||||
|
||||
override def quickSimplify(code: List[ZLine]): List[ZLine] = code.map(a => a.copy(parameter = a.parameter.quickSimplify))
|
||||
|
||||
override def gatherNiceFunctionProperties(niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], functionName: String, code: List[ZLine]): Unit = {
|
||||
// do nothing yet
|
||||
override def gatherNiceFunctionProperties(options: CompilationOptions, niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], function: NormalFunction, code: List[ZLine]): Unit = {
|
||||
import ZOpcode._
|
||||
val functionName = function.name
|
||||
if (isNaughty(code)) return
|
||||
val localLabels = code.flatMap {
|
||||
case ZLine0(LABEL, _, MemoryAddressConstant(Label(l))) => Some(l)
|
||||
case _ => None
|
||||
}.toSet
|
||||
if (code.exists {
|
||||
case ZLine0(JP | JR, _, MemoryAddressConstant(Label(l))) => !localLabels(l)
|
||||
case ZLine0(JP | JR, _, _) => true
|
||||
case ZLine0(RST, _, _) => true
|
||||
case _ => false
|
||||
}) return
|
||||
val optimizationContext = OptimizationContext(options, Map(), None, Set())
|
||||
val flow = CoarseFlowAnalyzer.analyze(function, code, optimizationContext)
|
||||
def retPropertyScan[T](extractor: CpuStatus => Status[T])(niceFunctionProperty: Status[T] => Option[NiceFunctionProperty]): Unit = {
|
||||
val statuses = code.zipWithIndex.flatMap{
|
||||
case (ZLine0(RET | RETI | RETN, _, _), ix) => Some(extractor(flow(ix)))
|
||||
case _ => None
|
||||
}.toSet
|
||||
statuses.toSeq match {
|
||||
case Seq(only) =>
|
||||
niceFunctionProperty(only).foreach { np =>
|
||||
niceFunctionProperties += (np -> functionName)
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
def simpleRetPropertyScan[T](extractor: CpuStatus => Status[T])(niceFunctionProperty: T => NiceFunctionProperty): Unit = {
|
||||
retPropertyScan(extractor) {
|
||||
case SingleStatus(x) => Some(niceFunctionProperty(x))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
def genericPropertyScan(niceFunctionProperty: NiceFunctionProperty)(predicate: ZLine => Boolean): Unit = {
|
||||
val preserved = code.forall {
|
||||
case ZLine0(JP | JR, _, MemoryAddressConstant(Label(label))) => localLabels(label)
|
||||
case ZLine0(CALL | JP | JR, _, MemoryAddressConstant(th)) => niceFunctionProperties(niceFunctionProperty -> th.name)
|
||||
case ZLine0(CALL | JP | JR, _, _) => false
|
||||
case l => predicate(l)
|
||||
}
|
||||
if (preserved) {
|
||||
niceFunctionProperties += (niceFunctionProperty -> functionName)
|
||||
}
|
||||
}
|
||||
genericPropertyScan(DoesntChangeHL)(l => !l.changesRegister(ZRegister.HL))
|
||||
genericPropertyScan(DoesntChangeDE)(l => !l.changesRegister(ZRegister.DE))
|
||||
genericPropertyScan(DoesntChangeBC)(l => !l.changesRegister(ZRegister.BC))
|
||||
genericPropertyScan(DoesntChangeIY)(l => !l.changesRegister(ZRegister.IY))
|
||||
simpleRetPropertyScan(_.a)(SetsATo)
|
||||
}
|
||||
|
||||
@tailrec
|
||||
private def isNaughty(code: List[ZLine]): Boolean = {
|
||||
import ZOpcode._
|
||||
code match {
|
||||
case ZLine0(JP, OneRegister(_), _) :: _ => true
|
||||
case ZLine0(PUSH, _, _) :: ZLine0(RET | RETI | RETN, _, _) :: _ => true
|
||||
case _ :: xs => isNaughty(xs)
|
||||
case Nil => false
|
||||
}
|
||||
}
|
||||
|
||||
override def bytePseudoopcode: String = "DB"
|
||||
|
@ -26,7 +26,7 @@ class Z80ToX86Crossassembler(program: Program,
|
||||
|
||||
override def quickSimplify(code: List[ZLine]): List[ZLine] = code.map(a => a.copy(parameter = a.parameter.quickSimplify))
|
||||
|
||||
override def gatherNiceFunctionProperties(niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], functionName: String, code: List[ZLine]): Unit = {
|
||||
override def gatherNiceFunctionProperties(options: CompilationOptions, niceFunctionProperties: mutable.Set[(NiceFunctionProperty, String)], function: NormalFunction, code: List[ZLine]): Unit = {
|
||||
// do nothing yet
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user