1
0
mirror of https://github.com/KarolS/millfork.git synced 2026-04-20 03:16:45 +00:00

Allow emitting addresses of labels in the output (#78)

This commit is contained in:
Karol Stasiak
2020-11-19 18:33:51 +01:00
parent c8e32a876f
commit 7e45967b0c
5 changed files with 65 additions and 6 deletions
+8 -2
View File
@@ -204,9 +204,15 @@ Default: `main,*`
* `endaddr_be` the same, but big-endian
* `startaddr+123`, `startaddr_be+123`, `endaddr+123`, `endaddr_be+123` the same, but incremented by the given number
* `addr:XXXX` little-endian 16-bit address of the symbol XXXX
* `addr_be:XXXX` the same, but big-endian
* `startaddr+123`, `startaddr_be+123`, `endaddr+123`, `endaddr_be+123`, `addr:XXXX+123`, `addr_be:XXXX+123` the same, but incremented by the given number
* `startaddr-123`, `startaddr_be-123`, `endaddr-123`, `endaddr_be-123` the same, but decremented by the given number
* the number can be decimal, hexadecimal, octal, quaternary or binary
* `startaddr-123`, `startaddr_be-123`, `endaddr-123`, `endaddr_be-123`, `addr:XXXX-123`, `addr_be:XXXX-123` the same, but decremented by the given number
* `startpage` the high byte of `startaddr`
+27 -2
View File
@@ -289,7 +289,17 @@ object Platform {
case "trscmd" => TrsCmdOutput
case n => n.split(":").filter(_.nonEmpty) match {
case Array(b, s, e) => BankFragmentOutput(b, parseNumber(s), parseNumber(e))
case Array(s, e) => CurrentBankFragmentOutput(parseNumber(s), parseNumber(e))
case Array(s, e) =>
s match {
case "addr" =>
val (symbol, bonus) = parseSymbolAndBonus(e)
SymbolAddressOutput(symbol, bonus)
case "addr_be" =>
val (symbol, bonus) = parseSymbolAndBonus(e)
SymbolAddressOutputBe(symbol, bonus)
case _ =>
CurrentBankFragmentOutput(parseNumber(s), parseNumber(e))
}
case Array(b) => try {
ConstOutput(parseNumber(b).toByte)
} catch {
@@ -424,7 +434,8 @@ object Platform {
}
}
def parseNumber(s: String): Int = {
def parseNumber(str: String): Int = {
val s = str.trim
if (s.startsWith("$")) {
Integer.parseInt(s.substring(1), 16)
} else if (s.startsWith("0x")) {
@@ -449,4 +460,18 @@ object Platform {
s.toInt
}
}
def parseSymbolAndBonus(token: String): (String, Int) = {
if (token.contains("+")) {
token.split("\\+", 2) match {
case Array(n, b) => n.trim -> parseNumber(b)
}
} else if (token.contains("-")) {
token.split("-", 2) match {
case Array(n, b) => n.trim -> -parseNumber(b)
}
} else {
token.trim -> 0
}
}
}
@@ -33,9 +33,9 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
var initializedVariablesSize: Int = 0
protected val log: Logger = rootEnv.log
val mem = new CompiledMemory(platform.bankNumbers.toList, platform.bankFill, platform.isBigEndian)
val labelMap: mutable.Map[String, (Int, Int)] = mutable.Map()
val unimportantLabelMap: mutable.Map[String, (Int, Int)] = mutable.Map()
val mem = new CompiledMemory(platform.bankNumbers.toList, platform.bankFill, platform.isBigEndian, labelMap, log)
val breakpointSet: mutable.Set[(Int, Int)] = mutable.Set()
private val bytesToWriteLater = mutable.ListBuffer[(String, Int, Constant, Option[Position])]()
private val wordsToWriteLater = mutable.ListBuffer[(String, Int, Constant, Option[Position])]()
@@ -1,17 +1,28 @@
package millfork.output
import millfork.error.Logger
import scala.collection.mutable
/**
* @author Karol Stasiak
*/
class CompiledMemory(bankNames: List[(String, Int)], bankFills: Map[String, Int], bigEndian: Boolean) {
class CompiledMemory(bankNames: List[(String, Int)], bankFills: Map[String, Int], bigEndian: Boolean, labels: mutable.Map[String, (Int, Int)], log: Logger) {
var programName = "MILLFORK"
val banks: mutable.Map[String, MemoryBank] = mutable.Map(bankNames.map{p =>
val bank = new MemoryBank(p._2, bigEndian)
bank.fill(bankFills.getOrElse(p._1, 0))
p._1 -> bank
}: _*)
def getAddress(symbol: String): Int = {
if (labels.contains(symbol)) {
labels(symbol)._2
} else {
log.error(s"Symbol `$symbol` (used in the output format) is not defined")
0
}
}
}
class MemoryBank(val index: Int, val isBigEndian: Boolean) {
@@ -92,6 +92,23 @@ case class EndAddressOutputBe(bonus: Int) extends OutputPackager {
}
}
case class SymbolAddressOutput(symbol: String, bonus: Int) extends OutputPackager {
def packageOutput(mem: CompiledMemory, bank: String): Array[Byte] = {
val b = mem.banks(bank)
val x = mem.getAddress(symbol) + bonus
Array(b.end.toByte, b.end.>>(8).toByte)
}
}
case class SymbolAddressOutputBe(symbol: String, bonus: Int) extends OutputPackager {
def packageOutput(mem: CompiledMemory, bank: String): Array[Byte] = {
val b = mem.banks(bank)
val x = mem.getAddress(symbol) + bonus
Array(x.>>(8).toByte, x.toByte)
}
}
object PageCountOutput extends OutputPackager {
def packageOutput(mem: CompiledMemory, bank: String): Array[Byte] = {
val e = mem.banks(bank).end.>>(8)