1
0
mirror of https://github.com/KarolS/millfork.git synced 2025-01-10 20:29:35 +00:00

More label file formats

This commit is contained in:
Karol Stasiak 2019-06-14 11:39:11 +02:00
parent 5ca6988039
commit 3852b2dbe9
38 changed files with 253 additions and 84 deletions

2
.gitignore vendored
View File

@ -24,6 +24,8 @@ examples/lunix/
*.asm *.asm
*.lbl *.lbl
*.nl *.nl
*.fns
*.sym
*.deb *.deb
*.xex *.xex
*.nes *.nes

View File

@ -10,6 +10,8 @@
* Support for Intel 8085, together with illegal instructions. * Support for Intel 8085, together with illegal instructions.
* More label file formats.
* Added `memory_barrier` macro. * Added `memory_barrier` macro.
* Added `random` module. * Added `random` module.

View File

@ -28,7 +28,20 @@ no extension for BBC micro program file,
* `-s` Generate also the assembly output. It is not compatible with any assembler, but it serves purely informational purpose. The file has the same nam as the output file and the extension is `.asm`. * `-s` Generate also the assembly output. It is not compatible with any assembler, but it serves purely informational purpose. The file has the same nam as the output file and the extension is `.asm`.
* `-g` Generate also the label file. The label file contains labels with their addresses, with duplicates removed. It can be loaded into the monitor of the Vice emulator for debugging purposes. The file has the same name as the output file and the extension is `.lbl`. * `-g` Generate also the label file. The label file contains labels with their addresses, with duplicates removed.
It can be loaded into the monitor of the emulator for debugging purposes.
The file has the same name as the output file.
The extension and the file format are platform-dependent.
* `-G <format>` The same as `-g`, but with the specified format:
* `-G vice` format compatible with the Vice emulator. The extension is `.lbl`.
* `-G nesasm` format used by the NESASM assembler. The extension is `.fns`.
* `-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`.
* `-I <dir>;<dir>` The include directories. * `-I <dir>;<dir>` The include directories.
Those directories are searched for modules and platform definitions. Those directories are searched for modules and platform definitions.

View File

@ -141,6 +141,9 @@ Default: the same as `segment_NAME_end`.
* `segment_NAME_datastart` the first address used for non-zeropage variables, or `after_code` if the variables should be allocated after the code. * `segment_NAME_datastart` the first address used for non-zeropage variables, or `after_code` if the variables should be allocated after the code.
Default: `after_code`. Default: `after_code`.
* `segment_NAME_bank` the bank number the segment belongs to. Default: `0`.
For better debugging on NES, RAM segments should use bank number `$ff`.
#### `[output]` section #### `[output]` section
* `style` how multi-segment programs should be output: * `style` how multi-segment programs should be output:
@ -178,3 +181,13 @@ Default: `after_code`.
* `bbc_inf` should the `.inf` file with file metadata for BBC Micro be created * `bbc_inf` should the `.inf` file with file metadata for BBC Micro be created
* `gb_checksum` should the main output file be patched with Game Boy-compatible checksums * `gb_checksum` should the main output file be patched with Game Boy-compatible checksums
* `labels` format of the label file:
* `vice` (the default) format compatible with the Vice emulator. The extension is `.lbl`.
* `nesasm` format used by the NESASM assembler. The extension is `.fns`.
* `sym` format used by the WLA/DX assembler. The extension is `.sym`.
* `fceux` multi-file format used by the FCEUX emulator. The extension is `.nl`.

View File

@ -31,19 +31,20 @@ x64 hello_world.prg
The following options are obligatory when compiling your sources: The following options are obligatory when compiling your sources:
* `-o FILENAME` specifies the base name for your output file, an appropriate file extension will be appended * `-o FILENAME` specifies the base name for your output file, an appropriate file extension will be appended:
(`prg` for Commodore, `prg` for Commodore;
`xex` for Atari computers, `crt` for Commodore cartridges;
`a2` for Apple, `xex` for Atari computers;
`asm` for assembly output, `a2` for Apple;
`lbl` for label file, `dsk` for PC-88;
`inf` for BBC file metadata, `tap` for ZX Spectrum;
`dsk` for PC-88, `rom` for MSX cartridges;
`tap` for ZX Spectrum, `com` for CP/M;
`rom` for MSX cartridges, `nes` for Famicom;
`com` for CP/M, `bin` for Atari 2600;
`nes` for Famicom, `inf` for BBC file metadata;
`bin` for Atari 2600) `asm` for assembly output;
`lbl`, `nl`, `fns`, or `sym` for label file
* `-t PLATFORM` specifies the target platform. * `-t PLATFORM` specifies the target platform.
Each platform is defined in an `.ini` file in the include directory. Each platform is defined in an `.ini` file in the include directory.
@ -62,7 +63,7 @@ You may be also interested in the following:
* `-fsource-in-asm` show original Millfork source in the assembly output * `-fsource-in-asm` show original Millfork source in the assembly output
* `-g` additionally generate a label file, in format compatible with VICE emulator * `-g` additionally generate a label file
* `-r PROGRAM` automatically launch given program after successful compilation * `-r PROGRAM` automatically launch given program after successful compilation

View File

@ -25,5 +25,6 @@ HAS_BITMAP_MODE=1
style=single style=single
format=startaddr,allocated format=startaddr,allocated
extension=prg extension=prg
labels=vice

View File

@ -24,5 +24,6 @@ HAS_BITMAP_MODE=1
style=single style=single
format=startaddr,allocated format=startaddr,allocated
extension=prg extension=prg
labels=vice

View File

@ -43,5 +43,6 @@ style=single
format=startaddr,allocated format=startaddr,allocated
; default output file extension ; default output file extension
extension=prg extension=prg
labels=vice

View File

@ -37,5 +37,6 @@ format =$43,$36,$34,$20,$43,$41,$52,$54,$52,$49,$44,$47,$45,$20,$20,$20, \
$43,$48,$49,$50, 0,0,$40,$10, 0,0, 0,0, $80,$00, $40,$00, \ $43,$48,$49,$50, 0,0,$40,$10, 0,0, 0,0, $80,$00, $40,$00, \
prgrom:$8000:$bfff prgrom:$8000:$bfff
extension=crt extension=crt
labels=vice

View File

