1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-23 23:30:22 +00:00

#101: Allow using local labels in all assembly instructions and all assembly expressions

This commit is contained in:
Karol Stasiak 2021-02-03 09:50:44 +01:00
parent 9c7e946f4c
commit 919f11af2e
8 changed files with 55 additions and 13 deletions

View File

@ -52,10 +52,7 @@ object FlowAnalyzer {
}
val labelMap: () => Option[Map[String, Int]] = () => req match {
case FlowInfoRequirement.NoRequirement => None
case _ => Some(code.flatMap {
case MLine0(op, _, MemoryAddressConstant(Label(l))) if op != MOpcode.LABEL => Some(l)
case _ => None
}.groupBy(identity).mapValues(_.size).view.force)
case _ => Some(code.flatMap(_.parameter.extractLabels).groupBy(identity).mapValues(_.size).view.force)
}
val holder = new FlowHolder(forwardFlow, reverseFlow)
code.zipWithIndex.map{ case (line, i) => FlowInfo(holder, i, labelMap) -> line}

View File

@ -52,11 +52,7 @@ object FlowAnalyzer {
}
val labelMap: () => Option[Map[String, Int]] = () => req match {
case FlowInfoRequirement.NoRequirement => None
case _ => Some(code.flatMap {
case AssemblyLine0(op, _, MemoryAddressConstant(Label(l))) if op != Opcode.LABEL => Some(l)
case AssemblyLine0(op, _, StructureConstant(_, List(_, MemoryAddressConstant(Label(l))))) => Some(l)
case _ => None
}.groupBy(identity).mapValues(_.size).view.force)
case _ => Some(code.flatMap(_.parameter.extractLabels).groupBy(identity).mapValues(_.size).view.force)
}
val holder = new FlowHolder(forwardFlow, reverseFlow)
code.zipWithIndex.map{ case (line, i) => FlowInfo(holder, i, labelMap) -> line}

View File

@ -47,10 +47,7 @@ object FlowAnalyzer {
}
val labelMap: (() => Option[Map[String, Int]]) = () => req match {
case FlowInfoRequirement.NoRequirement => None
case _ => Some(code.flatMap {
case ZLine0(op, _, MemoryAddressConstant(Label(l))) if op != ZOpcode.LABEL => Some(l)
case _ => None
}.groupBy(identity).mapValues(_.size).view.force)
case _ => Some(code.flatMap(_.parameter.extractLabels).groupBy(identity).mapValues(_.size).view.force)
}
val holder = new FlowHolder(forwardFlow, reverseFlow)
code.zipWithIndex.map{ case (line, i) => FlowInfo(holder, i, labelMap) -> line}

View File

@ -5,6 +5,8 @@ import millfork.DecimalUtils._
import millfork.node.{ResolvedFieldDesc, SumExpression}
import millfork.output.DivisibleAlignment
import scala.collection.GenTraversableOnce
object Constant {
val Zero: Constant = NumericConstant(0, 1)
val WordZero: Constant = NumericConstant(0, 2)
@ -129,6 +131,8 @@ sealed trait Constant {
def refersTo(name: String): Boolean
def extractLabels: List[String]
def fitsInto(typ: Type): Boolean = true // TODO
def fitInto(typ: Type): Constant = {
@ -196,6 +200,8 @@ case class AssertByte(c: Constant) extends Constant {
override def fitsInto(typ: Type): Boolean = true
override def toIntelString: String = c.toIntelString
override def rootThingName: String = c.rootThingName
override def extractLabels: List[String] = c.extractLabels
}
case class StructureConstant(typ: StructType, fields: List[Constant]) extends Constant {
@ -240,6 +246,8 @@ case class StructureConstant(typ: StructType, fields: List[Constant]) extends Co
Constant.Zero
}
override def rootThingName: String = "?"
override def extractLabels: List[String] = this.fields.flatMap(_.extractLabels)
}
case class UnexpandedConstant(name: String, requiredSize: Int) extends Constant {
@ -252,6 +260,8 @@ case class UnexpandedConstant(name: String, requiredSize: Int) extends Constant
override def refersTo(name: String): Boolean = name == this.name
override def rootThingName: String = "?"
override def extractLabels: List[String] = Nil
}
case class NumericConstant(value: Long, requiredSize: Int) extends Constant {
@ -336,6 +346,8 @@ case class NumericConstant(value: Long, requiredSize: Int) extends Constant {
}
override def rootThingName: String = ""
override def extractLabels: List[String] = Nil
}
case class MemoryAddressConstant(var thing: ThingInMemory) extends Constant {
@ -376,6 +388,11 @@ case class MemoryAddressConstant(var thing: ThingInMemory) extends Constant {
override def refersTo(name: String): Boolean = name == thing.name
override def rootThingName: String = thing.rootName
override def extractLabels: List[String] = thing match {
case Label(n) => List(n)
case _ => Nil
}
}
case class SubbyteConstant(base: Constant, index: Int) extends Constant {
@ -416,6 +433,8 @@ case class SubbyteConstant(base: Constant, index: Int) extends Constant {
override def refersTo(name: String): Boolean = base.refersTo(name)
override def rootThingName: String = base.rootThingName
override def extractLabels: List[String] = base.extractLabels
}
object MathOperator extends Enumeration {
@ -758,4 +777,6 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
case (x, "") => x
case _ => "?"
}
override def extractLabels: List[String] = lhs.extractLabels ++ rhs.extractLabels
}

View File

@ -21,6 +21,21 @@ class AssemblySuite extends FunSuite with Matchers with AppendedClues {
""".stripMargin)(_.readByte(0xc000) should equal(1))
}
test("Self-modifying assembly") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Motorola6809)(
"""
| byte output @$c000
| // w&x
| asm void main () {
| lda #3
| sta .l+1
| .l: lda #55
| sta output
| rts
| ignored:}
""".stripMargin)(_.readByte(0xc000) should equal(3))
}
test("Assembly functions") {
EmuBenchmarkRun(
"""
@ -32,6 +47,7 @@ class AssemblySuite extends FunSuite with Matchers with AppendedClues {
| asm void thing() {
| inc $c000
| rts
| ignored:
| }
""".stripMargin)(_.readByte(0xc000) should equal(1))
}

View File

@ -175,6 +175,11 @@ class EmuM6809Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizat
if (memoryBank.readable(i)) memoryBank.readable(i + 1) = true
}
}
if (source.contains("w&x")) {
for (i <- 0 until 0x10000) {
memoryBank.writeable(i) = true
}
}
val timings = run(log, memoryBank, platform.codeAllocators("default").startAt)
log.clearErrors()
timings

View File

@ -281,6 +281,11 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
if (memoryBank.readable(i)) memoryBank.readable(i + 1) = true
}
}
if (source.contains("w&x")) {
for (i <- 0 until 0x10000) {
memoryBank.writeable(i) = true
}
}
(0x200 until 0x2000).takeWhile(memoryBank.occupied(_)).map(memoryBank.output).grouped(16).map(_.map(i => f"$i%02x").mkString(" ")).foreach(log.debug(_))
val timings = platform.cpu match {
case millfork.Cpu.Cmos =>

View File

@ -173,6 +173,11 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
memoryBank.readable(i) = true
memoryBank.writeable(i) = true
}
if (source.contains("w&x")) {
for (i <- 0 until 0x10000) {
memoryBank.writeable(i) = true
}
}
// LD SP,$fffe
// CALL $0200