1
0
mirror of https://github.com/KarolS/millfork.git synced 2025-04-13 05:39:54 +00:00

6809: implement retun dispatch statements

This commit is contained in:
Karol Stasiak 2020-06-24 01:18:38 +02:00
parent b7a34457fb
commit b9bf433308
3 changed files with 63 additions and 3 deletions

View File

@ -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))
}
}

View File

@ -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)

View File

@ -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 {