@ -37,5 +37,6 @@ format =$43,$36,$34,$20,$43,$41,$52,$54,$52,$49,$44,$47,$45,$20,$20,$20, \
$43,$48,$49,$50, 0,0,$20,$10, 0,0, 0,0, $80,$00, $20,$00, \ $43,$48,$49,$50, 0,0,$20,$10, 0,0, 0,0, $80,$00, $20,$00, \
prgrom:$8000:$9fff prgrom:$8000:$9fff
extension=crt extension=crt
labels=vice

View File

@ -27,5 +27,6 @@ HAS_BITMAP_MODE=1
style=single style=single
format=startaddr,allocated format=startaddr,allocated
extension=prg extension=prg
labels=vice

View File

@ -29,5 +29,6 @@ HAS_BITMAP_MODE=1
style=single style=single
format=startaddr,allocated format=startaddr,allocated
extension=prg extension=prg
labels=vice

View File

@ -30,5 +30,6 @@ style=single
format=rom:0:$7fff format=rom:0:$7fff
gb_checksum=true gb_checksum=true
extension=gb extension=gb
labels=sym

View File

@ -30,5 +30,6 @@ HAS_BITMAP_MODE=1
style=lunix style=lunix
format=$ff,$fe,0,21,pagecount,startpage,allocated format=$ff,$fe,0,21,pagecount,startpage,allocated
extension=prg extension=prg
labels=vice

View File

@ -21,33 +21,43 @@ default_code_segment=prgrom7
segment_default_start=$200 segment_default_start=$200
segment_default_end=$7ff segment_default_end=$7ff
segment_default_bank=$ff
segment_ram_start=$6000 segment_ram_start=$6000
segment_ram_end=$7fff segment_ram_end=$7fff
segment_ram_bank=$ff
segment_prgrom7_start=$c000 segment_prgrom7_start=$c000
segment_prgrom7_end=$ffff segment_prgrom7_end=$ffff
segment_prgrom7_bank=7
segment_prgrom0_start=$8000 segment_prgrom0_start=$8000
segment_prgrom0_end=$bfff segment_prgrom0_end=$bfff
segment_prgrom0_bank=0
segment_prgrom1_start=$8000 segment_prgrom1_start=$8000
segment_prgrom1_end=$bfff segment_prgrom1_end=$bfff
segment_prgrom1_bank=1
segment_prgrom2_start=$8000 segment_prgrom2_start=$8000
segment_prgrom2_end=$bfff segment_prgrom2_end=$bfff
segment_prgrom2_bank=2
segment_prgrom3_start=$8000 segment_prgrom3_start=$8000
segment_prgrom3_end=$bfff segment_prgrom3_end=$bfff
segment_prgrom3_bank=3
segment_prgrom4_start=$8000 segment_prgrom4_start=$8000
segment_prgrom4_end=$bfff segment_prgrom4_end=$bfff
segment_prgrom4_bank=4
segment_prgrom5_start=$8000 segment_prgrom5_start=$8000
segment_prgrom5_end=$bfff segment_prgrom5_end=$bfff
segment_prgrom5_bank=5
segment_prgrom6_start=$8000 segment_prgrom6_start=$8000
segment_prgrom6_end=$bfff segment_prgrom6_end=$bfff
segment_prgrom6_bank=6
segment_chrrom0_start=$0000 segment_chrrom0_start=$0000
segment_chrrom0_end=$ffff segment_chrrom0_end=$ffff
@ -67,5 +77,6 @@ style=single
format=$4E,$45,$53,$1A, 8,16,$A0,8, 0,0,$07,0, 2,0,0,0, prgrom0:$8000:$bfff,prgrom1:$8000:$bfff,prgrom2:$8000:$bfff,prgrom3:$8000:$bfff,prgrom4:$8000:$bfff,prgrom5:$8000:$bfff,prgrom6:$8000:$bfff,prgrom7:$c000:$ffff,chrrom0:$0000:$ffff,chrrom1:$0000:$ffff format=$4E,$45,$53,$1A, 8,16,$A0,8, 0,0,$07,0, 2,0,0,0, prgrom0:$8000:$bfff,prgrom1:$8000:$bfff,prgrom2:$8000:$bfff,prgrom3:$8000:$bfff,prgrom4:$8000:$bfff,prgrom5:$8000:$bfff,prgrom6:$8000:$bfff,prgrom7:$c000:$ffff,chrrom0:$0000:$ffff,chrrom1:$0000:$ffff
extension=nes extension=nes
labels=nesasm

View File

@ -17,6 +17,7 @@ default_code_segment=prgrom
segment_default_start=$200 segment_default_start=$200
segment_default_end=$7ff segment_default_end=$7ff
segment_default_bank=$ff
segment_prgrom_start=$8000 segment_prgrom_start=$8000
segment_prgrom_end=$ffff segment_prgrom_end=$ffff
@ -35,5 +36,6 @@ HAS_BITMAP_MODE=0
style=single style=single
format=$4E,$45,$53,$1A, 2,1,0,0, 0,0,0,0, 0,0,0,0, prgrom:$8000:$ffff, chrrom:$0000:$1fff format=$4E,$45,$53,$1A, 2,1,0,0, 0,0,0,0, 0,0,0,0, prgrom:$8000:$ffff, chrrom:$0000:$1fff
extension=nes extension=nes
labels=nesasm

View File

@ -23,5 +23,6 @@ HAS_BITMAP_MODE=0
style=single style=single
format=startaddr,allocated format=startaddr,allocated
extension=prg extension=prg
labels=vice

View File

@ -24,5 +24,6 @@ HAS_BITMAP_MODE=1
style=per_bank style=per_bank
format=startaddr,allocated format=startaddr,allocated
extension=prg extension=prg
labels=vice

View File

@ -23,5 +23,6 @@ HAS_BITMAP_MODE=1
style=single style=single
format=startaddr,allocated format=startaddr,allocated
extension=prg extension=prg
labels=vice

View File

@ -23,5 +23,6 @@ HAS_BITMAP_MODE=1
style=single style=single
format=startaddr,allocated format=startaddr,allocated
extension=prg extension=prg
labels=vice

View File

@ -23,5 +23,6 @@ HAS_BITMAP_MODE=1
style=single style=single
format=startaddr,allocated format=startaddr,allocated
extension=prg extension=prg
labels=vice

View File

