mirror of
https://github.com/KarolS/millfork.git
synced 2024-10-25 05:24:11 +00:00
Fixed return dispatch returns on LUnix. Added non-relocated address constants.
This commit is contained in:
parent
8a417768b8
commit
278cbcec63
@ -81,6 +81,17 @@ After putting it on a disk, the file can be run with:
|
|||||||
|
|
||||||
Currently, multipart BBC Micro programs are not supported.
|
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
|
## Adding a custom platform
|
||||||
|
|
||||||
Every platform is defined in an `.ini` file with an appropriate name.
|
Every platform is defined in an `.ini` file with an appropriate name.
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
const word lkf_jumptab = $200
|
const word lkf_jumptab = $200
|
||||||
|
|
||||||
|
byte relocation_offset @$1001
|
||||||
|
|
||||||
inline asm byte get_ipid() {
|
inline asm byte get_ipid() {
|
||||||
? lda 2
|
? lda 2
|
||||||
? rts
|
? rts
|
||||||
|
@ -52,11 +52,12 @@ object ReturnDispatch {
|
|||||||
case _ => ()
|
case _ => ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var env = ctx.env
|
||||||
val returnType = ctx.function.returnType
|
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 min = Option.empty[Int]
|
||||||
var max = 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 =>
|
stmt.branches.foreach { branch =>
|
||||||
val function: String = ctx.env.evalForAsm(branch.function) match {
|
val function: String = ctx.env.evalForAsm(branch.function) match {
|
||||||
case Some(MemoryAddressConstant(f: FunctionInMemory)) =>
|
case Some(MemoryAddressConstant(f: FunctionInMemory)) =>
|
||||||
@ -80,14 +81,14 @@ object ReturnDispatch {
|
|||||||
}
|
}
|
||||||
min = start.map(toInt)
|
min = start.map(toInt)
|
||||||
max = end.map(toInt)
|
max = end.map(toInt)
|
||||||
default = Some(function -> params)
|
default = Some(Some(env.get[FunctionInMemory](function)) -> params)
|
||||||
case StandardReturnDispatchLabel(labels) =>
|
case StandardReturnDispatchLabel(labels) =>
|
||||||
labels.foreach { label =>
|
labels.foreach { label =>
|
||||||
val i = toInt(label)
|
val i = toInt(label)
|
||||||
if (map.contains(i)) {
|
if (map.contains(i)) {
|
||||||
ErrorReporting.error(s"Duplicate dispatch label: $label = $i", label.position)
|
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 actualMin = defaultMin min nonDefaultMin.getOrElse(defaultMin)
|
||||||
val actualMax = defaultMax max nonDefaultMax.getOrElse(defaultMax)
|
val actualMax = defaultMax max nonDefaultMax.getOrElse(defaultMax)
|
||||||
val zeroes = "" -> List[Expression]()
|
val zeroes = None -> List[Expression]()
|
||||||
for (i <- actualMin to actualMax) {
|
for (i <- actualMin to actualMax) {
|
||||||
if (!map.contains(i)) map(i) = default.getOrElse {
|
if (!map.contains(i)) map(i) = default.getOrElse {
|
||||||
// TODO: warning?
|
// TODO: warning?
|
||||||
@ -118,7 +119,6 @@ object ReturnDispatch {
|
|||||||
else actualMax
|
else actualMax
|
||||||
}
|
}
|
||||||
|
|
||||||
var env = ctx.env
|
|
||||||
while (env.parent.isDefined) env = env.parent.get
|
while (env.parent.isDefined) env = env.parent.get
|
||||||
val label = MfCompiler.nextLabel("di")
|
val label = MfCompiler.nextLabel("di")
|
||||||
val paramArrays = stmt.params.indices.map { ix =>
|
val paramArrays = stmt.params.indices.map { ix =>
|
||||||
@ -130,7 +130,7 @@ object ReturnDispatch {
|
|||||||
a
|
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")
|
val b = ctx.env.get[Type]("byte")
|
||||||
|
|
||||||
import millfork.assembly.AddrMode._
|
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)
|
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(jumpTableLo)
|
||||||
env.registerUnnamedArray(jumpTableHi)
|
env.registerUnnamedArray(jumpTableHi)
|
||||||
loadIndex ++ copyParams ++ List(
|
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.absoluteX(LDA, jumpTableHi.toAddress - actualMin),
|
||||||
AssemblyLine.implied(PHA),
|
AssemblyLine.implied(PHA),
|
||||||
AssemblyLine.absoluteX(LDA, jumpTableLo.toAddress - actualMin),
|
AssemblyLine.absoluteX(LDA, jumpTableLo.toAddress - actualMin),
|
||||||
AssemblyLine.implied(PHA),
|
AssemblyLine.implied(PHA),
|
||||||
AssemblyLine.implied(RTS))
|
AssemblyLine.implied(RTS))
|
||||||
}
|
}
|
||||||
|
loadIndex ++ copyParams ++ actualJump
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def lobyte0(fname: String): Expression = if (fname == "") LiteralExpression(0, 1) else {
|
private def zeroOr(function: Option[ThingInMemory])(F: ThingInMemory => Constant): Expression =
|
||||||
FunctionCallExpression("lo",List(VariableExpression(fname + ".addr")))
|
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 {
|
private def hibyte0(function: Option[ThingInMemory]): Expression = {
|
||||||
FunctionCallExpression("hi",List(VariableExpression(fname + ".addr")))
|
zeroOr(function)(f => MemoryAddressConstant(f).hiByte)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def lobyte1(fname: String): Expression = if (fname == "") LiteralExpression(0, 1) else {
|
private def lobyte1(function: Option[ThingInMemory]): Expression = {
|
||||||
FunctionCallExpression("lo", List(SumExpression(List(false -> VariableExpression(fname + ".addr"), true -> LiteralExpression(1, 1)), decimal = false)))
|
zeroOr(function)(f => MemoryAddressConstant(f).-(1).loByte)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def hibyte1(fname: String): Expression = if (fname == "") LiteralExpression(0, 1) else {
|
private def hibyte1(function: Option[ThingInMemory]): Expression = {
|
||||||
FunctionCallExpression("hi", List(SumExpression(List(false -> VariableExpression(fname + ".addr"), true -> LiteralExpression(1, 1)), decimal = false)))
|
zeroOr(function)(f => MemoryAddressConstant(f).-(1).hiByte)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
src/main/scala/millfork/env/Environment.scala
vendored
19
src/main/scala/millfork/env/Environment.scala
vendored
@ -174,14 +174,23 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
|||||||
removedThings += str + ".addr"
|
removedThings += str + ".addr"
|
||||||
removedThings += str + ".addr.lo"
|
removedThings += str + ".addr.lo"
|
||||||
removedThings += str + ".addr.hi"
|
removedThings += str + ".addr.hi"
|
||||||
|
removedThings += str + ".rawaddr"
|
||||||
|
removedThings += str + ".rawaddr.lo"
|
||||||
|
removedThings += str + ".rawaddr.hi"
|
||||||
things -= str
|
things -= str
|
||||||
things -= str + ".addr"
|
things -= str + ".addr"
|
||||||
things -= str + ".addr.lo"
|
things -= str + ".addr.lo"
|
||||||
things -= str + ".addr.hi"
|
things -= str + ".addr.hi"
|
||||||
|
things -= str + ".rawaddr"
|
||||||
|
things -= str + ".rawaddr.lo"
|
||||||
|
things -= str + ".rawaddr.hi"
|
||||||
things -= str.stripPrefix(prefix)
|
things -= str.stripPrefix(prefix)
|
||||||
things -= str.stripPrefix(prefix) + ".addr"
|
things -= str.stripPrefix(prefix) + ".addr"
|
||||||
things -= str.stripPrefix(prefix) + ".addr.lo"
|
things -= str.stripPrefix(prefix) + ".addr.lo"
|
||||||
things -= str.stripPrefix(prefix) + ".addr.hi"
|
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)
|
parent.foreach(_ removeVariableImpl str)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,6 +343,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
|||||||
def eval(e: Expression): Option[Constant] = {
|
def eval(e: Expression): Option[Constant] = {
|
||||||
e match {
|
e match {
|
||||||
case LiteralExpression(value, size) => Some(NumericConstant(value, size))
|
case LiteralExpression(value, size) => Some(NumericConstant(value, size))
|
||||||
|
case ConstantArrayElementExpression(c) => Some(c)
|
||||||
case VariableExpression(name) =>
|
case VariableExpression(name) =>
|
||||||
maybeGet[ConstantThing](name).map(_.value)
|
maybeGet[ConstantThing](name).map(_.value)
|
||||||
case IndexedExpression(_, _) => None
|
case IndexedExpression(_, _) => None
|
||||||
@ -429,6 +439,7 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
|||||||
def evalForAsm(e: Expression): Option[Constant] = {
|
def evalForAsm(e: Expression): Option[Constant] = {
|
||||||
e match {
|
e match {
|
||||||
case LiteralExpression(value, size) => Some(NumericConstant(value, size))
|
case LiteralExpression(value, size) => Some(NumericConstant(value, size))
|
||||||
|
case ConstantArrayElementExpression(c) => Some(c)
|
||||||
case VariableExpression(name) =>
|
case VariableExpression(name) =>
|
||||||
maybeGet[ConstantThing](name).map(_.value).orElse(maybeGet[ThingInMemory](name).map(_.toAddress))
|
maybeGet[ConstantThing](name).map(_.value).orElse(maybeGet[ThingInMemory](name).map(_.toAddress))
|
||||||
case IndexedExpression(name, index) => (evalForAsm(VariableExpression(name)), evalForAsm(index)) match {
|
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(relocatable, position)
|
||||||
addThing(RelativeVariable(thing.name + ".addr.hi", addr + 1, b, zeropage = false, None), 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)
|
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 {
|
} else {
|
||||||
val addr = thing.toAddress
|
val addr = thing.toAddress
|
||||||
addThing(ConstantThing(thing.name + ".addr", addr, get[Type]("pointer")), position)
|
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.hi", addr.hiByte, get[Type]("byte")), position)
|
||||||
addThing(ConstantThing(thing.name + ".addr.lo", addr.loByte, 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")
|
val pointerName = array.name.stripSuffix(".array")
|
||||||
addThing(ConstantThing(pointerName, array.toAddress, p), None)
|
addThing(ConstantThing(pointerName, array.toAddress, p), None)
|
||||||
addThing(ConstantThing(pointerName + ".addr", array.toAddress, p), None)
|
addThing(ConstantThing(pointerName + ".addr", array.toAddress, p), None)
|
||||||
|
addThing(ConstantThing(pointerName + ".rawaddr", array.toAddress, p), None)
|
||||||
addThing(array, None)
|
addThing(array, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,10 @@ sealed trait Expression extends Node {
|
|||||||
def replaceVariable(variable: String, actualParam: Expression): Expression
|
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 {
|
case class LiteralExpression(value: Long, requiredSize: Int) extends Expression {
|
||||||
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
|
override def replaceVariable(variable: String, actualParam: Expression): Expression = this
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user