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:
@@ -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`
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user