@ -30,5 +30,6 @@ HAS_BITMAP_MODE=1
style=single style=single
format=$00,$a0,prgrom:$a000:$bfff format=$00,$a0,prgrom:$a000:$bfff
extension=crt extension=crt
labels=vice

View File

@ -15,7 +15,9 @@ case class Context(errorReporting: Logger,
platform: Option[String] = None, platform: Option[String] = None,
outputAssembly: Boolean = false, outputAssembly: Boolean = false,
outputLabels: Boolean = false, outputLabels: Boolean = false,
outputLabelsFormatOverride: Option[DebugOutputFormat] = None,
includePath: List[String] = Nil, includePath: List[String] = Nil,
extraIncludePath: Seq[String] = IndexedSeq(),
flags: Map[CompilationFlag.Value, Boolean] = Map(), flags: Map[CompilationFlag.Value, Boolean] = Map(),
features: Map[String, Long] = Map(), features: Map[String, Long] = Map(),
verbosity: Option[Int] = None) { verbosity: Option[Int] = None) {

View File

@ -0,0 +1,77 @@
package millfork
/**
* @author Karol Stasiak
*/
object DebugOutputFormat {
val map: Map[String, DebugOutputFormat] = Map(
"vice" -> ViceDebugOutputFormat,
"nesasm" -> NesasmDebugOutputFormat,
"fns" -> NesasmDebugOutputFormat,
"fceux" -> FceuxDebugOutputFormat,
"nl" -> FceuxDebugOutputFormat,
"sym" -> SymDebugOutputFormat)
}
sealed trait DebugOutputFormat extends Function[(String, (Int, Int)), String] {
def apply(labelAndValue: (String, (Int, Int))): String = formatLine(labelAndValue._1, labelAndValue._2._1, labelAndValue._2._2)
def formatLine(label: String, bank: Int, value: Int): String
def fileExtension(bank: Int): String
def filePerBank: Boolean
def addOutputExtension: Boolean
}
object ViceDebugOutputFormat extends DebugOutputFormat {
override def formatLine(label: String, bank: Int, value: Int): String = {
val normalized = label.replace('$', '_').replace('.', '_')
s"al ${value.toHexString} .$normalized"
}
override def fileExtension(bank: Int): String = ".lbl"
override def filePerBank: Boolean = false
override def addOutputExtension: Boolean = false
}
object NesasmDebugOutputFormat extends DebugOutputFormat {
override def formatLine(label: String, bank: Int, value: Int): String = {
label + " = $" + value.toHexString
}
override def fileExtension(bank: Int): String = ".fns"
override def filePerBank: Boolean = false
override def addOutputExtension: Boolean = false
}
object SymDebugOutputFormat extends DebugOutputFormat {
override def formatLine(label: String, bank: Int, value: Int): String = {
f"$bank%02x:$value%04x $label%s"
}
override def fileExtension(bank: Int): String = ".sym"
override def filePerBank: Boolean = false
override def addOutputExtension: Boolean = false
}
object FceuxDebugOutputFormat extends DebugOutputFormat {
override def formatLine(label: String, bank: Int, value: Int): String = {
f"$$$value%04x#$label%s#"
}
override def fileExtension(bank: Int): String = if (bank == 0xff) ".ram.nl" else s".$bank.nl"
override def filePerBank: Boolean = true
override def addOutputExtension: Boolean = true
}

View File

@ -67,7 +67,6 @@ object Main {
val output = c.outputFileName.getOrElse("a") val output = c.outputFileName.getOrElse("a")
val assOutput = output + ".asm" val assOutput = output + ".asm"
val labelOutput = output + ".lbl"
// val prgOutputs = (platform.outputStyle match { // val prgOutputs = (platform.outputStyle match {
// case OutputStyle.Single => List("default") // case OutputStyle.Single => List("default")
// case OutputStyle.PerBank => platform.bankNumbers.keys.toList // case OutputStyle.PerBank => platform.bankNumbers.keys.toList
@ -91,17 +90,27 @@ object Main {
Files.write(path, result.asm.mkString("\n").getBytes(StandardCharsets.UTF_8)) Files.write(path, result.asm.mkString("\n").getBytes(StandardCharsets.UTF_8))
} }
if (c.outputLabels) { if (c.outputLabels) {
val path = Paths.get(labelOutput) def labelUnimportance(l: String): Int = {
errorReporting.debug("Writing labels to " + path.toAbsolutePath) if (l.startsWith(".")) 8
Files.write(path, result.labels.sortWith { (a, b) => else if (l.startsWith("__")) 7
val aLocal = a._1.head == '.' else 0
val bLocal = b._1.head == '.' }
if (aLocal == bLocal) a._1 < b._1 val sortedLabels = result.labels.groupBy(_._2).values.map(_.minBy(a => labelUnimportance(a._1) -> a._1)).toSeq.sortBy(_._2)
else b._1 < a._1 val format = c.outputLabelsFormatOverride.getOrElse(platform.outputLabelsFormat)
}.groupBy(_._2).values.map(_.head).toSeq.sortBy(_._2).map { case (l, a) => val basename = if (format.addOutputExtension) output + platform.fileExtension else output
val normalized = l.replace('$', '_').replace('.', '_') if (format.filePerBank) {
s"al ${a.toHexString} .$normalized" sortedLabels.groupBy(_._2._1).foreach{ case (bank, labels) =>
}.mkString("\n").getBytes(StandardCharsets.UTF_8)) val labelOutput = basename + format.fileExtension(bank)
val path = Paths.get(labelOutput)
errorReporting.debug("Writing labels to " + path.toAbsolutePath)
Files.write(path, labels.map(format).mkString("\n").getBytes(StandardCharsets.UTF_8))
}
} else {
val labelOutput = basename + format.fileExtension(0)
val path = Paths.get(labelOutput)
errorReporting.debug("Writing labels to " + path.toAbsolutePath)
Files.write(path, sortedLabels.map(format).mkString("\n").getBytes(StandardCharsets.UTF_8))
}
} }
val defaultPrgOutput = if (output.endsWith(platform.fileExtension)) output else output + platform.fileExtension val defaultPrgOutput = if (output.endsWith(platform.fileExtension)) output else output + platform.fileExtension
result.code.foreach{ result.code.foreach{
@ -336,7 +345,14 @@ object Main {
flag("-g").action { c => flag("-g").action { c =>
c.copy(outputLabels = true) c.copy(outputLabels = true)
}.description("Generate also the label file.") }.description("Generate also the label file in the default format.")
parameter("-G").placeholder("<format>").action { (p, c) =>
val f = DebugOutputFormat.map.getOrElse(
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.")
parameter("-t", "--target").placeholder("<platform>").action { (p, c) => parameter("-t", "--target").placeholder("<platform>").action { (p, c) =>
assertNone(c.platform, "Platform already defined") assertNone(c.platform, "Platform already defined")

View File

@ -3,6 +3,7 @@ package millfork
import java.io.{File, StringReader} import java.io.{File, StringReader}
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Paths} import java.nio.file.{Files, Paths}
import java.util.Locale
import millfork.error.Logger import millfork.error.Logger
import millfork.output._ import millfork.output._
@ -34,6 +35,7 @@ class Platform(
val generateGameBoyChecksums: Boolean, val generateGameBoyChecksums: Boolean,
val bankNumbers: Map[String, Int], val bankNumbers: Map[String, Int],
val defaultCodeBank: String, val defaultCodeBank: String,
val outputLabelsFormat: DebugOutputFormat,
val outputStyle: OutputStyle.Value val outputStyle: OutputStyle.Value
) { ) {
def hasZeroPage: Boolean = cpuFamily == CpuFamily.M6502 def hasZeroPage: Boolean = cpuFamily == CpuFamily.M6502
@ -201,6 +203,10 @@ object Platform {
case "lunix" => OutputStyle.LUnix case "lunix" => OutputStyle.LUnix
case x => log.fatal(s"Invalid output style: `$x`") case x => log.fatal(s"Invalid output style: `$x`")
} }
val debugOutputFormatName = os.get(classOf[String], "labels", "vice")
val debugOutputFormat = DebugOutputFormat.map.getOrElse(
debugOutputFormatName.toLowerCase(Locale.ROOT),
log.fatal(s"Invalid label file format: `$debugOutputFormatName`"))
val builtInFeatures = builtInCpuFeatures(cpu) val builtInFeatures = builtInCpuFeatures(cpu)
@ -232,6 +238,7 @@ object Platform {
generateGameBoyChecksums, generateGameBoyChecksums,
bankNumbers, bankNumbers,
defaultCodeBank, defaultCodeBank,
debugOutputFormat,
outputStyle) outputStyle)
} }

View File

@ -10,7 +10,7 @@ import millfork.node.NiceFunctionProperty
* @author Karol Stasiak * @author Karol Stasiak
*/ */
case class OptimizationContext(options: CompilationOptions, case class OptimizationContext(options: CompilationOptions,
labelMap: Map[String, Int], labelMap: Map[String, (Int, Int)],
zreg: Option[ThingInMemory], zreg: Option[ThingInMemory],
niceFunctionProperties: Set[(NiceFunctionProperty, String)]) { niceFunctionProperties: Set[(NiceFunctionProperty, String)]) {
@inline @inline

View File

@ -102,10 +102,10 @@ class RuleBasedAssemblyOptimization(val name: String, val needsFlowInfo: FlowInf
} }
class AssemblyMatchingContext(val compilationOptions: CompilationOptions, class AssemblyMatchingContext(val compilationOptions: CompilationOptions,
val labelMap: Map[String, Int], val labelMap: Map[String, (Int, Int)],
val zeropageRegister: Option[ThingInMemory], val zeropageRegister: Option[ThingInMemory],
val niceFunctionProperties: Set[(NiceFunctionProperty, String)], val niceFunctionProperties: Set[(NiceFunctionProperty, String)],
val labeUseCount: String => Int) { val labelUseCount: String => Int) {
@inline @inline
def log: Logger = compilationOptions.log def log: Logger = compilationOptions.log
@inline @inline
@ -222,7 +222,7 @@ class AssemblyMatchingContext(val compilationOptions: CompilationOptions,
} }
// if a jump leads inside the block, then it's internal // if a jump leads inside the block, then it's internal
// if a jump leads outside the block, then it's external // if a jump leads outside the block, then it's external
jumps == labels && labels.forall(l => labeUseCount(l) <= 1) jumps == labels && labels.forall(l => labelUseCount(l) <= 1)
} }
def zreg(i: Int): Constant = { def zreg(i: Int): Constant = {
@ -1530,10 +1530,10 @@ case object IsZeroPage extends AssemblyLinePattern {
ISC | DCP | LAX | SAX | RLA | RRA | SLO | SRE, AddrMode.Absolute, p, Elidability.Elidable, _) => ISC | DCP | LAX | SAX | RLA | RRA | SLO | SRE, AddrMode.Absolute, p, Elidability.Elidable, _) =>
p match { p match {
case NumericConstant(n, _) => n <= 255 case NumericConstant(n, _) => n <= 255
case MemoryAddressConstant(th) => ctx.labelMap.getOrElse(th.name, 0x800) < 0x100 case MemoryAddressConstant(th) => ctx.labelMap.getOrElse(th.name, 0 -> 0x800)._2 < 0x100
case CompoundConstant(MathOperator.Plus, case CompoundConstant(MathOperator.Plus,
MemoryAddressConstant(th), MemoryAddressConstant(th),
NumericConstant(n, _)) => ctx.labelMap.getOrElse(th.name, 0x800) + n < 0x100 NumericConstant(n, _)) => ctx.labelMap.getOrElse(th.name, 0 -> 0x800)._2 + n < 0x100
case _ => false case _ => false
} }
case _ => false case _ => false

View File

@ -110,7 +110,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
callGraph: CallGraph, callGraph: CallGraph,
allocators: Map[String, VariableAllocator], allocators: Map[String, VariableAllocator],
options: CompilationOptions, options: CompilationOptions,
onEachVariable: (String, Int) => Unit, onEachVariable: (String, (Int, Int)) => Unit,
pass: Int, pass: Int,
forZpOnly: Boolean): Unit = { forZpOnly: Boolean): Unit = {
if (forZpOnly && !options.platform.hasZeroPage) { if (forZpOnly && !options.platform.hasZeroPage) {
@ -155,14 +155,15 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
} }
} else GlobalVertex } else GlobalVertex
val bank = m.bank(options) val bank = m.bank(options)
val bank0 = mem.banks(bank)
m.alloc match { m.alloc match {
case VariableAllocationMethod.None => case VariableAllocationMethod.None =>
Nil Nil
case VariableAllocationMethod.Zeropage => case VariableAllocationMethod.Zeropage =>
if (forZpOnly || !options.platform.hasZeroPage) { if (forZpOnly || !options.platform.hasZeroPage) {
val addr = val addr =
allocators(bank).allocateBytes(mem.banks(bank), callGraph, vertex, options, m.sizeInBytes, initialized = false, writeable = true, location = AllocationLocation.Zeropage, alignment = m.alignment) allocators(bank).allocateBytes(bank0, callGraph, vertex, options, m.sizeInBytes, initialized = false, writeable = true, location = AllocationLocation.Zeropage, alignment = m.alignment)
onEachVariable(m.name, addr) onEachVariable(m.name, bank0.index -> addr)
List( List(
ConstantThing(m.name.stripPrefix(prefix) + "`", NumericConstant(addr, 2), p) ConstantThing(m.name.stripPrefix(prefix) + "`", NumericConstant(addr, 2), p)
) )
@ -175,10 +176,10 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
val graveName = m.name.stripPrefix(prefix) + "`" val graveName = m.name.stripPrefix(prefix) + "`"
if (forZpOnly) { if (forZpOnly) {
if (bank == "default") { if (bank == "default") {
allocators(bank).tryAllocateZeropageBytes(mem.banks(bank), callGraph, vertex, options, m.sizeInBytes, alignment = m.alignment) match { allocators(bank).tryAllocateZeropageBytes(bank0, callGraph, vertex, options, m.sizeInBytes, alignment = m.alignment) match {
case None => Nil case None => Nil
case Some(addr) => case Some(addr) =>
onEachVariable(m.name, addr) onEachVariable(m.name, bank0.index -> addr)
List( List(
ConstantThing(m.name.stripPrefix(prefix) + "`", NumericConstant(addr, 2), p) ConstantThing(m.name.stripPrefix(prefix) + "`", NumericConstant(addr, 2), p)
) )
@ -187,8 +188,8 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
} else if (things.contains(graveName)) { } else if (things.contains(graveName)) {
Nil Nil
} else { } else {
val addr = allocators(bank).allocateBytes(mem.banks(bank), callGraph, vertex, options, m.sizeInBytes, initialized = false, writeable = true, location = AllocationLocation.Either, alignment = m.alignment) val addr = allocators(bank).allocateBytes(bank0, callGraph, vertex, options, m.sizeInBytes, initialized = false, writeable = true, location = AllocationLocation.Either, alignment = m.alignment)
onEachVariable(m.name, addr) onEachVariable(m.name, bank0.index -> addr)
List( List(
ConstantThing(graveName, NumericConstant(addr, 2), p) ConstantThing(graveName, NumericConstant(addr, 2), p)
) )

View File

@ -16,7 +16,7 @@ import millfork.node.NiceFunctionProperty.IsLeaf
* @author Karol Stasiak * @author Karol Stasiak
*/ */
case class AssemblerOutput(code: Map[String, Array[Byte]], asm: Array[String], labels: List[(String, Int)]) case class AssemblerOutput(code: Map[String, Array[Byte]], asm: Array[String], labels: List[(String, (Int, Int))])
abstract class AbstractAssembler[T <: AbstractCode](private val program: Program, abstract class AbstractAssembler[T <: AbstractCode](private val program: Program,
private val rootEnv: Environment, private val rootEnv: Environment,
@ -30,8 +30,8 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
var initializedVariablesSize: Int = 0 var initializedVariablesSize: Int = 0
protected val log: Logger = rootEnv.log protected val log: Logger = rootEnv.log
val mem = new CompiledMemory(platform.bankNumbers.keys.toList) val mem = new CompiledMemory(platform.bankNumbers.toList)
val labelMap: mutable.Map[String, Int] = mutable.Map() val labelMap: mutable.Map[String, (Int, Int)] = mutable.Map()
private val bytesToWriteLater = mutable.ListBuffer[(String, Int, Constant)]() private val bytesToWriteLater = mutable.ListBuffer[(String, Int, Constant)]()
private val wordsToWriteLater = mutable.ListBuffer[(String, Int, Constant)]() private val wordsToWriteLater = mutable.ListBuffer[(String, Int, Constant)]()
@ -97,9 +97,9 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
} }
case MemoryAddressConstant(th) => case MemoryAddressConstant(th) =>
try { try {
if (labelMap.contains(th.name)) return labelMap(th.name) if (labelMap.contains(th.name)) return labelMap(th.name)._2
if (labelMap.contains(th.name + "`")) return labelMap(th.name) if (labelMap.contains(th.name + "`")) return labelMap(th.name)._2
if (labelMap.contains(th.name + ".addr")) return labelMap.getOrElse[Int](th.name, labelMap(th.name + ".array")) if (labelMap.contains(th.name + ".addr")) return labelMap.getOrElse[(Int, Int)](th.name, labelMap(th.name + ".array"))._2
val x1 = env.maybeGet[ConstantThing](th.name).map(_.value) val x1 = env.maybeGet[ConstantThing](th.name).map(_.value)
val x2 = env.maybeGet[ConstantThing](th.name + "`").map(_.value) val x2 = env.maybeGet[ConstantThing](th.name + "`").map(_.value)
val x3 = env.maybeGet[NormalFunction](th.name).flatMap(_.address) val x3 = env.maybeGet[NormalFunction](th.name).flatMap(_.address)
@ -121,7 +121,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
log.fatal("Stack overflow " + c) log.fatal("Stack overflow " + c)
} }
case UnexpandedConstant(name, _) => case UnexpandedConstant(name, _) =>
if (labelMap.contains(name)) labelMap(name) if (labelMap.contains(name)) labelMap(name)._2
else ??? else ???
case SubbyteConstant(cc, i) => deepConstResolve(cc).>>>(i * 8).&(0xff) case SubbyteConstant(cc, i) => deepConstResolve(cc).>>>(i * 8).&(0xff)
case CompoundConstant(operator, lc, rc) => case CompoundConstant(operator, lc, rc) =>
@ -286,7 +286,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
val index = f.address.get.asInstanceOf[NumericConstant].value.toInt val index = f.address.get.asInstanceOf[NumericConstant].value.toInt
compiledFunctions(f.name) match { compiledFunctions(f.name) match {
case NormalCompiledFunction(_, functionCode, _, _) => case NormalCompiledFunction(_, functionCode, _, _) =>
labelMap(f.name) = index labelMap(f.name) = bank0.index -> index
val end = outputFunction(bank, functionCode, index, assembly, options) val end = outputFunction(bank, functionCode, index, assembly, options)
for (i <- index until end) { for (i <- index until end) {
bank0.occupied(index) = true bank0.occupied(index) = true
@ -308,14 +308,16 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
// already done before // already done before
case (name, NormalCompiledFunction(bank, functionCode, false, alignment)) => case (name, NormalCompiledFunction(bank, functionCode, false, alignment)) =>
val size = functionCode.map(_.sizeInBytes).sum val size = functionCode.map(_.sizeInBytes).sum
val index = codeAllocators(bank).allocateBytes(mem.banks(bank), options, size, initialized = true, writeable = false, location = AllocationLocation.High, alignment = alignment) val bank0 = mem.banks(bank)
labelMap(name) = index val index = codeAllocators(bank).allocateBytes(bank0, options, size, initialized = true, writeable = false, location = AllocationLocation.High, alignment = alignment)
labelMap(name) = bank0.index -> index
justAfterCode += bank -> outputFunction(bank, functionCode, index, assembly, options) justAfterCode += bank -> outputFunction(bank, functionCode, index, assembly, options)
case _ => case _ =>
} }
sortedCompilerFunctions.foreach { sortedCompilerFunctions.foreach {
case (name, RedirectedFunction(_, target, offset)) => case (name, RedirectedFunction(_, target, offset)) =>
labelMap(name) = labelMap(target) + offset val tuple = labelMap(target)
labelMap(name) = tuple._1 -> (tuple._2 + offset)
case _ => case _ =>
} }
@ -332,7 +334,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
if (bank != "default") ??? if (bank != "default") ???
val bank0 = mem.banks(bank) val bank0 = mem.banks(bank)
var index = codeAllocators(bank).allocateBytes(bank0, options, typ.size + 1, initialized = true, writeable = false, location = AllocationLocation.High, alignment = m.alignment) var index = codeAllocators(bank).allocateBytes(bank0, options, typ.size + 1, initialized = true, writeable = false, location = AllocationLocation.High, alignment = m.alignment)
labelMap(name) = index + 1 labelMap(name) = bank0.index -> (index + 1)
val altName = m.name.stripPrefix(env.prefix) + "`" val altName = m.name.stripPrefix(env.prefix) + "`"
val thing = if (name.endsWith(".addr")) env.get[ThingInMemory](name.stripSuffix(".addr")) else env.get[ThingInMemory](name + ".array") val thing = if (name.endsWith(".addr")) env.get[ThingInMemory](name.stripSuffix(".addr")) else env.get[ThingInMemory](name + ".array")
env.things += altName -> ConstantThing(altName, NumericConstant(index, 2), env.get[Type]("pointer")) env.things += altName -> ConstantThing(altName, NumericConstant(index, 2), env.get[Type]("pointer"))
@ -363,7 +365,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
val bank = thing.bank(options) val bank = thing.bank(options)
val bank0 = mem.banks(bank) val bank0 = mem.banks(bank)
var index = codeAllocators(bank).allocateBytes(bank0, options, items.size, initialized = true, writeable = true, location = AllocationLocation.High, alignment = alignment) var index = codeAllocators(bank).allocateBytes(bank0, options, items.size, initialized = true, writeable = true, location = AllocationLocation.High, alignment = alignment)
labelMap(name) = index labelMap(name) = bank0.index -> index
assembly.append("* = $" + index.toHexString) assembly.append("* = $" + index.toHexString)
assembly.append(name) assembly.append(name)
for (item <- items) { for (item <- items) {
@ -385,7 +387,7 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
val bank = m.bank(options) val bank = m.bank(options)
val bank0 = mem.banks(bank) val bank0 = mem.banks(bank)
var index = codeAllocators(bank).allocateBytes(bank0, options, typ.size, initialized = true, writeable = true, location = AllocationLocation.High, alignment = alignment) var index = codeAllocators(bank).allocateBytes(bank0, options, typ.size, initialized = true, writeable = true, location = AllocationLocation.High, alignment = alignment)
labelMap(name) = index labelMap(name) = bank0.index -> index
val altName = m.name.stripPrefix(env.prefix) + "`" val altName = m.name.stripPrefix(env.prefix) + "`"
env.things += altName -> ConstantThing(altName, NumericConstant(index, 2), env.get[Type]("pointer")) env.things += altName -> ConstantThing(altName, NumericConstant(index, 2), env.get[Type]("pointer"))
assembly.append("* = $" + index.toHexString) assembly.append("* = $" + index.toHexString)
@ -414,20 +416,21 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put, 2, forZpOnly = false) 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, 3, forZpOnly = false)
val defaultBank = mem.banks("default").index
if (platform.freeZpPointers.nonEmpty) { if (platform.freeZpPointers.nonEmpty) {
val zpUsageOffset = platform.freeZpPointers.min val zpUsageOffset = platform.freeZpPointers.min
val zeropageOccupation = zpOccupied.slice(zpUsageOffset, platform.freeZpPointers.max + 2) val zeropageOccupation = zpOccupied.slice(zpUsageOffset, platform.freeZpPointers.max + 2)
labelMap += "__zeropage_usage" -> (zeropageOccupation.lastIndexOf(true) - zeropageOccupation.indexOf(true) + 1) labelMap += "__zeropage_usage" -> (defaultBank, zeropageOccupation.lastIndexOf(true) - zeropageOccupation.indexOf(true) + 1)
labelMap += "__zeropage_first" -> (zpUsageOffset + (zeropageOccupation.indexOf(true) max 0)) labelMap += "__zeropage_first" -> (defaultBank, zpUsageOffset + (zeropageOccupation.indexOf(true) max 0))
labelMap += "__zeropage_last" -> (zpUsageOffset + (zeropageOccupation.lastIndexOf(true) max 0)) labelMap += "__zeropage_last" -> (defaultBank, zpUsageOffset + (zeropageOccupation.lastIndexOf(true) max 0))
labelMap += "__zeropage_end" -> (zpUsageOffset + zeropageOccupation.lastIndexOf(true) + 1) labelMap += "__zeropage_end" -> (defaultBank, zpUsageOffset + zeropageOccupation.lastIndexOf(true) + 1)
} else { } else {
labelMap += "__zeropage_usage" -> 0 labelMap += "__zeropage_usage" -> (defaultBank -> 0)
labelMap += "__zeropage_first" -> 3 labelMap += "__zeropage_first" -> (defaultBank -> 3)
labelMap += "__zeropage_last" -> 2 labelMap += "__zeropage_last" -> (defaultBank -> 2)
labelMap += "__zeropage_end" -> 3 labelMap += "__zeropage_end" -> (defaultBank -> 3)
} }
labelMap += "__heap_start" -> variableAllocators("default").heapStart labelMap += "__heap_start" -> (defaultBank -> variableAllocators("default").heapStart)
env = rootEnv.allThings env = rootEnv.allThings
@ -449,10 +452,10 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
mem.banks(bank).end = end mem.banks(bank).end = end
} }
labelMap.toList.sorted.foreach { case (l, v) => labelMap.toList.sorted.foreach { case (l, (_, v)) =>
assembly += f"$l%-30s = $$$v%04X" assembly += f"$l%-30s = $$$v%04X"
} }
labelMap.toList.sortBy { case (a, b) => b -> a }.foreach { case (l, v) => labelMap.toList.sortBy { case (a, (_, v)) => v -> a }.foreach { case (l, (_, v)) =>
assembly += f" ; $$$v%04X = $l%s" assembly += f" ; $$$v%04X = $l%s"
} }
@ -464,13 +467,13 @@ abstract class AbstractAssembler[T <: AbstractCode](private val program: Program
AssemblerOutput(code, assembly.toArray, labelMap.toList) AssemblerOutput(code, assembly.toArray, labelMap.toList)
} }
def injectLabels(labelMap: Map[String, Int], code: List[T]): List[T] def injectLabels(labelMap: Map[String, (Int, Int)], code: List[T]): List[T]
private def compileFunction(f: NormalFunction, private def compileFunction(f: NormalFunction,
optimizations: Seq[AssemblyOptimization[T]], optimizations: Seq[AssemblyOptimization[T]],
options: CompilationOptions, options: CompilationOptions,
inlinedFunctions: Map[String, List[T]], inlinedFunctions: Map[String, List[T]],
labelMap: Map[String, Int], labelMap: Map[String, (Int, Int)],
niceFunctionProperties: Set[(NiceFunctionProperty, String)]): List[T] = { niceFunctionProperties: Set[(NiceFunctionProperty, String)]): List[T] = {
log.debug("Compiling: " + f.name, f.position) log.debug("Compiling: " + f.name, f.position)
val unoptimized: List[T] = val unoptimized: List[T] =

View File

@ -5,12 +5,12 @@ import scala.collection.mutable
/** /**
* @author Karol Stasiak * @author Karol Stasiak
*/ */
class CompiledMemory(bankNames: List[String]) { class CompiledMemory(bankNames: List[(String, Int)]) {
var programName = "MILLFORK" var programName = "MILLFORK"
val banks: mutable.Map[String, MemoryBank] = mutable.Map(bankNames.map(_ -> new MemoryBank): _*) val banks: mutable.Map[String, MemoryBank] = mutable.Map(bankNames.map(p => p._1 -> new MemoryBank(p._2)): _*)
} }
class MemoryBank { class MemoryBank(val index: Int) {
def readByte(addr: Int): Int = output(addr) & 0xff def readByte(addr: Int): Int = output(addr) & 0xff
def readWord(addr: Int): Int = readByte(addr) + (readByte(addr + 1) << 8) def readWord(addr: Int): Int = readByte(addr) + (readByte(addr + 1) << 8)

View File

@ -39,7 +39,8 @@ class MosAssembler(program: Program,
case AssemblyLine0(BYTE, _, _) => log.fatal("BYTE opcode failure") case AssemblyLine0(BYTE, _, _) => log.fatal("BYTE opcode failure")
case AssemblyLine0(_, RawByte, _) => log.fatal("BYTE opcode failure") case AssemblyLine0(_, RawByte, _) => log.fatal("BYTE opcode failure")
case AssemblyLine0(LABEL, _, MemoryAddressConstant(Label(labelName))) => case AssemblyLine0(LABEL, _, MemoryAddressConstant(Label(labelName))) =>
labelMap(labelName) = index val bank0 = mem.banks(bank)
labelMap(labelName) = bank0.index -> index
index index
case AssemblyLine0(_, DoesNotExist, _) => case AssemblyLine0(_, DoesNotExist, _) =>
index index
@ -66,7 +67,7 @@ class MosAssembler(program: Program,
} }
} }
override def injectLabels(labelMap: Map[String, Int], code: List[AssemblyLine]): List[AssemblyLine] = { override def injectLabels(labelMap: Map[String, (Int, Int)], code: List[AssemblyLine]): List[AssemblyLine] = {
import Opcode._ import Opcode._
code.map { code.map {
case l@AssemblyLine(LDA | STA | CMP | case l@AssemblyLine(LDA | STA | CMP |
@ -79,10 +80,10 @@ class MosAssembler(program: Program,
ISC | DCP | LAX | SAX | RLA | RRA | SLO | SRE, AddrMode.Absolute, p, Elidability.Elidable, _) => ISC | DCP | LAX | SAX | RLA | RRA | SLO | SRE, AddrMode.Absolute, p, Elidability.Elidable, _) =>
p match { p match {
case NumericConstant(n, _) => if (n <= 255) l.copy(addrMode = AddrMode.ZeroPage) else l case NumericConstant(n, _) => if (n <= 255) l.copy(addrMode = AddrMode.ZeroPage) else l
case MemoryAddressConstant(th) => if (labelMap.getOrElse(th.name, 0x800) < 0x100) l.copy(addrMode = AddrMode.ZeroPage) else l case MemoryAddressConstant(th) => if (labelMap.getOrElse(th.name, 0 -> 0x800)._2 < 0x100) l.copy(addrMode = AddrMode.ZeroPage) else l
case CompoundConstant(MathOperator.Plus, case CompoundConstant(MathOperator.Plus,
MemoryAddressConstant(th), MemoryAddressConstant(th),
NumericConstant(n, _)) => if (labelMap.getOrElse(th.name, 0x800) + n < 0x100) l.copy(addrMode = AddrMode.ZeroPage) else l NumericConstant(n, _)) => if (labelMap.getOrElse(th.name, 0 -> 0x800)._2 < 0x100) l.copy(addrMode = AddrMode.ZeroPage) else l
case _ => l case _ => l
} }

View File

@ -73,7 +73,8 @@ class Z80Assembler(program: Program,
try { instr match { try { instr match {
case ZLine0(LABEL, NoRegisters, MemoryAddressConstant(Label(labelName))) => case ZLine0(LABEL, NoRegisters, MemoryAddressConstant(Label(labelName))) =>
labelMap(labelName) = index val bank0 = mem.banks(bank)
labelMap(labelName) = bank0.index -> index
index index
case ZLine0(BYTE, NoRegisters, param) => case ZLine0(BYTE, NoRegisters, param) =>
writeByte(bank, index, param) writeByte(bank, index, param)
@ -688,7 +689,7 @@ class Z80Assembler(program: Program,
} }
} }
override def injectLabels(labelMap: Map[String, Int], code: List[ZLine]): List[ZLine] = code // TODO override def injectLabels(labelMap: Map[String, (Int, Int)], code: List[ZLine]): List[ZLine] = code // TODO
override def quickSimplify(code: List[ZLine]): List[ZLine] = code.map(a => a.copy(parameter = a.parameter.quickSimplify)) override def quickSimplify(code: List[ZLine]): List[ZLine] = code.map(a => a.copy(parameter = a.parameter.quickSimplify))

View File

@ -22,7 +22,7 @@ class Z80ToX86Crossassembler(program: Program,
} else code } else code
} }
override def injectLabels(labelMap: Map[String, Int], code: List[ZLine]): List[ZLine] = code // TODO override def injectLabels(labelMap: Map[String, (Int, Int)], code: List[ZLine]): List[ZLine] = code // TODO
override def quickSimplify(code: List[ZLine]): List[ZLine] = code.map(a => a.copy(parameter = a.parameter.quickSimplify)) override def quickSimplify(code: List[ZLine]): List[ZLine] = code.map(a => a.copy(parameter = a.parameter.quickSimplify))
@ -74,7 +74,8 @@ class Z80ToX86Crossassembler(program: Program,
import Z80ToX86Crossassembler._ import Z80ToX86Crossassembler._
instr match { instr match {
case ZLine0(LABEL, NoRegisters, MemoryAddressConstant(Label(labelName))) => case ZLine0(LABEL, NoRegisters, MemoryAddressConstant(Label(labelName))) =>
labelMap(labelName) = index val bank0 = mem.banks(bank)
labelMap(labelName) = bank0.index -> index
index index
case ZLine0(BYTE, NoRegisters, param) => case ZLine0(BYTE, NoRegisters, param) =>
writeByte(bank, index, param) writeByte(bank, index, param)

View File

@ -74,7 +74,7 @@ class EmuI86Run(nodeOptimizations: List[NodeOptimization], assemblyOptimizations
} }
def apply2(source: String): (Timings, MemoryBank) = { def apply2(source: String): (Timings, MemoryBank) = {
if (!Settings.enableIntel8086Tests) return Timings(-1, -1) -> new MemoryBank() if (!Settings.enableIntel8086Tests) return Timings(-1, -1) -> new MemoryBank(0)
Console.out.flush() Console.out.flush()
Console.err.flush() Console.err.flush()
val log = TestErrorReporting.log val log = TestErrorReporting.log
@ -139,7 +139,7 @@ class EmuI86Run(nodeOptimizations: List[NodeOptimization], assemblyOptimizations
println(";;; compiled: -----------------") println(";;; compiled: -----------------")
output.asm.takeWhile(s => !(s.startsWith(".") && s.contains("= $"))).filterNot(_.contains("////; DISCARD_")).foreach(println) output.asm.takeWhile(s => !(s.startsWith(".") && s.contains("= $"))).filterNot(_.contains("////; DISCARD_")).foreach(println)
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") }
val optimizedSize = assembler.mem.banks("default").initialized.count(identity).toLong val optimizedSize = assembler.mem.banks("default").initialized.count(identity).toLong
if (unoptimizedSize == optimizedSize) { if (unoptimizedSize == optimizedSize) {

View File

@ -2,7 +2,7 @@ package millfork.test.emu
import millfork.output.{AfterCodeByteAllocator, CurrentBankFragmentOutput, UpwardByteAllocator, VariableAllocator} import millfork.output.{AfterCodeByteAllocator, CurrentBankFragmentOutput, UpwardByteAllocator, VariableAllocator}
import millfork.parser.TextCodec import millfork.parser.TextCodec
import millfork.{Cpu, CpuFamily, OutputStyle, Platform} import millfork.{Cpu, CpuFamily, OutputStyle, Platform, ViceDebugOutputFormat}
/** /**
* @author Karol Stasiak * @author Karol Stasiak
@ -29,6 +29,7 @@ object EmuPlatform {
false, false,
Map("default" -> 0), Map("default" -> 0),
"default", "default",
ViceDebugOutputFormat,
OutputStyle.Single OutputStyle.Single
) )
} }

View File

@ -212,7 +212,7 @@ class EmuRun(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimization],
println(";;; compiled: -----------------") println(";;; compiled: -----------------")
output.asm.takeWhile(s => !(s.startsWith(".") && s.contains("= $"))).filterNot(_.contains("; DISCARD_")).foreach(println) output.asm.takeWhile(s => !(s.startsWith(".") && s.contains("= $"))).filterNot(_.contains("; DISCARD_")).foreach(println)
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") }
val optimizedSize = assembler.mem.banks("default").initialized.count(identity).toLong val optimizedSize = assembler.mem.banks("default").initialized.count(identity).toLong
if (unoptimizedSize == optimizedSize) { if (unoptimizedSize == optimizedSize) {

View File

@ -138,7 +138,7 @@ class EmuZ80Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizatio
println(";;; compiled: -----------------") println(";;; compiled: -----------------")
output.asm.takeWhile(s => !(s.startsWith(".") && s.contains("= $"))).filterNot(_.contains("////; DISCARD_")).foreach(println) output.asm.takeWhile(s => !(s.startsWith(".") && s.contains("= $"))).filterNot(_.contains("////; DISCARD_")).foreach(println)
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") }
val optimizedSize = assembler.mem.banks("default").initialized.count(identity).toLong val optimizedSize = assembler.mem.banks("default").initialized.count(identity).toLong
if (unoptimizedSize == optimizedSize) { if (unoptimizedSize == optimizedSize) {