mirror of
https://github.com/KarolS/millfork.git
synced 2024-10-30 06:24:09 +00:00
References to variables in assembly should always refer to their addresses
This commit is contained in:
parent
566631fc5e
commit
3e0d1d4978
@ -1090,14 +1090,10 @@ object MlCompiler {
|
|||||||
case function: InlinedFunction =>
|
case function: InlinedFunction =>
|
||||||
inlineFunction(function, params, Some(ctx)).map {
|
inlineFunction(function, params, Some(ctx)).map {
|
||||||
case AssemblyStatement(opcode, addrMode, expression, elidable) =>
|
case AssemblyStatement(opcode, addrMode, expression, elidable) =>
|
||||||
val param = env.eval(expression).getOrElse {
|
val param = env.evalForAsm(expression).getOrElse {
|
||||||
expression match {
|
|
||||||
case VariableExpression(name) => env.get[ThingInMemory](name).toAddress
|
|
||||||
case _ =>
|
|
||||||
ErrorReporting.error("Inlining failed due to non-constant things", expression.position)
|
ErrorReporting.error("Inlining failed due to non-constant things", expression.position)
|
||||||
Constant.Zero
|
Constant.Zero
|
||||||
}
|
}
|
||||||
}
|
|
||||||
AssemblyLine(opcode, addrMode, param, elidable)
|
AssemblyLine(opcode, addrMode, param, elidable)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1427,12 +1423,17 @@ object MlCompiler {
|
|||||||
if (OpcodeClasses.ShortBranching(o) || o == JMP || o == LABEL) {
|
if (OpcodeClasses.ShortBranching(o) || o == JMP || o == LABEL) {
|
||||||
MemoryAddressConstant(Label(name))
|
MemoryAddressConstant(Label(name))
|
||||||
} else{
|
} else{
|
||||||
env.eval(x).getOrElse(env.get[ThingInMemory](name, x.position).toAddress)
|
env.evalForAsm(x).getOrElse(env.get[ThingInMemory](name, x.position).toAddress)
|
||||||
}
|
}
|
||||||
case _ =>
|
case _ =>
|
||||||
env.eval(x).getOrElse(Constant.error(s"`$x` is not a constant", x.position))
|
env.evalForAsm(x).getOrElse(Constant.error(s"`$x` is not a constant", x.position))
|
||||||
|
}
|
||||||
|
val actualAddrMode = a match {
|
||||||
|
case Absolute if OpcodeClasses.ShortBranching(o) => Relative
|
||||||
|
case IndexedX if o == JMP => AbsoluteIndexedX
|
||||||
|
case Indirect if o != JMP => ZeroPageIndirect
|
||||||
|
case _ => a
|
||||||
}
|
}
|
||||||
val actualAddrMode = if (OpcodeClasses.ShortBranching(o) && a == Absolute) Relative else a
|
|
||||||
LinearChunk(List(AssemblyLine(o, actualAddrMode, c, e)))
|
LinearChunk(List(AssemblyLine(o, actualAddrMode, c, e)))
|
||||||
case Assignment(dest, source) =>
|
case Assignment(dest, source) =>
|
||||||
LinearChunk(compileAssignment(ctx, source, dest))
|
LinearChunk(compileAssignment(ctx, source, dest))
|
||||||
|
57
src/main/scala/millfork/env/Environment.scala
vendored
57
src/main/scala/millfork/env/Environment.scala
vendored
@ -285,7 +285,62 @@ class Environment(val parent: Option[Environment], val prefix: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private def constantOperation(op: MathOperator.Value, params: List[Expression]) = {
|
private def constantOperation(op: MathOperator.Value, params: List[Expression]) = {
|
||||||
params.map(eval(_)).reduceLeft[Option[Constant]] { (oc, om) =>
|
params.map(eval).reduceLeft[Option[Constant]] { (oc, om) =>
|
||||||
|
for {
|
||||||
|
c <- oc
|
||||||
|
m <- om
|
||||||
|
} yield CompoundConstant(op, c, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def evalForAsm(e: Expression): Option[Constant] = {
|
||||||
|
e match {
|
||||||
|
case LiteralExpression(value, size) => Some(NumericConstant(value, size))
|
||||||
|
case VariableExpression(name) =>
|
||||||
|
maybeGet[ConstantThing](name).map(_.value).orElse(maybeGet[ThingInMemory](name).map(_.toAddress))
|
||||||
|
case IndexedExpression(name, index) => (evalForAsm(VariableExpression(name)), evalForAsm(index)) match {
|
||||||
|
case (Some(a), Some(b)) => Some(CompoundConstant(MathOperator.Plus, a, b).quickSimplify)
|
||||||
|
}
|
||||||
|
case HalfWordExpression(param, hi) => evalForAsm(e).map(c => if (hi) c.hiByte else c.loByte)
|
||||||
|
case SumExpression(params, decimal) =>
|
||||||
|
params.map {
|
||||||
|
case (minus, param) => (minus, evalForAsm(param))
|
||||||
|
}.foldLeft(Some(Constant.Zero).asInstanceOf[Option[Constant]]) { (oc, pair) =>
|
||||||
|
oc.flatMap { c =>
|
||||||
|
pair match {
|
||||||
|
case (_, None) => None
|
||||||
|
case (minus, Some(addend)) =>
|
||||||
|
val op = if (decimal) {
|
||||||
|
if (minus) MathOperator.DecimalMinus else MathOperator.DecimalPlus
|
||||||
|
} else {
|
||||||
|
if (minus) MathOperator.Minus else MathOperator.Plus
|
||||||
|
}
|
||||||
|
Some(CompoundConstant(op, c, addend))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case SeparateBytesExpression(h, l) => for {
|
||||||
|
lc <- evalForAsm(l)
|
||||||
|
hc <- evalForAsm(h)
|
||||||
|
} yield hc.asl(8) + lc
|
||||||
|
case FunctionCallExpression(name, params) =>
|
||||||
|
name match {
|
||||||
|
case "*" =>
|
||||||
|
constantOperationForAsm(MathOperator.Times, params)
|
||||||
|
case "&&" | "&" =>
|
||||||
|
constantOperationForAsm(MathOperator.And, params)
|
||||||
|
case "^" =>
|
||||||
|
constantOperationForAsm(MathOperator.Exor, params)
|
||||||
|
case "||" | "|" =>
|
||||||
|
constantOperationForAsm(MathOperator.Or, params)
|
||||||
|
case _ =>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def constantOperationForAsm(op: MathOperator.Value, params: List[Expression]) = {
|
||||||
|
params.map(evalForAsm).reduceLeft[Option[Constant]] { (oc, om) =>
|
||||||
for {
|
for {
|
||||||
c <- oc
|
c <- oc
|
||||||
m <- om
|
m <- om
|
||||||
|
@ -96,4 +96,18 @@ class AssemblySuite extends FunSuite with Matchers {
|
|||||||
""".stripMargin)(_.readByte(0xc000) should equal(5))
|
""".stripMargin)(_.readByte(0xc000) should equal(5))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("Adresses in asm") {
|
||||||
|
EmuBenchmarkRun(
|
||||||
|
"""
|
||||||
|
| word output @$c000
|
||||||
|
| void main () {
|
||||||
|
| output = 0
|
||||||
|
| add256(output)
|
||||||
|
| }
|
||||||
|
| inline asm void add256(word ref v) {
|
||||||
|
| inc v+1
|
||||||
|
| }
|
||||||
|
""".stripMargin)(_.readWord(0xc000) should equal(0x100))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user