diff --git a/src/main/scala/millfork/compiler/mos/BuiltIns.scala b/src/main/scala/millfork/compiler/mos/BuiltIns.scala index 72f85263..1a6122a6 100644 --- a/src/main/scala/millfork/compiler/mos/BuiltIns.scala +++ b/src/main/scala/millfork/compiler/mos/BuiltIns.scala @@ -73,22 +73,35 @@ object BuiltIns { } case FunctionCallExpression(name, List(param)) if env.maybeGet[Type](name).isDefined => return simpleOperation(opcode, ctx, param, indexChoice, preserveA, commutative, decimal) - case _: FunctionCallExpression | _:SumExpression if commutative => + case _: FunctionCallExpression | _: SumExpression if commutative => // TODO: is it ok? - if (ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes)) { - return List(AssemblyLine.implied(PHA)) ++ MosExpressionCompiler.compile(ctx.addStack(1), source, Some(b -> RegisterVariable(MosRegister.A, b)), NoBranching) ++ wrapInSedCldIfNeeded(decimal, List( + if (ctx.options.zpRegisterSize >= 1) { + val reg = ctx.env.get[ThingInMemory]("__reg") + return List(AssemblyLine.implied(PHA)) ++ + MosExpressionCompiler.compileToA(ctx, source) ++ + List(AssemblyLine.zeropage(STA, reg), AssemblyLine.implied(PLA)) ++ + wrapInSedCldIfNeeded(decimal, List(AssemblyLine.zeropage(opcode, reg))) + } else if (ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes)) { + return List(AssemblyLine.implied(PHA)) ++ MosExpressionCompiler.compileToA(ctx.addStack(1), source) ++ wrapInSedCldIfNeeded(decimal, List( AssemblyLine.stackRelative(opcode, 1), AssemblyLine.implied(PHX))) } else { - return List(AssemblyLine.implied(PHA)) ++ MosExpressionCompiler.compile(ctx.addStack(1), source, Some(b -> RegisterVariable(MosRegister.A, b)), NoBranching) ++ wrapInSedCldIfNeeded(decimal, List( + return List(AssemblyLine.implied(PHA)) ++ MosExpressionCompiler.compileToA(ctx.addStack(1), source) ++ wrapInSedCldIfNeeded(decimal, List( AssemblyLine.implied(TSX), AssemblyLine.absoluteX(opcode, 0x101), AssemblyLine.implied(INX), AssemblyLine.implied(TXS))) // this TXS is fine, it won't appear in 65816 code } case _ => - ctx.log.error("Right-hand-side expression is too complex", source.position) - return Nil + if (ctx.options.zpRegisterSize < 1) { + ctx.log.error("Right-hand-side expression requires a zero-page register", source.position) + return Nil + } + val reg = ctx.env.get[ThingInMemory]("__reg") + return List(AssemblyLine.implied(PHA)) ++ + MosExpressionCompiler.compileToA(ctx, source) ++ + List(AssemblyLine.zeropage(STA, reg), AssemblyLine.implied(PLA)) ++ + wrapInSedCldIfNeeded(decimal, List(AssemblyLine.zeropage(opcode, reg))) } } { const => diff --git a/src/test/scala/millfork/test/ByteMathSuite.scala b/src/test/scala/millfork/test/ByteMathSuite.scala index bb548d44..03f88bee 100644 --- a/src/test/scala/millfork/test/ByteMathSuite.scala +++ b/src/test/scala/millfork/test/ByteMathSuite.scala @@ -22,6 +22,24 @@ class ByteMathSuite extends FunSuite with Matchers with AppendedClues { """.stripMargin)(_.readByte(0xc000) should equal(2)) } + test("Complex expression 2") { + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)( + """ + | byte output @$c000 + | void main () { + | output = 50 + | f() + | } + | noinline void f() { + | byte a + | a = g() + | output -= a >> 1 + | } + | noinline byte g() { return 3 } + | + """.stripMargin)(_.readByte(0xc000) should equal(49)) + } + test("Byte addition") { EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)( """