diff --git a/src/main/scala/millfork/assembly/m6809/MLine.scala b/src/main/scala/millfork/assembly/m6809/MLine.scala index a2b863b7..2a68f3d0 100644 --- a/src/main/scala/millfork/assembly/m6809/MLine.scala +++ b/src/main/scala/millfork/assembly/m6809/MLine.scala @@ -38,6 +38,8 @@ object MLine { def tfr(source: M6809Register.Value, target: M6809Register.Value): MLine = MLine(TFR, TwoRegisters(source, target), Constant.Zero) + def exg(source: M6809Register.Value, target: M6809Register.Value): MLine = MLine(EXG, TwoRegisters(source, target), Constant.Zero) + def pp(opcode: MOpcode.Value, registers: M6809Register.Value*): MLine = MLine(opcode, RegisterSet(registers.toSet), Constant.Zero) def indexedS(opcode: MOpcode.Value, offset: Int = 0): MLine = @@ -79,12 +81,12 @@ object MLine { def variable(ctx: CompilationContext, opcode : MOpcode.Value, variable: Variable, offset: Int = 0): MLine = { variable match { - case v: VariableInMemory => MLine.absolute(opcode, v.toAddress) + case v: VariableInMemory => MLine.absolute(opcode, v.toAddress + offset) case v: StackVariable => val size = variable.typ.size - if (ctx.options.flag(CompilationFlag.UseUForStack)) MLine(opcode, Indexed(M6809Register.U, indirect = false), NumericConstant(v.baseOffset, size)) - else if (ctx.options.flag(CompilationFlag.UseYForStack)) MLine(opcode, Indexed(M6809Register.Y, indirect = false), NumericConstant(v.baseOffset, size)) - else MLine(opcode, Indexed(M6809Register.S, indirect = false), NumericConstant(v.baseOffset + ctx.extraStackOffset, size)) + if (ctx.options.flag(CompilationFlag.UseUForStack)) MLine(opcode, Indexed(M6809Register.U, indirect = false), NumericConstant(v.baseOffset + offset, size)) + else if (ctx.options.flag(CompilationFlag.UseYForStack)) MLine(opcode, Indexed(M6809Register.Y, indirect = false), NumericConstant(v.baseOffset + offset, size)) + else MLine(opcode, Indexed(M6809Register.S, indirect = false), NumericConstant(v.baseOffset + ctx.extraStackOffset + offset, size)) case _ => ??? } } @@ -177,9 +179,9 @@ case class MLine(opcode: MOpcode.Value, addrMode: MAddrMode, parameter: Constant case (EXG, TwoRegisters(r1, r2)) => overlaps(r1) || overlaps(r2) case (op, _) if MOpcode.ChangesAAlways(op) => overlaps(A) || addrMode.changesRegister(reg) case (op, _) if MOpcode.ChangesBAlways(op) => overlaps(B) || addrMode.changesRegister(reg) - case (LDA, _) => overlaps(A) || addrMode.changesRegister(reg) - case (LDB, _) => overlaps(B) || addrMode.changesRegister(reg) - case (LDD, _) => overlaps(D) || addrMode.changesRegister(reg) + case (LDA | ANDA | ADDA | ADCA | SUBA | SBCA | EORA | ORA | BITA, _) => overlaps(A) || addrMode.changesRegister(reg) + case (LDB | ANDB | ADDB | ADCB | SUBB | SBCB | EORB | ORB | BITB, _) => overlaps(B) || addrMode.changesRegister(reg) + case (LDD | ADDD | SUBD, _) => overlaps(D) || addrMode.changesRegister(reg) case (LDU | LEAU, _) => reg == U || addrMode.changesRegister(reg) case (LDS | LEAS, _) => reg == S || addrMode.changesRegister(reg) case (LDX | LEAX, _) => reg == X || addrMode.changesRegister(reg) @@ -187,10 +189,17 @@ case class MLine(opcode: MOpcode.Value, addrMode: MAddrMode, parameter: Constant case (MUL, _) => overlaps(D) case (ABX, _) => reg == X case (NOP | SWI | SWI2 | SWI3 | SYNC, _) => false - case _ => true // TODO + case (STA | STB | STD | STS | STU | STX | STY, _) => false + case (SEX | DAA, _) => overlaps(A) + case (JSR | SWI | SWI2 | SWI3, _) => true + case _ => addrMode.changesRegister(reg) } } + def changesCarryFlag: Boolean = !MOpcode.PreservesC(opcode) + + + def readsRegister(reg: M6809Register.Value): Boolean = { import M6809Register._ def overlaps(other: M6809Register.Value): Boolean = { diff --git a/src/main/scala/millfork/assembly/m6809/MOpcode.scala b/src/main/scala/millfork/assembly/m6809/MOpcode.scala index d1ddec0b..bbc2a5d1 100644 --- a/src/main/scala/millfork/assembly/m6809/MOpcode.scala +++ b/src/main/scala/millfork/assembly/m6809/MOpcode.scala @@ -46,7 +46,6 @@ object MOpcode extends Enumeration { val ChangesAAlways: Set[MOpcode.Value] = Set(ADDA, ADCA, SUBA, SBCA, ANDA, ORA, EORA, SEX, DAA) val ChangesBAlways: Set[MOpcode.Value] = Set(ADDB, ADCB, SUBB, SBCB, ANDB, ORB, EORB) val ChangesDAlways: Set[MOpcode.Value] = Set(ADDD, SUBD, ANDB, ORB, EORB) - val ChangesCFAlways: Set[MOpcode.Value] = Set(ADDD, SUBD, ANDB, ORB, EORB) val ReadsAAlways: Set[MOpcode.Value] = Set(ADDD, SUBD, ANDB, ORB, EORB) val AccessesWordInMemory: Set[MOpcode.Value] = Set(ADDD, SUBD, LDD, STD, LDX, LDY, LDU, LDS, STX, STY, STU, STS, CMPD, CMPX, CMPY, CMPU, CMPS) val AllLinear: Set[MOpcode.Value] = Set( @@ -78,6 +77,15 @@ object MOpcode extends Enumeration { CMPA, CMPB, CMPD, CMPX, CMPY, CMPU, CMPS, MUL, ) + val PreservesC: Set[MOpcode.Value] = Set( + ANDA, ANDB, BITA, BITB, DEC, EXG, INC, + LDA, LDB, LDD, LDX, LDY, LDU, LDS, + LEAS, LEAX, LEAY, LEAU, + NOP, ORA, ORB, + PSHS, PSHU, PULS, PULU, + STA, STB, STD, STX, STY, STS, STU, + TFR, TST + ) // The following are incomplete: val ChangesN: Set[MOpcode.Value] = Set( CWAI, ORCC, ANDCC, diff --git a/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala b/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala index 1937a4e4..07753cce 100644 --- a/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala @@ -1,11 +1,13 @@ package millfork.compiler.m6809 +import java.util.concurrent.AbstractExecutorService + import millfork.CompilationFlag import millfork.assembly.m6809.{DAccumulatorIndexed, Immediate, Indexed, InherentB, MLine, MLine0, MOpcode, RegisterSet, TwoRegisters} import millfork.compiler.{AbstractExpressionCompiler, BranchIfFalse, BranchIfTrue, BranchSpec, ComparisonType, CompilationContext, NoBranching} import millfork.node.{DerefExpression, Expression, FunctionCallExpression, GeneratedConstantExpression, IndexedExpression, LhsExpression, LiteralExpression, M6809Register, SeparateBytesExpression, SumExpression, VariableExpression} import millfork.assembly.m6809.MOpcode._ -import millfork.env.{AssemblyOrMacroParamSignature, BuiltInBooleanType, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, FlagBooleanType, FunctionInMemory, FunctionPointerType, Label, M6809RegisterVariable, MacroFunction, MathOperator, MemoryAddressConstant, MemoryVariable, NonFatalCompilationException, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, ThingInMemory, Type, Variable, VariableInMemory, VariablePointy} +import millfork.env.{AssemblyOrMacroParamSignature, BuiltInBooleanType, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, FlagBooleanType, FunctionInMemory, FunctionPointerType, Label, M6809RegisterVariable, MacroFunction, MathOperator, MemoryAddressConstant, MemoryVariable, NonFatalCompilationException, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, StructureConstant, ThingInMemory, Type, Variable, VariableInMemory, VariablePointy} import scala.collection.GenTraversableOnce @@ -357,7 +359,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { size match { case 1 => M6809Buitins.perform8BitInPlace(ctx, l, r, ADDB) case 2 => M6809Buitins.perform16BitInPlace(ctx, l, r, ADDD, commutative = true) - case _ => ctx.log.error("Long addition not implemented yet", fce.position); Nil + case _ => M6809LargeBuiltins.modifyInPlaceViaX(ctx, l, r, ADDB) } case "+'=" => val (l, r, size) = assertArithmeticAssignmentLike(ctx, params) @@ -372,15 +374,14 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { case (true, false) => lc ++ rc ++ add case (true, true) => rc ++ stashAIfNeeded(ctx, lc) ++ add } - case 2 => ??? - case _ => ??? + case _ => M6809LargeBuiltins.modifyInPlaceViaX(ctx, l, r, ADDA) } case "-=" => val (l, r, size) = assertArithmeticAssignmentLike(ctx, params) size match { case 1 => M6809Buitins.perform8BitInPlace(ctx, l, r, SUBB) case 2 => M6809Buitins.perform16BitInPlace(ctx, l, r, SUBD, commutative = false) - case _ => ??? + case _ => M6809LargeBuiltins.modifyInPlaceViaX(ctx, l, r, SUBB) } case "-'=" => val (l, r, size) = assertArithmeticAssignmentLike(ctx, params) @@ -390,8 +391,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { val rc = compileToB(ctx, r) lc ++ List(MLine.pp(PSHS, M6809Register.B)) ++ rc ++ List(MLine.pp(PSHS, M6809Register.B), MLine.immediate(LDA, 0x9a), MLine.accessAndPullS(SUBA), MLine.accessAndPullS(ADDA), MLine.inherent(DAA), MLine.indexedX(STA, 0)) - case 2 => ??? - case _ => ??? + case _ => M6809LargeBuiltins.modifyInPlaceViaX(ctx, l, r, SUBA) } case "*=" => val (l, r, size) = assertArithmeticAssignmentLike(ctx, params) @@ -417,21 +417,21 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { size match { case 1 => M6809Buitins.perform8BitInPlace(ctx, l, r, ANDB) case 2 => M6809Buitins.perform16BitInPlace(ctx, l, r, ANDA, ANDB, commutative = true) - case _ => ??? + case _ => M6809LargeBuiltins.modifyInPlaceViaX(ctx, l, r, ANDB) } case "|=" => val (l, r, size) = assertArithmeticAssignmentLike(ctx, params) size match { case 1 => M6809Buitins.perform8BitInPlace(ctx, l, r, ORB) case 2 => M6809Buitins.perform16BitInPlace(ctx, l, r, ORA, ORB, commutative = true) - case _ => ??? + case _ => M6809LargeBuiltins.modifyInPlaceViaX(ctx, l, r, ORB) } case "^=" => val (l, r, size) = assertArithmeticAssignmentLike(ctx, params) size match { case 1 => M6809Buitins.perform8BitInPlace(ctx, l, r, EORB) case 2 => M6809Buitins.perform16BitInPlace(ctx, l, r, EORA, EORB, commutative = true) - case _ => ??? + case _ => M6809LargeBuiltins.modifyInPlaceViaX(ctx, l, r, EORB) } case "<<=" => val (l, r, size) = assertArithmeticAssignmentLike(ctx, params) @@ -441,6 +441,8 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { handleInPlaceModification(ctx, l, 1, M6809Buitins.compileByteShiftForB(ctx, r, left = true)) case 2 => handleInPlaceModification(ctx, l, 2, M6809Buitins.compileWordShiftForD(ctx, r, left = true)) + case _ => + M6809LargeBuiltins.compileShiftInPlace(ctx, size, l, r, left = true) } case "<<'=" => val (l, r, size) = assertArithmeticAssignmentLike(ctx, params) @@ -455,6 +457,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { size match { case 1 => handleInPlaceModification(ctx, l, 1, M6809Buitins.compileByteShiftForB(ctx, r, left = false)) case 2 => handleInPlaceModification(ctx, l, 2, M6809Buitins.compileWordShiftForD(ctx, r, left = false)) + case _ => M6809LargeBuiltins.compileShiftInPlace(ctx, size, l, r, left = false) } case ">>'=" => ??? case ">>>>=" => ??? @@ -499,7 +502,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { case 2 => compileToD(ctx, paramExpr) ++ storeD(callCtx, VariableExpression(paramVar.name + "`aa")) case _ => - ??? + M6809LargeBuiltins.storeLarge(callCtx, VariableExpression(paramVar.name + "`aa"), paramExpr) } } case AssemblyOrMacroParamSignature(signature) => @@ -647,6 +650,11 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { else lines } + def stashCarryIfNeeded(ctx: CompilationContext, lines: List[MLine]): List[MLine] = { + if (lines.exists(_.changesCarryFlag)) MLine.pp(PSHS, M6809Register.CC) :: (lines :+ MLine.pp(PULS, M6809Register.CC)) + else lines + } + def storeA(ctx: CompilationContext, target: LhsExpression): List[MLine] = store8(ctx, target, stashAIfNeeded, STA) def storeB(ctx: CompilationContext, target: LhsExpression): List[MLine] = store8(ctx, target, stashBIfNeeded, STB) @@ -839,4 +847,74 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { } false } + + def compileToByteReads(ctx: CompilationContext, source: Expression, targetSize: Int): List[List[MLine]] = { + val sourceType = AbstractExpressionCompiler.getExpressionType(ctx, source) + ctx.env.eval(source) match { + case Some(const) => + List.tabulate(targetSize)(i => List(MLine.immediate(LDB, const.subbyteBe(targetSize - 1 - i, targetSize)))) + case None => + sourceType.size match { + case 0 => ??? + case 1 => + List.tabulate(targetSize)(i => + if (sourceType.isSigned) { + if (i == 0) compileToB(ctx, source) :+ MLine.tfr(M6809Register.B, M6809Register.A) + else if (i == 1) List( + MLine.tfr(M6809Register.A, M6809Register.B), + MLine.inherent(SEX), + MLine.tfr(M6809Register.B, M6809Register.A) + ) + else List(MLine.tfr(M6809Register.A, M6809Register.B)) + } else { + if (i == 0) compileToB(ctx, source) + else List(MLine.immediate(LDB, 0)) + } + ) + case 2 => + List.tabulate(targetSize)(i => + if (sourceType.isSigned) { + if (i == 0) compileToD(ctx, source) + else if (i == 1) List(MLine.tfr(M6809Register.A, M6809Register.B)) + else if (i == 2) { + if (targetSize > 3) List( + MLine.tfr(M6809Register.A, M6809Register.B), + MLine.inherent(SEX), + MLine.tfr(M6809Register.B, M6809Register.A) + ) else List( + MLine.tfr(M6809Register.A, M6809Register.B), + MLine.inherent(SEX) + ) + } else List(MLine.tfr(M6809Register.A, M6809Register.B)) + } else { + if (i == 0) compileToD(ctx, source) + else if (i == 1) List(MLine.tfr(M6809Register.A, M6809Register.B)) + else List(MLine.immediate(LDB, 0)) + } + ) + case _ => + source match { + case LiteralExpression(value, size) => + val const = NumericConstant(value, size) + List.tabulate(targetSize)(i => List(MLine.immediate(LDB, const.subbyte(i)))) + case GeneratedConstantExpression(const, _) => + List.tabulate(targetSize)(i => List(MLine.immediate(LDB, const.subbyteBe(targetSize - 1 - i, targetSize)))) + case VariableExpression(name) => + val v = ctx.env.get[Variable](name) + List.tabulate(targetSize)(i => List(if (i < v.typ.size) MLine.variable(ctx, LDB, v, v.typ.size - 1 - i) else MLine.immediate(LDB, 0))) + case e:FunctionCallExpression => + ctx.env.maybeGet[NormalFunction](e.functionName) match { + case Some(function) => + val load = M6809ExpressionCompiler.compile(ctx, e, MExpressionTarget.NOTHING) + val v = ctx.env.get[VariableInMemory](function.name + ".return") + List.tabulate(targetSize) { i => + if (i == 0) load :+ MLine.variable(ctx, LDB, v, v.typ.size - 1 - i) + else List(if (i < v.typ.size) MLine.variable(ctx, LDB, v, v.typ.size - 1 - i) else MLine.immediate(LDB, 0)) + } + case _ => ??? + } + } + } + } + } } diff --git a/src/main/scala/millfork/compiler/m6809/M6809LargeBuiltins.scala b/src/main/scala/millfork/compiler/m6809/M6809LargeBuiltins.scala new file mode 100644 index 00000000..ae7ca9f9 --- /dev/null +++ b/src/main/scala/millfork/compiler/m6809/M6809LargeBuiltins.scala @@ -0,0 +1,238 @@ +package millfork.compiler.m6809 + +import millfork.assembly.m6809.{Immediate, MLine, MLine0, MOpcode, TwoRegisters} +import millfork.compiler.{AbstractExpressionCompiler, CompilationContext} +import millfork.node.{Expression, LhsExpression, M6809Register} +import millfork.assembly.m6809.MOpcode._ +import millfork.env.{Constant, NumericConstant} + +import scala.collection.GenTraversableOnce +import scala.collection.mutable.ListBuffer + +/** + * @author Karol Stasiak + */ +object M6809LargeBuiltins { + + def compileShiftInPlace(ctx: CompilationContext, size: Int, target: LhsExpression, shiftValue: Expression, left: Boolean): List[MLine] = { + val (targetAddr, targetInit): (Option[Constant], List[MLine]) = M6809ExpressionCompiler.compileAddressToX(ctx, target) match { + case List(MLine(LDX, Immediate, addr, _, _)) => Some(addr) -> Nil + case xs => None -> xs + } + val oneShift = if (left) { + targetAddr match { + case Some(addr) => + List.tabulate(size)(i => MLine.absolute(if (i == 0) ASL else ROL, addr + (size - 1 - i))) + case None => + List.tabulate(size)(i => MLine.indexedX(if (i == 0) ASL else ROL, size - 1 - i)) + } + } else { + targetAddr match { + case Some(addr) => + List.tabulate(size)(i => MLine.absolute(if (i == 0) LSR else ROR, addr + i)) + case None => + List.tabulate(size)(i => MLine.indexedX(if (i == 0) LSR else ROR, i)) + } + } + targetInit ++ (M6809ExpressionCompiler.compileToB(ctx, shiftValue) match { + case List(MLine0(LDB, Immediate, NumericConstant(n, _))) if n >= 0 && (n - 1) * size < 4 => + List.fill(n.toInt)(oneShift).flatten + case xs@List(MLine0(LDB, Immediate, c)) if c.isProvablyGreaterOrEqualThan(1) => + val label = ctx.nextLabel("sr") + xs ++ List(MLine.label(label)) ++ oneShift ++ List(MLine.inherentB(DEC), MLine.shortBranch(BNE, label)) + case xs => + val loop = ctx.nextLabel("sr") + val skip = ctx.nextLabel("ss") + M6809ExpressionCompiler.stashXIfNeeded(ctx, xs) ++ List( + MLine.label(loop), + MLine.inherentB(DEC), + MLine.immediate(CMPB, -1), + MLine.shortBranch(BEQ, skip)) ++ oneShift ++ List( + MLine.shortBranch(BRA, loop), + MLine.label(skip) + ) + }) + } + + def storeLarge(ctx: CompilationContext, target: LhsExpression, source: Expression): List[MLine] = { + val byteCount = AbstractExpressionCompiler.getExpressionType(ctx, target).size + val byteLoads = M6809ExpressionCompiler.compileToByteReads(ctx, source, byteCount) + val (targetAddr, targetInit): (Option[Constant], List[MLine]) = M6809ExpressionCompiler.compileAddressToX(ctx, target) match { + case List(MLine(LDX, Immediate, addr, _, _)) => Some(addr) -> Nil + case xs => None -> xs + } + // TODO: use loop for very large structures + // TODO: use D to speed up certain loads + targetInit ++ byteLoads.zipWithIndex.flatMap{ case (loadByte, ix) => + M6809ExpressionCompiler.stashXIfNeeded(ctx, loadByte) :+ ( targetAddr match { + case Some(addr) => MLine.absolute(STB, addr + (byteCount - 1 - ix)) + case None => MLine.indexedX(STB, byteCount - 1 - ix) + } ) + } + } + + def convertToLda(ldb: List[MLine]): List[MLine] = { + ldb match { + case List(l@MLine0(LDB, _, _)) => List(l.copy(opcode = LDA)) + case List(l@MLine0(TFR, TwoRegisters(M6809Register.A, M6809Register.B), _)) => List(l.copy(addrMode = TwoRegisters(M6809Register.B, M6809Register.A))) + case _ => MLine.exg(M6809Register.A, M6809Register.B) :: (ldb :+ MLine.exg(M6809Register.A, M6809Register.B)) + } + } + + def compileInc(ctx: CompilationContext, target: LhsExpression): List[MLine] = { + val sizeInBytes = AbstractExpressionCompiler.getExpressionType(ctx, target).size + val result = new ListBuffer[MLine]() + val targetAddr: Option[Constant] = M6809ExpressionCompiler.compileAddressToX(ctx, target) match { + case List(MLine(LDX, Immediate, addr, _, _)) => Some(addr) + case xs => + result ++= xs + None + } + val skipLabel = ctx.nextLabel("in") + for (i <- 0 until sizeInBytes) { + targetAddr match { + case Some(addr) => + result += MLine.absolute(INC, addr + (sizeInBytes - 1 - i)) + case None => + result += MLine.indexedX(INC, sizeInBytes - 1 - i) + } + if (i != sizeInBytes - 1) { + result += MLine.shortBranch(BNE, skipLabel) + } + } + result += MLine.label(skipLabel) + result.toList + } + + def modifyInPlaceViaX(ctx: CompilationContext, target: LhsExpression, argument: Expression, opcode: MOpcode.Value): List[MLine] = { + if (opcode == ADDB) ctx.env.eval(argument) match { + case Some(NumericConstant(1, _)) => + return compileInc(ctx, target) + case _ => + } + val sizeInBytes = AbstractExpressionCompiler.getExpressionType(ctx, target).size + val byteLoads = M6809ExpressionCompiler.compileToByteReads(ctx, argument, sizeInBytes) + val result = new ListBuffer[MLine]() + val targetAddr: Option[Constant] = M6809ExpressionCompiler.compileAddressToX(ctx, target) match { + case List(MLine(LDX, Immediate, addr, _, _)) => Some(addr) + case xs => + result ++= xs + ctx.log.error("Invalid left-hand-side expression", target.position) + None + } + var firstNonzeroByte = 0 + for (i <- 0 until sizeInBytes) { + val ldb = byteLoads(i) + val magicConstant = + ldb match { + case List(MLine0(LDB, Immediate, NumericConstant(x, _))) => Some(x.toInt & 0xff) + case _ => None + } + (opcode, magicConstant) match { + + case (ORB | EORB, Some(0)) => + // nothing + case (ANDB, Some(0xff)) => + // nothing + case (EORB, Some(0xff)) => + targetAddr match { + case Some(addr) => + result += MLine.absolute(COM, addr + (sizeInBytes - 1 - i)) + case None => + result += MLine.indexedX(COM, sizeInBytes - 1 - i) + } + + case (ADDB | SUBB | ADDA | SUBA, Some(0)) if i == firstNonzeroByte => + firstNonzeroByte = i + 1 + + case (SUBA, _) => ??? + + case (ADDA, _) if i == firstNonzeroByte => + val lda = convertToLda(ldb) + targetAddr match { + case Some(addr) => + result ++= lda + result += MLine.absolute(ADCA, addr + (sizeInBytes - 1 - i)) + result += MLine.inherent(DAA) + result += MLine.absolute(STA, addr + (sizeInBytes - 1 - i)) + case None => + result ++= M6809ExpressionCompiler.stashXIfNeeded(ctx, lda) + result += MLine.indexedX(ADCA, sizeInBytes - 1 - i) + result += MLine.inherent(DAA) + result += MLine.indexedX(STA, sizeInBytes - 1 - i) + } + + case (ADDA, _) if i != firstNonzeroByte => + val lda = convertToLda(ldb) + targetAddr match { + case Some(addr) => + result ++= M6809ExpressionCompiler.stashCarryIfNeeded(ctx, lda) + result += MLine.absolute(ADCA, addr + (sizeInBytes - 1 - i)) + result += MLine.inherent(DAA) + result += MLine.absolute(STA, addr + (sizeInBytes - 1 - i)) + case None => + result ++= M6809ExpressionCompiler.stashCarryIfNeeded(ctx, M6809ExpressionCompiler.stashXIfNeeded(ctx, lda)) + result += MLine.indexedX(ADCA, sizeInBytes - 1 - i) + result += MLine.inherent(DAA) + result += MLine.indexedX(STA, sizeInBytes - 1 - i) + } + + case (SUBB, _) if i == firstNonzeroByte => + targetAddr match { + case Some(addr) => + result ++= ldb + result += MLine.pp(PSHS, M6809Register.B) + result += MLine.absolute(LDB, addr + (sizeInBytes - 1 - i)) + result += MLine.accessAndPullS(SUBB) + result += MLine.absolute(STB, addr + (sizeInBytes - 1 - i)) + case None => + result ++= M6809ExpressionCompiler.stashXIfNeeded(ctx, ldb) + result += MLine.pp(PSHS, M6809Register.B) + result += MLine.indexedX(LDB, sizeInBytes - 1 - i) + result += MLine.accessAndPullS(SUBB) + result += MLine.indexedX(STB, sizeInBytes - 1 - i) + } + + case (SUBB, _) if i != firstNonzeroByte => + targetAddr match { + case Some(addr) => + result ++= M6809ExpressionCompiler.stashCarryIfNeeded(ctx, ldb) + result += MLine.pp(PSHS, M6809Register.B) + result += MLine.absolute(LDB, addr + (sizeInBytes - 1 - i)) + result += MLine.accessAndPullS(SBCB) + result += MLine.absolute(STB, addr + (sizeInBytes - 1 - i)) + case None => + result ++= M6809ExpressionCompiler.stashCarryIfNeeded(ctx, M6809ExpressionCompiler.stashXIfNeeded(ctx, ldb)) + result += MLine.pp(PSHS, M6809Register.B) + result += MLine.indexedX(LDB, sizeInBytes - 1 - i) + result += MLine.accessAndPullS(SBCB) + result += MLine.indexedX(STB, sizeInBytes - 1 - i) + } + case (ADDB, _) if i != firstNonzeroByte => + targetAddr match { + case Some(addr) => + result ++= M6809ExpressionCompiler.stashCarryIfNeeded(ctx, ldb) + result += MLine.absolute(ADCB, addr + (sizeInBytes - 1 - i)) + result += MLine.absolute(STB, addr + (sizeInBytes - 1 - i)) + case None => + result ++= M6809ExpressionCompiler.stashCarryIfNeeded(ctx, M6809ExpressionCompiler.stashXIfNeeded(ctx, ldb)) + result += MLine.indexedX(ADCB, sizeInBytes - 1 - i) + result += MLine.indexedX(STB, sizeInBytes - 1 - i) + } + case _ => + targetAddr match { + case Some(addr) => + result ++= ldb + result += MLine.absolute(opcode, addr + (sizeInBytes - 1 - i)) + result += MLine.absolute(STB, addr + (sizeInBytes - 1 - i)) + case None => + result ++= M6809ExpressionCompiler.stashXIfNeeded(ctx, ldb) + result += MLine.indexedX(opcode, sizeInBytes - 1 - i) + result += MLine.indexedX(STB, sizeInBytes - 1 - i) + } + } + } + result.toList + } + +} diff --git a/src/main/scala/millfork/compiler/m6809/M6809StatementCompiler.scala b/src/main/scala/millfork/compiler/m6809/M6809StatementCompiler.scala index 58261559..e1cdf883 100644 --- a/src/main/scala/millfork/compiler/m6809/M6809StatementCompiler.scala +++ b/src/main/scala/millfork/compiler/m6809/M6809StatementCompiler.scala @@ -33,6 +33,12 @@ object M6809StatementCompiler extends AbstractStatementCompiler[MLine] { M6809ExpressionCompiler.compile(ctx, e, MExpressionTarget.NOTHING) case 1 => M6809ExpressionCompiler.compileToB(ctx, e) case 2 => M6809ExpressionCompiler.compileToD(ctx, e) + case _ => + if (ctx.function.hasElidedReturnVariable) { + Nil + } else { + M6809LargeBuiltins.storeLarge(ctx, VariableExpression(ctx.function.name + ".return"), e) + } } } (eval ++ rts) -> Nil @@ -65,6 +71,7 @@ object M6809StatementCompiler extends AbstractStatementCompiler[MLine] { case _ => M6809ExpressionCompiler.compileToB(ctx, source) ++ M6809ExpressionCompiler.storeB(ctx, destination) } case 2 => M6809ExpressionCompiler.compileToD(ctx, source) ++ M6809ExpressionCompiler.storeD(ctx, destination) + case _ => M6809LargeBuiltins.storeLarge(ctx, destination, source) }) -> Nil case ExpressionStatement(expression) => M6809ExpressionCompiler.compile(ctx, expression, MExpressionTarget.NOTHING) -> Nil diff --git a/src/main/scala/millfork/output/CompiledMemory.scala b/src/main/scala/millfork/output/CompiledMemory.scala index e493a8da..0ec56e02 100644 --- a/src/main/scala/millfork/output/CompiledMemory.scala +++ b/src/main/scala/millfork/output/CompiledMemory.scala @@ -34,6 +34,10 @@ class MemoryBank(val index: Int, val isBigEndian: Boolean) { if (isBigEndian) readByte(addr + 3) + (readByte(addr + 2) << 8) + (readByte(addr + 1) << 16) + (readByte(addr) << 24) else readByte(addr) + (readByte(addr + 1) << 8) + (readByte(addr + 2) << 16) + (readByte(addr + 3) << 24) + def readLongLong(addr: Int): Long = + if (isBigEndian) readLong(addr).toLong.<<(32) + readLong(addr + 4).&(1L.<<(32).-(1)) + else readLong(addr + 4).toLong.<<(32) + readLong(addr).&(1L.<<(32).-(1)) + def readWord(addrHi: Int, addrLo: Int): Int = readByte(addrLo) + (readByte(addrHi) << 8) val output: Array[Byte] = Array.fill[Byte](1 << 16)(0) diff --git a/src/test/scala/millfork/test/FarwordTest.scala b/src/test/scala/millfork/test/FarwordTest.scala index 908f8fbe..4d575727 100644 --- a/src/test/scala/millfork/test/FarwordTest.scala +++ b/src/test/scala/millfork/test/FarwordTest.scala @@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers} class FarwordTest extends FunSuite with Matchers { test("Int24 assignment") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output3 @$c000 | int24 output2 @$c004 @@ -29,7 +29,7 @@ class FarwordTest extends FunSuite with Matchers { } } test("Int24 assignment 2") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output3 @$c000 | int24 output2 @$c004 @@ -48,12 +48,12 @@ class FarwordTest extends FunSuite with Matchers { """.stripMargin) { m => m.readMedium(0xc000) should equal(0x23344) m.readMedium(0xc004) should equal(0x7788) - m.readMedium(0xc008) should equal(0x55) + m.readWord(0xc008) should equal(0x55) } } test("Int24 assignment 3") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output0 @$c000 | int24 output1 @$c003 @@ -70,7 +70,7 @@ class FarwordTest extends FunSuite with Matchers { } } test("Int24 addition") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output @$c000 | void main () { @@ -90,7 +90,7 @@ class FarwordTest extends FunSuite with Matchers { } } test("Int24 addition 2") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output @$c000 | void main () { @@ -104,7 +104,7 @@ class FarwordTest extends FunSuite with Matchers { } } test("Int24 subtraction") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output @$c000 | void main () { @@ -124,7 +124,7 @@ class FarwordTest extends FunSuite with Matchers { } } test("Int24 subtraction 2") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output @$c000 | void main () { @@ -138,7 +138,7 @@ class FarwordTest extends FunSuite with Matchers { } } test("Int24 subtraction 3") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output @$c000 | void main () { @@ -158,7 +158,7 @@ class FarwordTest extends FunSuite with Matchers { } test("Int24 AND") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output @$c000 | void main () { @@ -178,7 +178,7 @@ class FarwordTest extends FunSuite with Matchers { } test("Int24 INC/DEC") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int24 output0 @$c000 | int24 output1 @$c004 diff --git a/src/test/scala/millfork/test/LongTest.scala b/src/test/scala/millfork/test/LongTest.scala index b03952fa..334d0524 100644 --- a/src/test/scala/millfork/test/LongTest.scala +++ b/src/test/scala/millfork/test/LongTest.scala @@ -28,7 +28,7 @@ class LongTest extends FunSuite with Matchers { } test("Long assignment") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output4 @$c000 | long output2 @$c004 @@ -47,7 +47,7 @@ class LongTest extends FunSuite with Matchers { } } test("Long assignment 2") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output4 @$c000 | long output2 @$c004 @@ -66,11 +66,11 @@ class LongTest extends FunSuite with Matchers { """.stripMargin) { m => m.readLong(0xc000) should equal(0x11223344) m.readLong(0xc004) should equal(0x7788) - m.readLong(0xc008) should equal(0x55) + m.readWord(0xc008) should equal(0x55) } } test("Long addition") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output @$c000 | void main () { @@ -90,7 +90,7 @@ class LongTest extends FunSuite with Matchers { } } test("Long addition 2") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output @$c000 | void main () { @@ -104,7 +104,7 @@ class LongTest extends FunSuite with Matchers { } } test("Long addition 3") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output @$c000 | void main () { @@ -138,7 +138,7 @@ class LongTest extends FunSuite with Matchers { } } test("Long subtraction") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output @$c000 | void main () { @@ -158,7 +158,7 @@ class LongTest extends FunSuite with Matchers { } } test("Long subtraction 2") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output @$c000 | void main () { @@ -172,7 +172,7 @@ class LongTest extends FunSuite with Matchers { } } test("Long subtraction 3") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output @$c000 | void main () { @@ -192,7 +192,7 @@ class LongTest extends FunSuite with Matchers { } test("Long AND") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output @$c000 | void main () { @@ -212,7 +212,7 @@ class LongTest extends FunSuite with Matchers { } test("Long INC/DEC") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output0 @$c000 | long output1 @$c004 @@ -252,7 +252,7 @@ class LongTest extends FunSuite with Matchers { } test("Returning long") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output @$c000 | void main () { @@ -267,7 +267,7 @@ class LongTest extends FunSuite with Matchers { } test("Various combinations involving promotions") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | long output0 @$c000 | long output1 @$c004 @@ -329,7 +329,7 @@ class LongTest extends FunSuite with Matchers { } test("Larger than long") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)( + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)( """ | int64 output0 @$c000 | int64 output1 @$c008 @@ -364,18 +364,11 @@ class LongTest extends FunSuite with Matchers { | return param | } """.stripMargin) { m => - m.readLong(0xc000) should equal(0x91929394) - m.readLong(0xc008) should equal(0x929394) - m.readLong(0xc010) should equal(0x9394) - m.readLong(0xc018) should equal(0x94) - - m.readLong(0xc004) should equal(0) - m.readLong(0xc00c) should equal(0) - m.readLong(0xc014) should equal(0) - m.readLong(0xc01c) should equal(0) - - m.readLong(0xc020) should equal(0x91929394) - m.readLong(0xc024) should equal(0x01010101) + m.readLongLong(0xc000) should equal(0x91929394L) + m.readLongLong(0xc008) should equal(0x929394L) + m.readLongLong(0xc010) should equal(0x9394L) + m.readLongLong(0xc018) should equal(0x94L) + m.readLongLong(0xc020) should equal(0x0101010191929394L) } } } diff --git a/src/test/scala/millfork/test/SignExtensionSuite.scala b/src/test/scala/millfork/test/SignExtensionSuite.scala index bdc65cc8..2c4bd6af 100644 --- a/src/test/scala/millfork/test/SignExtensionSuite.scala +++ b/src/test/scala/millfork/test/SignExtensionSuite.scala @@ -33,7 +33,7 @@ class SignExtensionSuite extends FunSuite with Matchers { """.stripMargin){m => m.readWord(0xc000) should equal(0xfffe)} } test("Sbyte to Long") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(""" + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(""" | long output @$c000 | void main () { | output = 421 @@ -46,7 +46,7 @@ class SignExtensionSuite extends FunSuite with Matchers { } test("Optimize pointless sign extension") { - EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(""" + EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(""" | array output [10] @$c000 | word w | void main () { @@ -66,7 +66,7 @@ class SignExtensionSuite extends FunSuite with Matchers { | return 5 | } """.stripMargin){m => - m.readWord(0xc000) should equal(440) + m.readWord(0xc001, 0xc000) should equal(440) } } @@ -111,7 +111,7 @@ class SignExtensionSuite extends FunSuite with Matchers { } test("Check multilayered conversions of signed and unsigned types") { - EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)( + EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)( """ |long output @$c000 |noinline sbyte f() = $FE @@ -140,7 +140,7 @@ class SignExtensionSuite extends FunSuite with Matchers { } test("Signed16 to int32 extension") { - EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)( + EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)( """ |int32 output @$c000 | @@ -156,7 +156,7 @@ class SignExtensionSuite extends FunSuite with Matchers { } test("Signed16 to int32 extension 2") { - EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)( + EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)( """ |int32 output @$c000 | diff --git a/src/test/scala/millfork/test/emu/Settings.scala b/src/test/scala/millfork/test/emu/Settings.scala index d77d89f6..1dd59051 100644 --- a/src/test/scala/millfork/test/emu/Settings.scala +++ b/src/test/scala/millfork/test/emu/Settings.scala @@ -50,7 +50,7 @@ object Settings { /** * Should the Motorola 6809 tests be enabled? - * Motorola 6809 emulation is not yet implemented, so keep this false for the time being. + * Motorola 6809 emulation is currently under development and more and more tests are ran against it. */ val enableMotorola6809Tests: Boolean = true