mirror of
https://github.com/KarolS/millfork.git
synced 2024-08-28 05:29:06 +00:00
References to variables in assembly should always refer to their addresses
This commit is contained in:
parent
566631fc5e
commit
3e0d1d4978
@ -1090,13 +1090,9 @@ object MlCompiler {
|
||||
case function: InlinedFunction =>
|
||||
inlineFunction(function, params, Some(ctx)).map {
|
||||
case AssemblyStatement(opcode, addrMode, expression, elidable) =>
|
||||
val param = env.eval(expression).getOrElse {
|
||||
expression match {
|
||||
case VariableExpression(name) => env.get[ThingInMemory](name).toAddress
|
||||
case _ =>
|
||||
ErrorReporting.error("Inlining failed due to non-constant things", expression.position)
|
||||
Constant.Zero
|
||||
}
|
||||
val param = env.evalForAsm(expression).getOrElse {
|
||||
ErrorReporting.error("Inlining failed due to non-constant things", expression.position)
|
||||
Constant.Zero
|
||||
}
|
||||
AssemblyLine(opcode, addrMode, param, elidable)
|
||||
|
||||
@ -1427,12 +1423,17 @@ object MlCompiler {
|
||||
if (OpcodeClasses.ShortBranching(o) || o == JMP || o == LABEL) {
|
||||
MemoryAddressConstant(Label(name))
|
||||
} else{
|
||||
env.eval(x).getOrElse(env.get[ThingInMemory](name, x.position).toAddress)
|
||||
env.evalForAsm(x).getOrElse(env.get[ThingInMemory](name, x.position).toAddress)
|
||||
}
|
||||
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)))
|
||||
case Assignment(dest, source) =>
|
||||
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]) = {
|
||||
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 {
|
||||
c <- oc
|
||||
m <- om
|
||||
|
@ -96,4 +96,18 @@ class AssemblySuite extends FunSuite with Matchers {
|
||||
""".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