mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-11 12:29:46 +00:00
Multiple improvements:
- fixed some invalid LDX(zp),Y instructions - better error reporting - removing unused extern functions - a new testcase
This commit is contained in:
parent
775707801c
commit
5dc1bba8ed
@ -695,7 +695,7 @@ object ExpressionCompiler {
|
|||||||
case Register.A =>
|
case Register.A =>
|
||||||
List(AssemblyLine.indexedY(LDA, reg))
|
List(AssemblyLine.indexedY(LDA, reg))
|
||||||
case Register.X =>
|
case Register.X =>
|
||||||
List(AssemblyLine.indexedY(LDX, reg))
|
List(AssemblyLine.indexedY(LDA, reg), AssemblyLine.implied(TAX))
|
||||||
case Register.Y =>
|
case Register.Y =>
|
||||||
List(AssemblyLine.indexedY(LDA, reg), AssemblyLine.implied(TAY))
|
List(AssemblyLine.indexedY(LDA, reg), AssemblyLine.implied(TAY))
|
||||||
}
|
}
|
||||||
@ -716,7 +716,7 @@ object ExpressionCompiler {
|
|||||||
case Register.Y =>
|
case Register.Y =>
|
||||||
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAY))
|
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAY))
|
||||||
case Register.X =>
|
case Register.X =>
|
||||||
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedY(LDX, p.addr))
|
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAX))
|
||||||
}
|
}
|
||||||
case (p:VariablePointy, Some(_), 0 | 1, _) =>
|
case (p:VariablePointy, Some(_), 0 | 1, _) =>
|
||||||
val calculatingIndex = compile(ctx, indexExpr, Some(b, RegisterVariable(Register.Y, b)), NoBranching)
|
val calculatingIndex = compile(ctx, indexExpr, Some(b, RegisterVariable(Register.Y, b)), NoBranching)
|
||||||
@ -724,7 +724,7 @@ object ExpressionCompiler {
|
|||||||
case Register.A =>
|
case Register.A =>
|
||||||
calculatingIndex :+ AssemblyLine.indexedY(LDA, p.addr)
|
calculatingIndex :+ AssemblyLine.indexedY(LDA, p.addr)
|
||||||
case Register.X =>
|
case Register.X =>
|
||||||
calculatingIndex :+ AssemblyLine.indexedY(LDX, p.addr)
|
calculatingIndex ++ List(AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAX))
|
||||||
case Register.Y =>
|
case Register.Y =>
|
||||||
calculatingIndex ++ List(AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAY))
|
calculatingIndex ++ List(AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAY))
|
||||||
}
|
}
|
||||||
@ -1270,7 +1270,7 @@ object ExpressionCompiler {
|
|||||||
|
|
||||||
def expressionStorageFromAX(ctx: CompilationContext, exprTypeAndVariable: Option[(Type, Variable)], position: Option[Position]): List[AssemblyLine] = {
|
def expressionStorageFromAX(ctx: CompilationContext, exprTypeAndVariable: Option[(Type, Variable)], position: Option[Position]): List[AssemblyLine] = {
|
||||||
exprTypeAndVariable.fold(noop) {
|
exprTypeAndVariable.fold(noop) {
|
||||||
case (VoidType, _) => ???
|
case (VoidType, _) => ErrorReporting.fatal("Cannot assign word to void", position)
|
||||||
case (_, RegisterVariable(Register.A, _)) => noop
|
case (_, RegisterVariable(Register.A, _)) => noop
|
||||||
case (_, RegisterVariable(Register.AW, _)) => List(AssemblyLine.implied(XBA), AssemblyLine.implied(TXA), AssemblyLine.implied(XBA))
|
case (_, RegisterVariable(Register.AW, _)) => List(AssemblyLine.implied(XBA), AssemblyLine.implied(TXA), AssemblyLine.implied(XBA))
|
||||||
case (_, RegisterVariable(Register.X, _)) => List(AssemblyLine.implied(TAX))
|
case (_, RegisterVariable(Register.X, _)) => List(AssemblyLine.implied(TAX))
|
||||||
@ -1421,7 +1421,7 @@ object ExpressionCompiler {
|
|||||||
def lookupFunction(ctx: CompilationContext, f: FunctionCallExpression): MangledFunction = {
|
def lookupFunction(ctx: CompilationContext, f: FunctionCallExpression): MangledFunction = {
|
||||||
val paramsWithTypes = f.expressions.map(x => getExpressionType(ctx, x) -> x)
|
val paramsWithTypes = f.expressions.map(x => getExpressionType(ctx, x) -> x)
|
||||||
ctx.env.lookupFunction(f.functionName, paramsWithTypes).getOrElse(
|
ctx.env.lookupFunction(f.functionName, paramsWithTypes).getOrElse(
|
||||||
ErrorReporting.fatal(s"Cannot find function `${f.functionName}` with given params `${paramsWithTypes.map(_._1)}`", f.position))
|
ErrorReporting.fatal(s"Cannot find function `${f.functionName}` with given params `${paramsWithTypes.map(_._1).mkString("(", ",", ")")}`", f.position))
|
||||||
}
|
}
|
||||||
|
|
||||||
def arrayBoundsCheck(ctx: CompilationContext, pointy: Pointy, register: Register.Value, index: Expression): List[AssemblyLine] = {
|
def arrayBoundsCheck(ctx: CompilationContext, pointy: Pointy, register: Register.Value, index: Expression): List[AssemblyLine] = {
|
||||||
|
@ -13,7 +13,7 @@ object UnusedFunctions extends NodeOptimization {
|
|||||||
override def optimize(nodes: List[Node], options: CompilationOptions): List[Node] = {
|
override def optimize(nodes: List[Node], options: CompilationOptions): List[Node] = {
|
||||||
val panicRequired = options.flags(CompilationFlag.CheckIndexOutOfBounds)
|
val panicRequired = options.flags(CompilationFlag.CheckIndexOutOfBounds)
|
||||||
val allNormalFunctions = nodes.flatMap {
|
val allNormalFunctions = nodes.flatMap {
|
||||||
case v: FunctionDeclarationStatement => if (v.address.isDefined || v.interrupt || v.name == "main" || panicRequired && v.name == "_panic") Nil else List(v.name)
|
case v: FunctionDeclarationStatement => if (v.address.isDefined && v.statements.isDefined || v.interrupt || v.name == "main" || panicRequired && v.name == "_panic") Nil else List(v.name)
|
||||||
case _ => Nil
|
case _ => Nil
|
||||||
}.toSet
|
}.toSet
|
||||||
val allCalledFunctions = getAllCalledFunctions(nodes).toSet
|
val allCalledFunctions = getAllCalledFunctions(nodes).toSet
|
||||||
|
@ -15,7 +15,7 @@ class TextCodec(val name: String, private val map: String, private val extra: Ma
|
|||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
List(index)
|
List(index)
|
||||||
} else {
|
} else {
|
||||||
ErrorReporting.fatal("Invalid character in string")
|
ErrorReporting.fatal("Invalid character in string", position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,26 @@ class ByteMathSuite extends FunSuite with Matchers {
|
|||||||
""".stripMargin)(_.readByte(0xc001) should equal(42))
|
""".stripMargin)(_.readByte(0xc001) should equal(42))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("LHS evaluation during in-place byte addition") {
|
||||||
|
EmuBenchmarkRun(
|
||||||
|
"""
|
||||||
|
| array output[1] @$c000
|
||||||
|
| byte call_count @$c001
|
||||||
|
| void main () {
|
||||||
|
| output[0] = 1
|
||||||
|
| output[identity(0)] += identity(1)
|
||||||
|
| }
|
||||||
|
| noinline byte identity(byte a) {
|
||||||
|
| call_count += 1
|
||||||
|
| return a
|
||||||
|
| }
|
||||||
|
""".stripMargin){m =>
|
||||||
|
m.readByte(0xc000) should equal(2)
|
||||||
|
// TODO: currently the compiler emits separate evaluations of the left hand side for reading and writing
|
||||||
|
// m.readByte(0xc001) should equal(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test("Parameter order") {
|
test("Parameter order") {
|
||||||
EmuBenchmarkRun(
|
EmuBenchmarkRun(
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user