1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-13 15:29:01 +00:00

Fixed return dispatch returns on LUnix. Added non-relocated address constants.

This commit is contained in:
Karol Stasiak 2018-06-10 01:56:04 +02:00
parent 8a417768b8
commit 278cbcec63
5 changed files with 72 additions and 21 deletions

View File

@ -81,6 +81,17 @@ After putting it on a disk, the file can be run with:
Currently, multipart BBC Micro programs are not supported.
### A note about LUnix
LUnix uses relocatable code, which means that object addresses (`.addr`) are not constants.
To help with this problem, new constants are defined, with a `.rawaddr` suffix.
They are not relocated, so to use them, you need to manually relocate them
by adding `relocation_offset` to their high bytes:
pointer p
p = variable.rawaddr
p.hi += relocation_offset
## Adding a custom platform
Every platform is defined in an `.ini` file with an appropriate name.

View File

@ -1,5 +1,7 @@
const word lkf_jumptab = $200
byte relocation_offset @$1001
inline asm byte get_ipid() {
? lda 2
? rts

View File

@ -52,11 +52,12 @@ object ReturnDispatch {
case _ => ()
}
var env = ctx.env
val returnType = ctx.function.returnType
val map: mutable.Map[Int, (String, List[Expression])] = mutable.Map()
val map: mutable.Map[Int, (Option[ThingInMemory], List[Expression])] = mutable.Map()
var min = Option.empty[Int]
var max = Option.empty[Int]
var default = Option.empty[(String, List[Expression])]
var default = Option.empty[(Option[ThingInMemory], List[Expression])]
stmt.branches.foreach { branch =>
val function: String = ctx.env.evalForAsm(branch.function) match {
case Some(MemoryAddressConstant(f: FunctionInMemory)) =>
@ -80,14 +81,14 @@ object ReturnDispatch {
}
min = start.map(toInt)
max = end.map(toInt)
default = Some(function -> params)
default = Some(Some(env.get[FunctionInMemory](function)) -> params)
case StandardReturnDispatchLabel(labels) =>
labels.foreach { label =>
val i = toInt(label)
if (map.contains(i)) {
ErrorReporting.error(s"Duplicate dispatch label: $label = $i", label.position)
}
map(i) = function -> params
map(i) = Some(env.get[FunctionInMemory](function)) -> params
}
}
}
@ -100,7 +101,7 @@ object ReturnDispatch {
}
val actualMin = defaultMin min nonDefaultMin.getOrElse(defaultMin)
val actualMax = defaultMax max nonDefaultMax.getOrElse(defaultMax)
val zeroes = "" -> List[Expression]()
val zeroes = None -> List[Expression]()
for (i <- actualMin to actualMax) {
if (!map.contains(i)) map(i) = default.getOrElse {
// TODO: warning?
@ -118,7 +119,6 @@ object ReturnDispatch {
else actualMax
}
var env = ctx.env
while (env.parent.isDefined) env = env.parent.get
val label = MfCompiler.nextLabel("di")
val paramArrays = stmt.params.indices.map { ix =>
@ -130,7 +130,7 @@ object ReturnDispatch {
a
}
val useJmpaix = ctx.options.flag(CompilationFlag.EmitCmosOpcodes) && (actualMax - actualMin) <= 127
val useJmpaix = ctx.options.flag(CompilationFlag.EmitCmosOpcodes) && !ctx.options.flag(CompilationFlag.LUnixRelocatableCode) && (actualMax - actualMin) <= 127
val b = ctx.env.get[Type]("byte")
import millfork.assembly.AddrMode._
@ -164,28 +164,43 @@ object ReturnDispatch {
val jumpTableHi = InitializedArray(label + "$jh.array", None, (actualMin to actualMax).map(i => hibyte1(map(i)._1)).toList, ctx.function.declaredBank)
env.registerUnnamedArray(jumpTableLo)
env.registerUnnamedArray(jumpTableHi)
loadIndex ++ copyParams ++ List(
AssemblyLine.absoluteX(LDA, jumpTableHi.toAddress - actualMin),
AssemblyLine.implied(PHA),
AssemblyLine.absoluteX(LDA, jumpTableLo.toAddress - actualMin),
AssemblyLine.implied(PHA),
AssemblyLine.implied(RTS))
val actualJump = if (ctx.options.flag(CompilationFlag.LUnixRelocatableCode)) {
List(
AssemblyLine.absoluteX(LDA, jumpTableHi.toAddress - actualMin),
AssemblyLine.implied(CLC),
AssemblyLine.absolute(ADC, env.get[ThingInMemory]("relocation_offset")),
AssemblyLine.implied(PHA),
AssemblyLine.absoluteX(LDA, jumpTableLo.toAddress - actualMin),
AssemblyLine.implied(PHA),
AssemblyLine.implied(RTS))
}else {
List(
AssemblyLine.absoluteX(LDA, jumpTableHi.toAddress - actualMin),
AssemblyLine.implied(PHA),
AssemblyLine.absoluteX(LDA, jumpTableLo.toAddress - actualMin),
AssemblyLine.implied(PHA),
AssemblyLine.implied(RTS))
}
loadIndex ++ copyParams ++ actualJump
}
}
private def lobyte0(fname: String): Expression = if (fname == "") LiteralExpression(0, 1) else {
FunctionCallExpression("lo",List(VariableExpression(fname + ".addr")))
private def zeroOr(function: Option[ThingInMemory])(F: ThingInMemory => Constant): Expression =
function.fold[Expression](LiteralExpression(0, 1))(F andThen ConstantArrayElementExpression)
private def lobyte0(function: Option[ThingInMemory]): Expression = {
zeroOr(function)(f => MemoryAddressConstant(f).loByte)
}
private def hibyte0(fname: String): Expression = if (fname == "") LiteralExpression(0, 1) else {
FunctionCallExpression("hi",List(VariableExpression(fname + ".addr")))
private def hibyte0(function: Option[ThingInMemory]): Expression = {
zeroOr(function)(f => MemoryAddressConstant(f).hiByte)
}
private def lobyte1(fname: String): Expression = if (fname == "") LiteralExpression(0, 1) else {
FunctionCallExpression("lo", List(SumExpression(List(false -> VariableExpression(fname + ".addr"), true -> LiteralExpression(1, 1)), decimal = false)))
private def lobyte1(function: Option[ThingInMemory]): Expression = {
zeroOr(function)(f => MemoryAddressConstant(f).-(1).loByte)
}
private def hibyte1(fname: String): Expression = if (fname == "") LiteralExpression(0, 1) else {
FunctionCallExpression("hi", List(SumExpression(List(false -> VariableExpression(fname + ".addr"), true -> LiteralExpression(1, 1)), decimal = false)))
private def hibyte1(function: Option[ThingInMemory]): Expression = {
zeroOr(function)(f => MemoryAddressConstant(f).-(1).hiByte)
}
}

View File

@ -174,14 +174,23 @@ class Environment(val parent: Option[Environment], val prefix: String) {
removedThings += str + ".addr"
removedThings += str + ".addr.lo"
removedThings += str + ".addr.hi"
removedThings += str + ".rawaddr"
removedThings += str + ".rawaddr.lo"
removedThings += str + ".rawaddr.hi"
things -= str
things -= str + ".addr"
things -= str + ".addr.lo"
things -= str + ".addr.hi"
things -= str + ".rawaddr"
things -= str + ".rawaddr.lo"
things -= str + ".rawaddr.hi"
things -= str.stripPrefix(prefix)
things -= str.stripPrefix(prefix) + ".addr"
things -= str.stripPrefix(prefix) + ".addr.lo"
things -= str.stripPrefix(prefix) + ".addr.hi"
things -= str.stripPrefix(prefix) + ".rawaddr"
things -= str.stripPrefix(prefix) + ".rawaddr.lo"
things -= str.stripPrefix(prefix) + ".rawaddr.hi"
parent.foreach(_ removeVariableImpl str)
}
@ -334,6 +343,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
def eval(e: Expression): Option[Constant] = {
e match {
case LiteralExpression(value, size) => Some(NumericConstant(value, size))
case ConstantArrayElementExpression(c) => Some(c)
case VariableExpression(name) =>
maybeGet[ConstantThing](name).map(_.value)
case IndexedExpression(_, _) => None
@ -429,6 +439,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
def evalForAsm(e: Expression): Option[Constant] = {
e match {
case LiteralExpression(value, size) => Some(NumericConstant(value, size))
case ConstantArrayElementExpression(c) => Some(c)
case VariableExpression(name) =>
maybeGet[ConstantThing](name).map(_.value).orElse(maybeGet[ThingInMemory](name).map(_.toAddress))
case IndexedExpression(name, index) => (evalForAsm(VariableExpression(name)), evalForAsm(index)) match {
@ -602,11 +613,18 @@ class Environment(val parent: Option[Environment], val prefix: String) {
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)
val rawaddr = thing.toAddress
addThing(ConstantThing(thing.name + ".rawaddr", rawaddr, get[Type]("pointer")), position)
addThing(ConstantThing(thing.name + ".rawaddr.hi", rawaddr.hiByte, get[Type]("byte")), position)
addThing(ConstantThing(thing.name + ".rawaddr.lo", rawaddr.loByte, get[Type]("byte")), 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)
addThing(ConstantThing(thing.name + ".rawaddr", addr, get[Type]("pointer")), position)
addThing(ConstantThing(thing.name + ".rawaddr.hi", addr.hiByte, get[Type]("byte")), position)
addThing(ConstantThing(thing.name + ".rawaddr.lo", addr.loByte, get[Type]("byte")), position)
}
}
@ -661,6 +679,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
val pointerName = array.name.stripSuffix(".array")
addThing(ConstantThing(pointerName, array.toAddress, p), None)
addThing(ConstantThing(pointerName + ".addr", array.toAddress, p), None)
addThing(ConstantThing(pointerName + ".rawaddr", array.toAddress, p), None)
addThing(array, None)
}

View File

@ -22,6 +22,10 @@ sealed trait Expression extends Node {
def replaceVariable(variable: String, actualParam: Expression): Expression
}
case class ConstantArrayElementExpression(constant: Constant) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
}
case class LiteralExpression(value: Long, requiredSize: Int) extends Expression {
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
}