From c9ef5e636bdfc9c896a820f1eda015a6c892e0fc Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Tue, 21 Sep 2021 00:09:59 +0200 Subject: [PATCH] Add raw label file format --- docs/api/command-line.md | 2 + examples/crossplatform/fire.labels | 141 ++++++++++++++++++ .../scala/millfork/DebugOutputFormat.scala | 39 +++-- src/main/scala/millfork/Main.scala | 16 +- src/main/scala/millfork/env/Environment.scala | 6 +- .../millfork/output/AbstractAssembler.scala | 33 +++- .../scala/millfork/test/emu/EmuM6809Run.scala | 2 +- src/test/scala/millfork/test/emu/EmuRun.scala | 2 +- .../scala/millfork/test/emu/EmuZ80Run.scala | 2 +- 9 files changed, 216 insertions(+), 27 deletions(-) create mode 100644 examples/crossplatform/fire.labels diff --git a/docs/api/command-line.md b/docs/api/command-line.md index efe40bcf..3e9ecdb2 100644 --- a/docs/api/command-line.md +++ b/docs/api/command-line.md @@ -47,6 +47,8 @@ The extension and the file format are platform-dependent. * `-G sym` – format used by the WLA DX assembler. The extension is `.sym`. * `-G fceux` – multi-file format used by the FCEUX emulator. The extension is `.nl`. + + * `-G raw` – Millfork-specific format. The extension is '.labels'. Each row contains bank number, start address, end address (if known), object type, and Millfork-specific object identifier. * `-fbreakpoints`, `-fno-breakpoints` – Whether the compiler should use the `breakpoint` macro. diff --git a/examples/crossplatform/fire.labels b/examples/crossplatform/fire.labels new file mode 100644 index 00000000..609d1264 --- /dev/null +++ b/examples/crossplatform/fire.labels @@ -0,0 +1,141 @@ +00:0000:0000:v:cpu6510_ddr +00:0001:0001:v:cpu6510_port +00:0043:0044:v:fire$p +00:0045:0045:v:fire$noise +00:0046:0046:v:fire$column +00:0047:0047:v:fire$heat +00:0048:0048:v:fire$entropy +00:004B:004B:v:fire$row +00:004C:004C:v:cls$i +00:009E:009E:v:main$i +00:00F7:00F7:v:build_reverse_palette$j +00:00F8:00F8:v:build_reverse_palette$i +00:00F9:00FA:v:rand_seed +00:00FB:00FE:v:__reg +00:0314:0315:v:irq_pointer +00:0315:0315:v:irq_pointer.hi +00:0400:07E7:a:screen.array +00:0801:080C:A:_basic_loader.array +00:080D:083B:F:main +00:0824::x:.do__00031 +00:0832::x:.od__00033 +00:0838::x:.fp__00037 +00:083B::x:.ew__00038 +00:083C:0846:F:wait_frame +00:083F::x:.fp__00018 +00:0846::x:.ew__00019 +00:0847:08A8:F:fire +00:0857::x:.do__00001 +00:085D::x:.do__00004 +00:086C::x:.fi__00007 +00:0886::x:.fi__00008 +00:0897::x:.od__00006 +00:08A8::x:.od__00003 +00:08A9:08F5:F:cls +00:08AD::x:.do__00010 +00:08CF::x:.od__00012 +00:08D3::x:.do__00013 +00:08F5::x:.od__00015 +00:08F6:0928:F:build_reverse_palette +00:08FA::x:.do__00020 +00:0900::x:.wh__00023 +00:0913::x:.fp__00025 +00:091F::x:.el__00027 +00:0921::x:.fi__00028 +00:0924::x:.ew__00026 +00:0928::x:.od__00022 +00:0929:0939:F:rand +00:092D::x:__rand_loop +00:0934::x:__no_eor +00:093A:093E:A:palette.array +00:0A00:0AFF:a:reverse_palette.array +00:D000:D000:v:vic_spr0_x +00:D001:D001:v:vic_spr0_y +00:D002:D002:v:vic_spr1_x +00:D003:D003:v:vic_spr1_y +00:D004:D004:v:vic_spr2_x +00:D005:D005:v:vic_spr2_y +00:D006:D006:v:vic_spr3_x +00:D007:D007:v:vic_spr3_y +00:D008:D008:v:vic_spr4_x +00:D009:D009:v:vic_spr4_y +00:D00A:D00A:v:vic_spr5_x +00:D00B:D00B:v:vic_spr5_y +00:D00C:D00C:v:vic_spr6_x +00:D00D:D00D:v:vic_spr6_y +00:D00E:D00E:v:vic_spr7_x +00:D00F:D00F:v:vic_spr7_y +00:D010:D010:v:vic_spr_hi_x +00:D011:D011:v:vic_cr1 +00:D012:D012:v:vic_raster +00:D013:D013:v:vic_lp_x +00:D014:D014:v:vic_lp_y +00:D015:D015:v:vic_spr_ena +00:D016:D016:v:vic_cr2 +00:D017:D017:v:vic_spr_exp_y +00:D018:D018:v:vic_mem +00:D019:D019:v:vic_irq +00:D01A:D01A:v:vic_irq_ena +00:D01B:D01B:v:vic_spr_dp +00:D01C:D01C:v:vic_spr_mcolor +00:D01D:D01D:v:vic_spr_exp_x +00:D01E:D01E:v:vic_spr_ss_col +00:D01F:D01F:v:vic_spr_sd_col +00:D020:D020:v:vic_border +00:D021:D021:v:vic_bg_color0 +00:D022:D022:v:vic_bg_color1 +00:D023:D023:v:vic_bg_color2 +00:D024:D024:v:vic_bg_color3 +00:D025:D025:v:vic_spr_color1 +00:D026:D026:v:vic_spr_color2 +00:D027:D027:v:vic_spr0_color +00:D028:D028:v:vic_spr1_color +00:D029:D029:v:vic_spr2_color +00:D02A:D02A:v:vic_spr3_color +00:D02B:D02B:v:vic_spr4_color +00:D02C:D02C:v:vic_spr5_color +00:D02D:D02D:v:vic_spr6_color +00:D02E:D02E:v:vic_spr7_color +00:D400:D401:v:sid_v1_freq +00:D401:D401:v:sid_v1_freq.hi +00:D402:D403:v:sid_v1_pulse +00:D403:D403:v:sid_v1_pulse.hi +00:D404:D404:v:sid_v1_cr +00:D405:D405:v:sid_v1_ad +00:D407:D408:v:sid_v2_freq +00:D408:D408:v:sid_v2_freq.hi +00:D409:D409:v:sid_v1_sr +00:D40A:D40A:v:sid_v2_pulse.hi +00:D40B:D40B:v:sid_v2_cr +00:D40C:D40C:v:sid_v2_ad +00:D40D:D40D:v:sid_v2_sr +00:D40E:D40F:v:sid_v3_freq +00:D40F:D40F:v:sid_v3_freq.hi +00:D410:D411:v:sid_v3_pulse +00:D411:D411:v:sid_v3_pulse.hi +00:D412:D412:v:sid_v3_cr +00:D413:D413:v:sid_v3_ad +00:D414:D414:v:sid_v3_sr +00:D415:D416:v:sid_filt_cutoff +00:D416:D416:v:sid_filt_cutoff.hi +00:D417:D417:v:sid_filt_cr +00:D418:D418:v:sid_filt_mode +00:D419:D419:v:sid_paddle_x +00:D41A:D41A:v:sid_paddle_y +00:D41B:D41B:v:sid_v3_osc_out +00:D41C:D41C:v:sid_v3_adsr_out +00:D800:DBE7:a:c64_color_ram.array +00:DC00:DC00:v:cia1_pra +00:DC01:DC01:v:cia1_prb +00:DC02:DC02:v:cia1_ddra +00:DC03:DC03:v:cia1_ddrb +00:DD00:DD00:v:cia2_pra +00:DD01:DD01:v:cia2_prb +00:DD02:DD02:v:cia2_ddra +00:DD03:DD03:v:cia2_ddrb +00:FFFA:FFFB:v:nmi_routine_addr +00:FFFB:FFFB:v:nmi_routine_addr.hi +00:FFFC:FFFD:v:reset_routine_addr +00:FFFD:FFFD:v:reset_routine_addr.hi +00:FFFE:FFFF:v:irq_routine_addr +00:FFFF:FFFF:v:irq_routine_addr.hi diff --git a/src/main/scala/millfork/DebugOutputFormat.scala b/src/main/scala/millfork/DebugOutputFormat.scala index a4366fe8..c1924ab7 100644 --- a/src/main/scala/millfork/DebugOutputFormat.scala +++ b/src/main/scala/millfork/DebugOutputFormat.scala @@ -6,6 +6,7 @@ package millfork object DebugOutputFormat { val map: Map[String, DebugOutputFormat] = Map( + "raw" -> RawDebugOutputFormat, "vice" -> ViceDebugOutputFormat, "nesasm" -> NesasmDebugOutputFormat, "fns" -> NesasmDebugOutputFormat, @@ -16,7 +17,7 @@ object DebugOutputFormat { sealed trait DebugOutputFormat { - def formatAll(labels: Seq[(String, (Int, Int))], breakpoints: Seq[(Int, Int)]): String = { + def formatAll(labels: Seq[(String, Int, Int, Char, Option[Int])], breakpoints: Seq[(Int, Int)]): String = { val labelPart = labelsHeader + labels.map(formatLineTupled).mkString("\n") + "\n" if (breakpoints.isEmpty) { labelPart @@ -25,9 +26,10 @@ sealed trait DebugOutputFormat { } } - final def formatLineTupled(labelAndValue: (String, (Int, Int))): String = formatLine(labelAndValue._1, labelAndValue._2._1, labelAndValue._2._2) + final def formatLineTupled(labelAndValue: (String, Int, Int, Char, Option[Int])): String = + formatLine(labelAndValue._1, labelAndValue._2, labelAndValue._3, labelAndValue._4, labelAndValue._5) - def formatLine(label: String, bank: Int, value: Int): String + def formatLine(label: String, bank: Int, startValue: Int, category: Char, endValue: Option[Int]): String final def formatBreakpointTupled(value: (Int, Int)): Seq[String] = formatBreakpoint(value._1, value._2).toSeq @@ -45,10 +47,25 @@ sealed trait DebugOutputFormat { def breakpointsHeader: String = "" } +object RawDebugOutputFormat extends DebugOutputFormat { + override def formatLine(label: String, bank: Int, startValue: Int, category: Char, endValue: Option[Int]): String = { + f"$bank%02X:$startValue%04X:${endValue.fold("")(_.formatted("%04X"))}%s:$category%s:$label%s" + } + + override def fileExtension(bank: Int): String = ".labels" + + override def filePerBank: Boolean = false + + override def addOutputExtension: Boolean = false + + override def formatBreakpoint(bank: Int, value: Int): Option[String] = + Some(f"$bank%02X:$value%04X::b:") +} + object ViceDebugOutputFormat extends DebugOutputFormat { - override def formatLine(label: String, bank: Int, value: Int): String = { + override def formatLine(label: String, bank: Int, startValue: Int, category: Char, endValue: Option[Int]): String = { val normalized = label.replace('$', '_').replace('.', '_') - s"al ${value.toHexString} .$normalized" + s"al ${startValue.toHexString} .$normalized" } override def fileExtension(bank: Int): String = ".lbl" @@ -61,8 +78,8 @@ object ViceDebugOutputFormat extends DebugOutputFormat { } object NesasmDebugOutputFormat extends DebugOutputFormat { - override def formatLine(label: String, bank: Int, value: Int): String = { - label + " = $" + value.toHexString + override def formatLine(label: String, bank: Int, startValue: Int, category: Char, endValue: Option[Int]): String = { + label + " = $" + startValue.toHexString } override def fileExtension(bank: Int): String = ".fns" @@ -75,8 +92,8 @@ object NesasmDebugOutputFormat extends DebugOutputFormat { } object SymDebugOutputFormat extends DebugOutputFormat { - override def formatLine(label: String, bank: Int, value: Int): String = { - f"$bank%02x:$value%04x $label%s" + override def formatLine(label: String, bank: Int, startValue: Int, category: Char, endValue:Option[Int]): String = { + f"$bank%02x:$startValue%04x $label%s" } override def fileExtension(bank: Int): String = ".sym" @@ -93,8 +110,8 @@ object SymDebugOutputFormat extends DebugOutputFormat { } object FceuxDebugOutputFormat extends DebugOutputFormat { - override def formatLine(label: String, bank: Int, value: Int): String = { - f"$$$value%04x#$label%s#" + override def formatLine(label: String, bank: Int, startValue: Int, category: Char, endValue: Option[Int]): String = { + f"$$$startValue%04x#$label%s#" } override def fileExtension(bank: Int): String = if (bank == 0xff) ".ram.nl" else s".$bank.nl" diff --git a/src/main/scala/millfork/Main.scala b/src/main/scala/millfork/Main.scala index 4b427218..f93d6166 100644 --- a/src/main/scala/millfork/Main.scala +++ b/src/main/scala/millfork/Main.scala @@ -119,14 +119,22 @@ object Main { else if (l.startsWith("__")) 7 else 0 } - val sortedLabels = result.labels.groupBy(_._2).values.map(_.minBy(a => labelUnimportance(a._1) -> a._1)).toSeq.sortBy(_._2) + val sortedLabels: Seq[(String, Int, Int, Char, Option[Int])] = + result.labels.groupBy(_._2).values + .map(_.minBy(a => labelUnimportance(a._1) -> a._1)).toSeq.sortBy(_._2) + .map { case (l, (b, s)) => + result.endLabels.get(l) match { + case Some((c, e)) => (l, b, s, c, Some(e)) + case _ => (l, b, s, 'x', None) + } + } val sortedBreakpoints = result.breakpoints val format = c.outputLabelsFormatOverride.getOrElse(platform.outputLabelsFormat) val basename = if (format.addOutputExtension) output + platform.fileExtension else output if (format.filePerBank) { - val banks = sortedLabels.map(_._2._1).toSet ++ sortedBreakpoints.map(_._2).toSet + val banks: Set[Int] = sortedLabels.map(_._2).toSet ++ sortedBreakpoints.map(_._1).toSet banks.foreach{ bank => - val labels = sortedLabels.filter(_._2._1.==(bank)) + val labels = sortedLabels.filter(_._2.==(bank)) val breakpoints = sortedBreakpoints.filter(_._1.==(bank)) val labelOutput = basename + format.fileExtension(bank) val path = Paths.get(labelOutput) @@ -429,7 +437,7 @@ object Main { p.toLowerCase(Locale.ROOT), errorReporting.fatal("Invalid label file format: " + p)) c.copy(outputLabels = true, outputLabelsFormatOverride = Some(f)) - }.description("Generate also the label file in the given format. Available options: vice, nesasm, sym.") + }.description("Generate also the label file in the given format. Available options: vice, nesasm, sym, raw.") boolean("-fbreakpoints", "-fno-breakpoints").action((c,v) => c.changeFlag(CompilationFlag.EnableBreakpoints, v) diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala index b909ec5f..a5ddc457 100644 --- a/src/main/scala/millfork/env/Environment.scala +++ b/src/main/scala/millfork/env/Environment.scala @@ -118,6 +118,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa allocators: Map[String, VariableAllocator], options: CompilationOptions, onEachVariable: (String, (Int, Int)) => Unit, + onEachVariableEnd: (String, (Char, Int)) => Unit, pass: Int, forZpOnly: Boolean): Unit = { if (forZpOnly && !options.platform.hasZeroPage) { @@ -184,6 +185,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa allocators(bank).allocateBytes(bank0, callGraph, vertex, options, m.sizeInBytes, initialized = false, writeable = true, location = AllocationLocation.Zeropage, alignment = m.alignment) if (log.traceEnabled) log.trace("addr $" + addr.toHexString) onEachVariable(m.name, bank0.index -> addr) + onEachVariableEnd(m.name, (if (m.isInstanceOf[MfArray])'a' else 'v') -> (addr + m.sizeInBytes - 1)) List( ConstantThing(m.name.stripPrefix(prefix) + "`", NumericConstant(addr, 2), p) ) @@ -207,6 +209,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa case Some(addr) => if (log.traceEnabled) log.trace("addr $" + addr.toHexString) onEachVariable(m.name, bank0.index -> addr) + onEachVariableEnd(m.name, (if (m.isInstanceOf[MfArray])'a' else 'v') -> (addr + m.sizeInBytes - 1)) List( ConstantThing(m.name.stripPrefix(prefix) + "`", NumericConstant(addr, 2), p) ) @@ -218,6 +221,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa val addr = allocators(bank).allocateBytes(bank0, callGraph, vertex, options, m.sizeInBytes, initialized = false, writeable = true, location = AllocationLocation.Either, alignment = m.alignment) if (log.traceEnabled) log.trace("addr $" + addr.toHexString) onEachVariable(m.name, bank0.index -> addr) + onEachVariableEnd(m.name, (if (m.isInstanceOf[MfArray])'a' else 'v') -> (addr + m.sizeInBytes - 1)) List( ConstantThing(graveName, NumericConstant(addr, 2), p) ) @@ -225,7 +229,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa } } case f: NormalFunction => - f.environment.allocateVariables(Some(f), mem, callGraph, allocators, options, onEachVariable, pass, forZpOnly) + f.environment.allocateVariables(Some(f), mem, callGraph, allocators, options, onEachVariable, onEachVariableEnd, pass, forZpOnly) Nil case _ => Nil }.toList diff --git a/src/main/scala/millfork/output/AbstractAssembler.scala b/src/main/scala/millfork/output/AbstractAssembler.scala index bfc1fb51..02d54135 100644 --- a/src/main/scala/millfork/output/AbstractAssembler.scala +++ b/src/main/scala/millfork/output/AbstractAssembler.scala @@ -19,7 +19,7 @@ import scala.collection.mutable.ArrayBuffer * @author Karol Stasiak */ -case class AssemblerOutput(code: Map[String, Array[Byte]], asm: Array[String], labels: List[(String, (Int, Int))], breakpoints: List[(Int, Int)]) +case class AssemblerOutput(code: Map[String, Array[Byte]], asm: Array[String], labels: List[(String, (Int, Int))], endLabels: Map[String, (Char, Int)], breakpoints: List[(Int, Int)]) abstract class AbstractAssembler[T <: AbstractCode](private val program: Program, private val rootEnv: Environment, @@ -34,6 +34,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program protected val log: Logger = rootEnv.log val labelMap: mutable.Map[String, (Int, Int)] = mutable.Map() + val endLabelMap: mutable.Map[String, (Char, 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() @@ -251,6 +252,9 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program m.occupied(i + n.toInt) = true } labelMap.put(tim.name, m.index -> n.toInt) + endLabelMap.put(tim.name, + (if (tim.isInstanceOf[InitializedMemoryVariable]) 'V' else 'v') -> + (n.toInt + tim.typ.size - 1)) case _ => } case arr: MfArray => @@ -261,15 +265,18 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program m.occupied(i + n.toInt) = true } labelMap.put(arr.name, m.index -> n.toInt) + endLabelMap.put(arr.name, + (if (arr.isInstanceOf[InitializedArray]) 'A' else 'a') -> + (n.toInt + arr.sizeInBytes - 1)) case _ => } case _ => } } - env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, 1, forZpOnly = true) - env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, 2, forZpOnly = true) - env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, 3, forZpOnly = true) + env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, endLabelMap.put, 1, forZpOnly = true) + env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, endLabelMap.put, 2, forZpOnly = true) + env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, endLabelMap.put, 3, forZpOnly = true) var inlinedFunctions = Map[String, List[T]]() val compiledFunctions = mutable.Map[String, CompiledFunction[T]]() @@ -396,6 +403,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program case NormalCompiledFunction(_, functionCode, _, _, _) => labelMap(f.name) = bank0.index -> index val end = outputFunction(bank, functionCode, index, assembly, options) + endLabelMap(f.name) = 'F' -> (end - 1) for (i <- index until end) { bank0.occupied(index) = true bank0.initialized(index) = true @@ -444,6 +452,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program val bank0 = mem.banks(bank) val index = codeAllocators(bank).allocateBytes(bank0, options, size, initialized = true, writeable = false, location = AllocationLocation.High, alignment = alignment) labelMap(name) = bank0.index -> index + endLabelMap(name) = 'F' -> (index + size - 1) justAfterCode += bank -> outputFunction(bank, functionCode, index, assembly, options) case _ => } @@ -529,6 +538,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program val bank0 = mem.banks(bank) var index = codeAllocators(bank).allocateBytes(bank0, options, thing.sizeInBytes, initialized = true, writeable = true, location = AllocationLocation.High, alignment = alignment) labelMap(name) = bank0.index -> index + endLabelMap(name) = 'A' -> (index + thing.sizeInBytes - 1) if (!readOnlyPass) { rwDataStart = rwDataStart.min(index) rwDataEnd = rwDataEnd.max(index + thing.sizeInBytes) @@ -559,6 +569,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program val bank0 = mem.banks(bank) var index = codeAllocators(bank).allocateBytes(bank0, options, typ.alignedSize, initialized = true, writeable = true, location = AllocationLocation.High, alignment = alignment) labelMap(name) = bank0.index -> index + endLabelMap(name) = 'V' -> (index + typ.size - 1) if (!readOnlyPass) { rwDataStart = rwDataStart.min(index) rwDataEnd = rwDataEnd.max(index + typ.alignedSize) @@ -632,8 +643,8 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program variableAllocators("default").notifyAboutEndOfData(rwDataEnd) } variableAllocators.foreach { case (b, a) => a.notifyAboutEndOfCode(justAfterCode(b)) } - env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, 2, forZpOnly = false) - env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, 3, forZpOnly = false) + env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, endLabelMap.put, 2, forZpOnly = false) + env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, endLabelMap.put, 3, forZpOnly = false) val defaultBank = mem.banks("default").index if (platform.freeZpBytes.nonEmpty) { @@ -695,6 +706,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program val holes = (b.start to b.end).count(i => !b.occupied(i)) val size = b.end - b.start + 1 log.info(f"Segment ${bank}%s: $$${b.start}%04x-$$${b.end}%04x, size: $size%d B ($holes%d B unused)") + // TODO: report holes: } } if (platform.cpuFamily == CpuFamily.M6502) { @@ -706,7 +718,12 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program val allLabelList = labelMap.toList ++ unimportantLabelMap.toList allLabelList.sorted.foreach { case (l, (_, v)) => - assembly += f"$l%-30s = $$$v%04X" + endLabelMap.get(l) match { + case Some((category, end)) => + assembly += f"$l%-30s = $$$v%04X ;-$$$end%04X $category%s" + case _ => + assembly += f"$l%-30s = $$$v%04X" + } } allLabelList.sortBy { case (a, (_, v)) => v -> a }.foreach { case (l, (_, v)) => assembly += f" ; $$$v%04X = $l%s" @@ -729,7 +746,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program } } } - AssemblerOutput(code, assembly.toArray, labelMap.toList, breakpointSet.toList.sorted) + AssemblerOutput(code, assembly.toArray, labelMap.toList, endLabelMap.toMap, breakpointSet.toList.sorted) } private def printArrayToAssemblyOutput(assembly: ArrayBuffer[String], name: String, elementType: Type, items: Seq[Expression]): Unit = { diff --git a/src/test/scala/millfork/test/emu/EmuM6809Run.scala b/src/test/scala/millfork/test/emu/EmuM6809Run.scala index f2d1c70f..b4c81d74 100644 --- a/src/test/scala/millfork/test/emu/EmuM6809Run.scala +++ b/src/test/scala/millfork/test/emu/EmuM6809Run.scala @@ -154,7 +154,7 @@ class EmuM6809Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizat println(";;; compiled: -----------------") output.asm.takeWhile(s => !(s.startsWith(".") && s.contains("= $"))).filterNot(_.contains("; DISCARD_")).foreach(println) println(";;; ---------------------------") - assembler.labelMap.foreach { case (l, (_, addr)) => println(f"$l%-15s $$$addr%04x") } + assembler.labelMap.foreach { case (l, (_, addr)) => println(f"$l%-15s $$$addr%04x${assembler.endLabelMap.get(l)match{case Some((c,e)) => f"-$$$e%04x $c%s"; case _ => ""}}%s") } val optimizedSize = assembler.mem.banks("default").initialized.count(identity).toLong if (unoptimizedSize == optimizedSize) { diff --git a/src/test/scala/millfork/test/emu/EmuRun.scala b/src/test/scala/millfork/test/emu/EmuRun.scala index 4710179e..73ca50a3 100644 --- a/src/test/scala/millfork/test/emu/EmuRun.scala +++ b/src/test/scala/millfork/test/emu/EmuRun.scala @@ -260,7 +260,7 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization], println(";;; compiled: -----------------") output.asm.takeWhile(s => !(s.startsWith(".") && s.contains("= $"))).filterNot(_.contains("; DISCARD_")).foreach(println) println(";;; ---------------------------") - assembler.labelMap.foreach { case (l, (_, addr)) => println(f"$l%-15s $$$addr%04x") } + assembler.labelMap.foreach { case (l, (_, addr)) => println(f"$l%-15s $$$addr%04x${assembler.endLabelMap.get(l)match{case Some((c,e)) => f"-$$$e%04x $c%s"; case _ => ""}}%s") } val optimizedSize = assembler.mem.banks("default").initialized.count(identity).toLong if (unoptimizedSize == optimizedSize) { diff --git a/src/test/scala/millfork/test/emu/EmuZ80Run.scala b/src/test/scala/millfork/test/emu/EmuZ80Run.scala index 9ddd1cd7..d11535f4 100644 --- a/src/test/scala/millfork/test/emu/EmuZ80Run.scala +++ b/src/test/scala/millfork/test/emu/EmuZ80Run.scala @@ -155,7 +155,7 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio println(";;; compiled: -----------------") output.asm.takeWhile(s => !(s.startsWith(".") && s.contains("= $"))).filterNot(_.contains("////; DISCARD_")).foreach(println) println(";;; ---------------------------") - assembler.labelMap.foreach { case (l, (_, addr)) => println(f"$l%-15s $$$addr%04x") } + assembler.labelMap.foreach { case (l, (_, addr)) => println(f"$l%-15s $$$addr%04x${assembler.endLabelMap.get(l)match{case Some((c,e)) => f"-$$$e%04x $c%s"; case _ => ""}}%s") } val optimizedSize = assembler.mem.banks("default").initialized.count(identity).toLong if (unoptimizedSize == optimizedSize) {