1
0
mirror of https://github.com/KarolS/millfork.git synced 2026-04-21 09:16:34 +00:00

Preliminary LUnix support

This commit is contained in:
Karol Stasiak
2018-06-09 00:18:21 +02:00
parent 5dc1bba8ed
commit 8931ced6fc
14 changed files with 444 additions and 51 deletions
@@ -104,6 +104,9 @@ object Cpu extends Enumeration {
case "6502" => Mos
case "6510" => Mos
case "strict" => StrictMos
case "strictnmos" => StrictMos
case "strict6502" => StrictMos
case "strict6510" => StrictMos
case "cmos" => Cmos
case "65sc02" => Cmos
case "sc02" => Cmos
@@ -135,7 +138,7 @@ object CompilationFlag extends Enumeration {
// optimization options:
DangerousOptimizations, InlineFunctions, OptimizeForSize, OptimizeForSpeed, OptimizeForSonicSpeed,
// memory allocation options
VariableOverlap, CompactReturnDispatchParams,
VariableOverlap, CompactReturnDispatchParams, LUnixRelocatableCode,
// runtime check options
CheckIndexOutOfBounds,
// special options
@@ -150,6 +153,7 @@ object CompilationFlag extends Enumeration {
val allWarnings: Set[CompilationFlag.Value] = Set(ExtraComparisonWarnings)
val fromString = Map(
"lunix" -> LUnixRelocatableCode,
"emit_illegals" -> EmitIllegals,
"emit_cmos" -> EmitCmosOpcodes,
"emit_65ce02" -> Emit65CE02Opcodes,
+17 -2
View File
@@ -13,7 +13,7 @@ import org.apache.commons.configuration2.INIConfiguration
*/
object OutputStyle extends Enumeration {
val Single, PerBank = Value
val Single, PerBank, LUnix = Value
}
class Platform(
@@ -135,7 +135,7 @@ object Platform {
val freePointers = as.get(classOf[String], "zp_pointers", "all") match {
case "all" => List.tabulate(128)(_ * 2)
case xs => xs.split("[, ]+").map(parseNumber).toList
case xs => xs.split("[, ]+").flatMap(parseNumberOrRange).toList
}
val codeAllocators = banks.map(b => b -> new UpwardByteAllocator(bankStarts(b), bankCodeEnds(b)))
@@ -148,7 +148,9 @@ object Platform {
val os = conf.getSection("output")
val outputPackager = SequenceOutput(os.get(classOf[String], "format", "").split("[, ]+").filter(_.nonEmpty).map {
case "startaddr" => StartAddressOutput
case "startpage" => StartPageOutput
case "endaddr" => EndAddressOutput
case "pagecount" => PageCountOutput
case "allocated" => AllocatedDataOutput
case n => n.split(":").filter(_.nonEmpty) match {
case Array(b, s, e) => BankFragmentOutput(b, parseNumber(s), parseNumber(e))
@@ -162,6 +164,7 @@ object Platform {
val outputStyle = os.get(classOf[String], "style", "single") match {
case "" | "single" => OutputStyle.Single
case "per_bank" | "per_segment" => OutputStyle.PerBank
case "lunix" => OutputStyle.LUnix
case x => ErrorReporting.fatal(s"Invalid output style: `$x`")
}
@@ -175,6 +178,18 @@ object Platform {
outputStyle)
}
def parseNumberOrRange(s:String): Seq[Int] = {
if (s.contains("-")) {
var segments = s.split("-")
if (segments.length != 2) {
ErrorReporting.fatal(s"Invalid range: `$s`")
}
Range(parseNumber(segments(0)), parseNumber(segments(1)), 2)
} else {
Seq(parseNumber(s))
}
}
def parseNumber(s: String): Int = {
if (s.startsWith("$")) {
Integer.parseInt(s.substring(1), 16)
+9 -7
View File
@@ -70,7 +70,7 @@ sealed trait Constant {
def quickSimplify: Constant = this
def isRelatedTo(v: Variable): Boolean
def isRelatedTo(v: Thing): Boolean
}
case class AssertByte(c: Constant) extends Constant {
@@ -78,13 +78,15 @@ case class AssertByte(c: Constant) extends Constant {
override def requiredSize: Int = 1
override def isRelatedTo(v: Variable): Boolean = c.isRelatedTo(v)
override def isRelatedTo(v: Thing): Boolean = c.isRelatedTo(v)
override def quickSimplify: Constant = AssertByte(c.quickSimplify)
}
case class UnexpandedConstant(name: String, requiredSize: Int) extends Constant {
override def isRelatedTo(v: Variable): Boolean = false
override def isRelatedTo(v: Thing): Boolean = false
override def toString: String = name
}
case class NumericConstant(value: Long, requiredSize: Int) extends Constant {
@@ -111,7 +113,7 @@ case class NumericConstant(value: Long, requiredSize: Int) extends Constant {
override def toString: String = if (value > 9) value.formatted("$%X") else value.toString
override def isRelatedTo(v: Variable): Boolean = false
override def isRelatedTo(v: Thing): Boolean = false
}
case class MemoryAddressConstant(var thing: ThingInMemory) extends Constant {
@@ -119,7 +121,7 @@ case class MemoryAddressConstant(var thing: ThingInMemory) extends Constant {
override def toString: String = thing.name
override def isRelatedTo(v: Variable): Boolean = thing.name == v.name
override def isRelatedTo(v: Thing): Boolean = thing.name == v.name
}
case class SubbyteConstant(base: Constant, index: Int) extends Constant {
@@ -144,7 +146,7 @@ case class SubbyteConstant(base: Constant, index: Int) extends Constant {
case 3 => ".b3"
})
override def isRelatedTo(v: Variable): Boolean = base.isRelatedTo(v)
override def isRelatedTo(v: Thing): Boolean = base.isRelatedTo(v)
}
object MathOperator extends Enumeration {
@@ -304,5 +306,5 @@ case class CompoundConstant(operator: MathOperator.Value, lhs: Constant, rhs: Co
override def requiredSize: Int = lhs.requiredSize max rhs.requiredSize
override def isRelatedTo(v: Variable): Boolean = lhs.isRelatedTo(v) || rhs.isRelatedTo(v)
override def isRelatedTo(v: Thing): Boolean = lhs.isRelatedTo(v) || rhs.isRelatedTo(v)
}
+68 -33
View File
@@ -100,7 +100,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
}
}.toSet
val toAdd = things.values.flatMap {
case m: UninitializedMemory if nf.isDefined == isLocalVariableName(m.name) =>
case m: UninitializedMemory if nf.isDefined == isLocalVariableName(m.name) && !m.name.endsWith(".addr") && maybeGet[Thing](m.name + ".array").isEmpty =>
val vertex = if (options.flag(CompilationFlag.VariableOverlap)) {
nf.fold[VariableVertex](GlobalVertex) { f =>
if (m.alloc == VariableAllocationMethod.Static) {
@@ -240,20 +240,23 @@ class Environment(val parent: Option[Environment], val prefix: String) {
if (parent.isEmpty) {
addThing(VoidType, None)
addThing(BuiltInBooleanType, None)
addThing(BasicPlainType("byte", 1), None)
addThing(BasicPlainType("word", 2), None)
val b = BasicPlainType("byte", 1)
val w = BasicPlainType("word", 2)
addThing(b, None)
addThing(w, None)
addThing(BasicPlainType("farword", 3), None)
addThing(BasicPlainType("long", 4), None)
addThing(DerivedPlainType("pointer", get[PlainType]("word"), isSigned = false), None)
// addThing(DerivedPlainType("farpointer", get[PlainType]("farword"), isSigned = false), None)
addThing(DerivedPlainType("ubyte", get[PlainType]("byte"), isSigned = false), None)
addThing(DerivedPlainType("sbyte", get[PlainType]("byte"), isSigned = true), None)
addThing(DerivedPlainType("pointer", w, isSigned = false), None)
// addThing(DerivedPlainType("farpointer", get[PlainType]("farword"), isSigned = false), None)
addThing(DerivedPlainType("ubyte", b, isSigned = false), None)
addThing(DerivedPlainType("sbyte", b, isSigned = true), None)
val trueType = ConstantBooleanType("true$", value = true)
val falseType = ConstantBooleanType("false$", value = false)
addThing(trueType, None)
addThing(falseType, None)
addThing(ConstantThing("true", NumericConstant(0, 0), trueType), None)
addThing(ConstantThing("false", NumericConstant(0, 0), falseType), None)
addThing(ConstantThing("__zeropage_usage", UnexpandedConstant("__zeropage_usage", 1), b), None)
addThing(FlagBooleanType("set_carry", Opcode.BCS, Opcode.BCC), None)
addThing(FlagBooleanType("clear_carry", Opcode.BCC, Opcode.BCS), None)
addThing(FlagBooleanType("set_overflow", Opcode.BVS, Opcode.BVC), None)
@@ -502,7 +505,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
}
val env = new Environment(Some(this), name + "$")
stmt.params.foreach(p => env.registerParameter(p))
stmt.params.foreach(p => env.registerParameter(p, options))
val params = if (stmt.assembly) {
AssemblyParamSignature(stmt.params.map {
pd =>
@@ -539,7 +542,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
stmt.bank
)
addThing(mangled, stmt.position)
registerAddressConstant(mangled, stmt.position)
registerAddressConstant(mangled, stmt.position, options)
addThing(ConstantThing(name + '`', addr, w), stmt.position)
}
@@ -585,19 +588,29 @@ class Environment(val parent: Option[Environment], val prefix: String) {
declaredBank = stmt.bank
)
addThing(mangled, stmt.position)
registerAddressConstant(mangled, stmt.position)
registerAddressConstant(mangled, stmt.position, options)
}
}
}
private def registerAddressConstant(thing: ThingInMemory, position: Option[Position]): Unit = {
val addr = thing.toAddress
addThing(ConstantThing(thing.name + ".addr", addr, get[Type]("pointer")), position)
addThing(ConstantThing(thing.name + ".addr.hi", addr.hiByte, get[Type]("byte")), position)
addThing(ConstantThing(thing.name + ".addr.lo", addr.loByte, get[Type]("byte")), position)
private def registerAddressConstant(thing: ThingInMemory, position: Option[Position], options: CompilationOptions): Unit = {
if (!thing.zeropage && options.flag(CompilationFlag.LUnixRelocatableCode)) {
val b = get[Type]("byte")
val w = get[Type]("word")
val relocatable = UninitializedMemoryVariable(thing.name + ".addr", w, VariableAllocationMethod.Static, None)
val addr = relocatable.toAddress
addThing(relocatable, position)
addThing(RelativeVariable(thing.name + ".addr.hi", addr + 1, b, zeropage = false, None), position)
addThing(RelativeVariable(thing.name + ".addr.lo", addr, b, zeropage = false, None), position)
} else {
val addr = thing.toAddress
addThing(ConstantThing(thing.name + ".addr", addr, get[Type]("pointer")), position)
addThing(ConstantThing(thing.name + ".addr.hi", addr.hiByte, get[Type]("byte")), position)
addThing(ConstantThing(thing.name + ".addr.lo", addr.loByte, get[Type]("byte")), position)
}
}
def registerParameter(stmt: ParameterDeclaration): Unit = {
def registerParameter(stmt: ParameterDeclaration, options: CompilationOptions): Unit = {
val typ = get[Type](stmt.typ)
val b = get[Type]("byte")
val w = get[Type]("word")
@@ -607,7 +620,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
val zp = typ.name == "pointer" // TODO
val v = UninitializedMemoryVariable(prefix + name, typ, if (zp) VariableAllocationMethod.Zeropage else VariableAllocationMethod.Auto, None)
addThing(v, stmt.position)
registerAddressConstant(v, stmt.position)
registerAddressConstant(v, stmt.position, options)
val addr = v.toAddress
typ.size match {
case 2 =>
@@ -674,7 +687,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
}
}
def registerArray(stmt: ArrayDeclarationStatement): Unit = {
def registerArray(stmt: ArrayDeclarationStatement, options: CompilationOptions): Unit = {
val b = get[Type]("byte")
val p = get[Type]("pointer")
stmt.elements match {
@@ -694,18 +707,30 @@ class Environment(val parent: Option[Environment], val prefix: String) {
declaredBank = stmt.bank)
}
addThing(array, stmt.position)
registerAddressConstant(UninitializedMemoryVariable(stmt.name, p, VariableAllocationMethod.None, stmt.bank), stmt.position)
registerAddressConstant(UninitializedMemoryVariable(stmt.name, p, VariableAllocationMethod.None, stmt.bank), stmt.position, options)
val a = address match {
case None => array.toAddress
case Some(aa) => aa
}
addThing(RelativeVariable(stmt.name + ".first", a, b, zeropage = false,
declaredBank = stmt.bank), stmt.position)
addThing(ConstantThing(stmt.name, a, p), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte.quickSimplify, b), stmt.position)
if (options.flag(CompilationFlag.LUnixRelocatableCode)) {
val b = get[Type]("byte")
val w = get[Type]("word")
val relocatable = UninitializedMemoryVariable(stmt.name, w, VariableAllocationMethod.Static, None)
val addr = relocatable.toAddress
addThing(relocatable, stmt.position)
addThing(RelativeVariable(stmt.name + ".addr.hi", addr + 1, b, zeropage = false, None), stmt.position)
addThing(RelativeVariable(stmt.name + ".addr.lo", addr, b, zeropage = false, None), stmt.position)
addThing(RelativeVariable(stmt.name + ".array.hi", addr + 1, b, zeropage = false, None), stmt.position)
addThing(RelativeVariable(stmt.name + ".array.lo", addr, b, zeropage = false, None), stmt.position)
} else {
addThing(ConstantThing(stmt.name, a, p), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte.quickSimplify, b), stmt.position)
}
if (length < 256) {
addThing(ConstantThing(stmt.name + ".length", lengthConst, b), stmt.position)
}
@@ -730,18 +755,28 @@ class Environment(val parent: Option[Environment], val prefix: String) {
val array = InitializedArray(stmt.name + ".array", address, contents, declaredBank = stmt.bank)
addThing(array, stmt.position)
registerAddressConstant(UninitializedMemoryVariable(stmt.name, p, VariableAllocationMethod.None,
declaredBank = stmt.bank), stmt.position)
declaredBank = stmt.bank), stmt.position, options)
val a = address match {
case None => array.toAddress
case Some(aa) => aa
}
addThing(RelativeVariable(stmt.name + ".first", a, b, zeropage = false,
declaredBank = stmt.bank), stmt.position)
addThing(ConstantThing(stmt.name, a, p), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte.quickSimplify, b), stmt.position)
if (options.flag(CompilationFlag.LUnixRelocatableCode)) {
val b = get[Type]("byte")
val w = get[Type]("word")
val relocatable = UninitializedMemoryVariable(stmt.name, w, VariableAllocationMethod.Static, None)
val addr = relocatable.toAddress
addThing(relocatable, stmt.position)
addThing(RelativeVariable(stmt.name + ".array.hi", addr + 1, b, zeropage = false, None), stmt.position)
addThing(RelativeVariable(stmt.name + ".array.lo", addr, b, zeropage = false, None), stmt.position)
} else {
addThing(ConstantThing(stmt.name, a, p), stmt.position)
addThing(ConstantThing(stmt.name + ".hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".lo", a.loByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.hi", a.hiByte.quickSimplify, b), stmt.position)
addThing(ConstantThing(stmt.name + ".array.lo", a.loByte.quickSimplify, b), stmt.position)
}
if (length < 256) {
addThing(ConstantThing(stmt.name + ".length", NumericConstant(length, 1), b), stmt.position)
}
@@ -846,7 +881,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
}
InitializedMemoryVariable(name, None, typ, ive, declaredBank = stmt.bank)
}
registerAddressConstant(v, stmt.position)
registerAddressConstant(v, stmt.position, options)
(v, v.toAddress)
})(a => {
val addr = eval(a).getOrElse(Constant.error(s"Address of `$name` has a non-constant value", position))
@@ -856,7 +891,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
}
val v = RelativeVariable(prefix + name, addr, typ, zeropage = zp,
declaredBank = stmt.bank)
registerAddressConstant(v, stmt.position)
registerAddressConstant(v, stmt.position, options)
(v, addr)
})
addThing(v, stmt.position)
@@ -927,7 +962,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
program.declarations.foreach {
case f: FunctionDeclarationStatement => registerFunction(f, options)
case v: VariableDeclarationStatement => registerVariable(v, options)
case a: ArrayDeclarationStatement => registerArray(a)
case a: ArrayDeclarationStatement => registerArray(a, options)
case i: ImportStatement => ()
}
if (options.flag(CompilationFlag.ZeropagePseudoregister) && !things.contains("__reg")) {
+14 -1
View File
@@ -78,6 +78,8 @@ sealed trait TypedThing extends Thing {
sealed trait ThingInMemory extends Thing {
def zeropage: Boolean
def toAddress: Constant
var farFlag: Option[Boolean] = None
@@ -105,12 +107,13 @@ case class Label(name: String) extends ThingInMemory {
declaredBank.getOrElse(compilationOptions.platform.defaultCodeBank)
override val declaredBank: Option[String] = None
override def zeropage: Boolean = false
}
sealed trait Variable extends TypedThing with VariableLikeThing
sealed trait VariableInMemory extends Variable with ThingInMemory with IndexableThing {
def zeropage: Boolean
override def isFar(compilationOptions: CompilationOptions): Boolean =
!zeropage && farFlag.getOrElse(false)
@@ -175,6 +178,8 @@ case class UninitializedArray(name: String, sizeInBytes: Int, declaredBank: Opti
override def isFar(compilationOptions: CompilationOptions): Boolean = farFlag.getOrElse(false)
override def bank(compilationOptions: CompilationOptions): String = declaredBank.getOrElse("default")
override def zeropage: Boolean = false
}
case class RelativeArray(name: String, address: Constant, sizeInBytes: Int, declaredBank: Option[String]) extends MfArray {
@@ -183,6 +188,8 @@ case class RelativeArray(name: String, address: Constant, sizeInBytes: Int, decl
override def isFar(compilationOptions: CompilationOptions): Boolean = farFlag.getOrElse(false)
override def bank(compilationOptions: CompilationOptions): String = declaredBank.getOrElse("default")
override def zeropage: Boolean = false
}
case class InitializedArray(name: String, address: Option[Constant], contents: List[Expression], declaredBank: Option[String]) extends MfArray with PreallocableThing {
@@ -191,6 +198,8 @@ case class InitializedArray(name: String, address: Option[Constant], contents: L
override def isFar(compilationOptions: CompilationOptions): Boolean = farFlag.getOrElse(false)
override def bank(compilationOptions: CompilationOptions): String = declaredBank.getOrElse(compilationOptions.platform.defaultCodeBank)
override def zeropage: Boolean = false
}
case class RelativeVariable(name: String, address: Constant, typ: Type, zeropage: Boolean, declaredBank: Option[String]) extends VariableInMemory {
@@ -242,6 +251,8 @@ case class ExternFunction(name: String,
override def toAddress: Constant = address
override def interrupt = false
override def zeropage: Boolean = false
}
case class NormalFunction(name: String,
@@ -257,6 +268,8 @@ case class NormalFunction(name: String,
position: Option[Position],
declaredBank: Option[String]) extends FunctionInMemory with PreallocableThing {
override def shouldGenerate = true
override def zeropage: Boolean = false
}
case class ConstantThing(name: String, value: Constant, typ: Type) extends TypedThing with VariableLikeThing with IndexableThing {
+49 -4
View File
@@ -78,7 +78,7 @@ class Assembler(private val program: Program, private val rootEnv: Environment,
try {
if (labelMap.contains(th.name)) return labelMap(th.name)
if (labelMap.contains(th.name + "`")) return labelMap(th.name)
if (labelMap.contains(th.name + ".addr")) return labelMap(th.name)
if (labelMap.contains(th.name + ".addr")) return labelMap.getOrElse[Int](th.name, labelMap(th.name + ".array"))
val x1 = 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)
@@ -97,6 +97,9 @@ class Assembler(private val program: Program, private val rootEnv: Environment,
case e: StackOverflowError =>
ErrorReporting.fatal("Stack overflow " + c)
}
case UnexpandedConstant(name, _) =>
if (labelMap.contains(name)) labelMap(name)
else ???
case SubbyteConstant(cc, i) => deepConstResolve(cc).>>>(i * 8).&(0xff)
case CompoundConstant(operator, lc, rc) =>
val l = deepConstResolve(lc)
@@ -282,6 +285,42 @@ class Assembler(private val program: Program, private val rootEnv: Environment,
}
case _ =>
}
if (options.flag(CompilationFlag.LUnixRelocatableCode)) {
env.allThings.things.foreach {
case (_, m@UninitializedMemoryVariable(name, typ, _, _)) if name.endsWith(".addr") || env.maybeGet[Thing](name + ".array").isDefined =>
val isUsed = compiledFunctions.values.exists(_.exists(_.parameter.isRelatedTo(m)))
// println(m.name -> isUsed)
if (isUsed) {
val bank = m.bank(options)
if (bank != "default") ???
val bank0 = mem.banks(bank)
var index = codeAllocators(bank).allocateBytes(bank0, options, typ.size + 1, initialized = true, writeable = false)
labelMap(name) = index + 1
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")
env.things += altName -> ConstantThing(altName, NumericConstant(index, 2), env.get[Type]("pointer"))
assembly.append("* = $" + index.toHexString)
assembly.append(" !byte $2c")
assembly.append(name)
val c = thing.toAddress
writeByte(bank, index, 0x2c.toByte) // BIT abs
index += 1
for (i <- 0 until typ.size) {
writeByte(bank, index, c.subbyte(i))
assembly.append(" !byte " + c.subbyte(i).quickSimplify)
index += 1
}
initializedVariablesSize += typ.size
justAfterCode += bank -> index
}
case _ => ()
}
val index = codeAllocators("default").allocateBytes(mem.banks("default"), options, 1, initialized = true, writeable = false)
writeByte("default", index, 2.toByte) // BIT abs
assembly.append("* = $" + index.toHexString)
assembly.append(" !byte 2 ;; end of LUnix relocatable segment")
justAfterCode += "default" -> (index + 1)
}
env.allPreallocatables.foreach {
case thing@InitializedArray(name, None, items, _) =>
val bank = thing.bank(options)
@@ -305,7 +344,7 @@ class Assembler(private val program: Program, private val rootEnv: Environment,
}
initializedVariablesSize += items.length
justAfterCode += bank -> index
case m@InitializedMemoryVariable(name, None, typ, value, _) =>
case m@InitializedMemoryVariable(name, None, typ, value, _) =>
val bank = m.bank(options)
val bank0 = mem.banks(bank)
var index = codeAllocators(bank).allocateBytes(bank0, options, typ.size, initialized = true, writeable = true)
@@ -335,9 +374,15 @@ class Assembler(private val program: Program, private val rootEnv: Environment,
for(i <- 0 until size) bank0.occupied(addr + i) = true
}
val variableAllocators = platform.variableAllocators
variableAllocators.foreach{case (b,a) => a.notifyAboutEndOfCode(justAfterCode(b))}
variableAllocators.foreach { case (b, a) => a.notifyAboutEndOfCode(justAfterCode(b)) }
env.allocateVariables(None, mem, callGraph, variableAllocators, options, labelMap.put)
val zeropageOccupation = mem.banks("default").occupied.slice(variableAllocators("default").pointers.head, variableAllocators("default").pointers.last + 2)
labelMap += "__zeropage_usage" -> (zeropageOccupation.lastIndexOf(true) - zeropageOccupation.indexOf(true) + 1)
labelMap += "__zeropage_first" -> (zeropageOccupation.indexOf(true) max 0)
labelMap += "__zeropage_last" -> (zeropageOccupation.lastIndexOf(true) max 0)
labelMap += "__zeropage_end" -> (zeropageOccupation.lastIndexOf(true) + 1)
env = rootEnv.allThings
for ((bank, addr, b) <- bytesToWriteLater) {
@@ -367,7 +412,7 @@ class Assembler(private val program: Program, private val rootEnv: Environment,
// TODO:
val code = (platform.outputStyle match {
case OutputStyle.Single => List("default")
case OutputStyle.Single | OutputStyle.LUnix => List("default")
case OutputStyle.PerBank => platform.bankNumbers.keys.toList
}).map(b => b -> platform.outputPackager.packageOutput(mem, b)).toMap
AssemblerOutput(code, assembly.toArray, labelMap.toList)
@@ -45,6 +45,13 @@ object StartAddressOutput extends OutputPackager {
}
}
object StartPageOutput extends OutputPackager {
def packageOutput(mem: CompiledMemory, bank: String): Array[Byte] = {
val b = mem.banks(bank)
Array(b.start.>>(8).toByte)
}
}
object EndAddressOutput extends OutputPackager {
def packageOutput(mem: CompiledMemory, bank: String): Array[Byte] = {
val b = mem.banks(bank)
@@ -52,6 +59,14 @@ object EndAddressOutput extends OutputPackager {
}
}
object PageCountOutput extends OutputPackager {
def packageOutput(mem: CompiledMemory, bank: String): Array[Byte] = {
val e = mem.banks(bank).end.>>(8)
val s = mem.banks(bank).start.>>(8)
Array((e - s + 1).toByte)
}
}
object AllocatedDataOutput extends OutputPackager {
def packageOutput(mem: CompiledMemory, bank: String): Array[Byte] = {
val b = mem.banks(bank)
@@ -50,7 +50,7 @@ class AfterCodeByteAllocator(val endBefore: Int) extends ByteAllocator {
def notifyAboutEndOfCode(org: Int): Unit = startAt = org
}
class VariableAllocator(private val pointers: List[Int], private val bytes: ByteAllocator) {
class VariableAllocator(val pointers: List[Int], private val bytes: ByteAllocator) {
private val pointerMap = mutable.Map[Int, Set[VariableVertex]]()
private val variableMap = mutable.Map[Int, mutable.Map[Int, Set[VariableVertex]]]()