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:
parent
9c7e946f4c
commit
919f11af2e
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
21
src/main/scala/millfork/env/Constant.scala
vendored
21
src/main/scala/millfork/env/Constant.scala
vendored
@ -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
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 =>
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user