From b9bf433308158c16e22d2cca04e9b94066b1dae2 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Wed, 24 Jun 2020 01:18:38 +0200 Subject: [PATCH] 6809: implement retun dispatch statements --- .../compiler/m6809/M6809ReturnDispatch.scala | 58 +++++++++++++++++++ .../m6809/M6809StatementCompiler.scala | 2 + .../millfork/test/ReturnDispatchSuite.scala | 6 +- 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 src/main/scala/millfork/compiler/m6809/M6809ReturnDispatch.scala diff --git a/src/main/scala/millfork/compiler/m6809/M6809ReturnDispatch.scala b/src/main/scala/millfork/compiler/m6809/M6809ReturnDispatch.scala new file mode 100644 index 00000000..e877b5c9 --- /dev/null +++ b/src/main/scala/millfork/compiler/m6809/M6809ReturnDispatch.scala @@ -0,0 +1,58 @@ +package millfork.compiler.m6809 + +import millfork.assembly.m6809.MLine +import millfork.compiler.{AbstractReturnDispatch, CompilationContext} +import millfork.env.{Constant, InitializedArray, ThingInMemory, VariableType} +import millfork.node.{Expression, M6809Register, ReturnDispatchStatement} +import millfork.output.NoAlignment + +import scala.collection.mutable + +/** + * @author Karol Stasiak + */ +object M6809ReturnDispatch extends AbstractReturnDispatch[MLine] { + override def compileImpl(ctx: CompilationContext, + stmt: ReturnDispatchStatement, + label: String, + actualMin: Int, + actualMax: Int, + paramArrays: IndexedSeq[InitializedArray], + paramMins: IndexedSeq[Int], + map: mutable.Map[Int, (Option[ThingInMemory], List[Expression])]): List[MLine] = { + import millfork.assembly.m6809.MOpcode._ + import M6809Register.{A, B, D, X} + val env = ctx.env.root + val b = env.get[VariableType]("byte") + val ctxForStoringParams = ctx.neverCheckArrayBounds + val loadIndex = M6809ExpressionCompiler.compileToX(ctx, stmt.indexer) + + val pair = stmt.params.zipWithIndex.foldLeft(List[List[MLine]]()) { (p1, p2) => + (p1, p2) match { + case (reversedResult, (paramVar, paramIndex)) => + val storeParam = M6809ExpressionCompiler.stashXIfNeeded(ctx, M6809ExpressionCompiler.storeB(ctxForStoringParams, paramVar)) + if (storeParam.exists(l => l.changesRegister(B))) { + ctx.log.error("Invalid/too complex target parameter variable", paramVar.position) + storeParam.foreach(l => ctx.log.debug(l.toString)) + } + val nextArray = (paramArrays(paramIndex).toAddress - paramMins(paramIndex)).quickSimplify + (( + MLine.indexedX(LDB, nextArray) :: + storeParam + ) :: reversedResult) + } + } + val copyParams = pair.reverse.flatten + // TODO: would it be better to use one table of words and do TFR X,D / LEAX D,X / LDX array,X ? + val jumpTableLo = InitializedArray(label + "$jl.array", None, (actualMin to actualMax).map(i => lobyte0(map(i)._1)).toList, ctx.function.declaredBank, b, b, readOnly = true, NoAlignment) + val jumpTableHi = InitializedArray(label + "$jh.array", None, (actualMin to actualMax).map(i => hibyte0(map(i)._1)).toList, ctx.function.declaredBank, b, b, readOnly = true, NoAlignment) + env.registerUnnamedArray(jumpTableLo) + env.registerUnnamedArray(jumpTableHi) + val moveOffsetToLo = (jumpTableLo.toAddress - actualMin).quickSimplify + val moveOffsetToHi = (jumpTableHi.toAddress - actualMin).quickSimplify + val loadAddressToD = List( + MLine.indexedX(LDB, moveOffsetToLo), + MLine.indexedX(LDA, moveOffsetToHi)) + loadIndex ++ copyParams ++ loadAddressToD ++ List(MLine.tfr(D, X), MLine.indexedX(JMP, 0)) + } +} diff --git a/src/main/scala/millfork/compiler/m6809/M6809StatementCompiler.scala b/src/main/scala/millfork/compiler/m6809/M6809StatementCompiler.scala index e1cdf883..97c05334 100644 --- a/src/main/scala/millfork/compiler/m6809/M6809StatementCompiler.scala +++ b/src/main/scala/millfork/compiler/m6809/M6809StatementCompiler.scala @@ -107,6 +107,8 @@ object M6809StatementCompiler extends AbstractStatementCompiler[MLine] { case None => (M6809ExpressionCompiler.compileToX(ctx, s.target) :+ MLine.indexedX(JMP, 0)) -> Nil } + case s: ReturnDispatchStatement => + M6809ReturnDispatch.compile(ctx, s) -> Nil case _ => println(statement) ctx.log.error("Not implemented yet", statement.position) diff --git a/src/test/scala/millfork/test/ReturnDispatchSuite.scala b/src/test/scala/millfork/test/ReturnDispatchSuite.scala index 3bd8e175..938010ac 100644 --- a/src/test/scala/millfork/test/ReturnDispatchSuite.scala +++ b/src/test/scala/millfork/test/ReturnDispatchSuite.scala @@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers} class ReturnDispatchSuite extends FunSuite with Matchers { test("Trivial test") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | byte output @$c000 | void main () { @@ -28,7 +28,7 @@ class ReturnDispatchSuite extends FunSuite with Matchers { } } test("Parameter test") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | array output [200] @$c000 | sbyte param @@ -74,7 +74,7 @@ class ReturnDispatchSuite extends FunSuite with Matchers { } test("Enum test") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | byte output @$c000 | enum ugly {