mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-06 20:37:12 +00:00
6809: Various improvements
This commit is contained in:
parent
c61d044226
commit
f08caa0b7a
@ -3,7 +3,7 @@ package millfork.assembly.m6809
|
||||
import millfork.CompilationFlag
|
||||
import millfork.assembly.{AbstractCode, Elidability, SourceLine}
|
||||
import millfork.compiler.CompilationContext
|
||||
import millfork.env.{Constant, Label, MemoryVariable, NumericConstant, StackVariable, Variable, VariableInMemory}
|
||||
import millfork.env.{Constant, Label, MemoryVariable, NumericConstant, StackVariable, ThingInMemory, Variable, VariableInMemory}
|
||||
import millfork.node.{M6809Register, Position}
|
||||
|
||||
/**
|
||||
@ -56,6 +56,8 @@ object MLine {
|
||||
|
||||
def absolute(opcode: MOpcode.Value, param: Constant): MLine = MLine(opcode, Absolute(false), param)
|
||||
|
||||
def absolute(opcode: MOpcode.Value, param: ThingInMemory): MLine = MLine(opcode, Absolute(false), param.toAddress)
|
||||
|
||||
//def userstack(opcode: MOpcode.Value, offset: Int): MLine = MLine(opcode, Indexed(M6809Register.U, indirect = false), Constant(offset))
|
||||
|
||||
def variablestack(ctx: CompilationContext, opcode: MOpcode.Value, offset: Int): MLine = {
|
||||
@ -112,12 +114,12 @@ case class MLine(opcode: MOpcode.Value, addrMode: MAddrMode, parameter: Constant
|
||||
case Absolute(true) => s" [$parameter]"
|
||||
case Indexed(base, false) => s" $parameter,$base"
|
||||
case Indexed(base, true) => s" [$parameter,$base]"
|
||||
case DAccumulatorIndexed(base, false) => " D,$base"
|
||||
case DAccumulatorIndexed(base, true) => " [D,$base]"
|
||||
case AAccumulatorIndexed(base, false) => " A,$base"
|
||||
case AAccumulatorIndexed(base, true) => " [A,$base]"
|
||||
case BAccumulatorIndexed(base, false) => " B,$base"
|
||||
case BAccumulatorIndexed(base, true) => " [B,$base]"
|
||||
case DAccumulatorIndexed(base, false) => s" D,$base"
|
||||
case DAccumulatorIndexed(base, true) => s" [D,$base]"
|
||||
case AAccumulatorIndexed(base, false) => s" A,$base"
|
||||
case AAccumulatorIndexed(base, true) => s" [A,$base]"
|
||||
case BAccumulatorIndexed(base, false) => s" B,$base"
|
||||
case BAccumulatorIndexed(base, true) => s" [B,$base]"
|
||||
case PreDecremented(base, 1, false) => s" ,-$base"
|
||||
case PreDecremented(base, 2, false) => s" ,--$base"
|
||||
case PreDecremented(base, 1, true) => s" [-$base]"
|
||||
@ -146,8 +148,8 @@ case class MLine(opcode: MOpcode.Value, addrMode: MAddrMode, parameter: Constant
|
||||
}
|
||||
import MOpcode._
|
||||
(opcode, addrMode) match {
|
||||
case (_, InherentA) => reg == A
|
||||
case (_, InherentB) => reg == B
|
||||
case (_, InherentA) => overlaps(A)
|
||||
case (_, InherentB) => overlaps(B)
|
||||
case (PULU, set:RegisterSet) => reg == U || set.contains(reg)
|
||||
case (PULS, set:RegisterSet) => reg == S || set.contains(reg)
|
||||
case (PSHS, _) => reg == U
|
||||
|
@ -34,6 +34,26 @@ object M6809Buitins {
|
||||
}
|
||||
}
|
||||
|
||||
def perform16BitInPlace(ctx: CompilationContext, l: LhsExpression, r: Expression, opcode: MOpcode.Value, commutative: Boolean): List[MLine] = {
|
||||
val lc = M6809ExpressionCompiler.compileToD(ctx, l)
|
||||
val rc = M6809ExpressionCompiler.compileToD(ctx, r)
|
||||
(lc, rc) match {
|
||||
case (List(ldl@MLine0(LDD, Absolute(false), _)), _) if opcode != SUBD =>
|
||||
rc ++ List(ldl.copy(opcode = opcode), ldl.copy(opcode = STD))
|
||||
case (_, List(ldr@MLine0(LDD, Absolute(false), _))) if lc.last.opcode == LDD =>
|
||||
lc ++ List(ldr.copy(opcode = opcode), lc.last.copy(opcode = STD))
|
||||
case _ if lc.last.opcode == LDD && commutative =>
|
||||
// TODO: preserve X?
|
||||
lc ++ List(MLine.pp(PSHS, M6809Register.D)) ++ rc ++ List(MLine.accessAndPullSTwice(opcode), lc.last.copy(opcode = STD))
|
||||
case _ if lc.last.opcode == LDD =>
|
||||
// TODO: preserve X?
|
||||
rc ++ List(MLine.pp(PSHS, M6809Register.D)) ++ lc ++ List(MLine.accessAndPullSTwice(opcode), lc.last.copy(opcode = STD))
|
||||
case _ =>
|
||||
println(lc)
|
||||
???
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def split(ctx: CompilationContext, expr: SumExpression): (Constant, List[(Boolean, Expression)]) = {
|
||||
var constant = Constant.Zero
|
||||
@ -92,7 +112,7 @@ object M6809Buitins {
|
||||
for ((neg, load) <- addendReads) {
|
||||
if (result.isEmpty && fromScratch) {
|
||||
result ++= load
|
||||
if (neg) result += MLine.inherent(NEG)
|
||||
if (neg) result += MLine.inherentB(NEG)
|
||||
} else {
|
||||
load match {
|
||||
case List(l@MLine0(LDB, _, _)) =>
|
||||
@ -168,15 +188,112 @@ object M6809Buitins {
|
||||
}
|
||||
|
||||
def compileWordSum(ctx: CompilationContext, expr: SumExpression, fromScratch: Boolean): List[MLine] = {
|
||||
???
|
||||
if (expr.decimal) ???
|
||||
val (constant, variable) = split(ctx, expr)
|
||||
val addendReads = variable
|
||||
.map(addend => addend._1 -> M6809ExpressionCompiler.compileToD(ctx, addend._2))
|
||||
.map(code => (if (code._1) 1 else 0, complexityD(code._2)) -> code).sortBy(_._1).map(_._2)
|
||||
val result = ListBuffer[MLine]()
|
||||
for ((neg, load) <- addendReads) {
|
||||
if (result.isEmpty && fromScratch) {
|
||||
result ++= load
|
||||
if (neg) {
|
||||
result += MLine.immediate(EORA, 0xff)
|
||||
result += MLine.immediate(EORB, 0xff)
|
||||
result += MLine.immediate(ADDD, 1)
|
||||
}
|
||||
} else {
|
||||
load match {
|
||||
case List(l@MLine0(LDD, _, _)) =>
|
||||
if (neg) {
|
||||
result += l.copy(opcode = SUBD)
|
||||
} else {
|
||||
result += l.copy(opcode = ADDD)
|
||||
}
|
||||
case _ =>
|
||||
if (neg) {
|
||||
result += MLine.pp(PSHS, M6809Register.D)
|
||||
result ++= load
|
||||
// TODO: optimize
|
||||
result += MLine.immediate(EORA, 0xff)
|
||||
result += MLine.immediate(EORB, 0xff)
|
||||
result += MLine.immediate(ADDD, 1)
|
||||
result += MLine.accessAndPullSTwice(ADDD)
|
||||
} else {
|
||||
result += MLine.pp(PSHS, M6809Register.D)
|
||||
result ++= load
|
||||
result += MLine.accessAndPullSTwice(ADDD)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!constant.isProvablyZero) {
|
||||
if (result.isEmpty) {
|
||||
result += MLine.immediate(LDD, constant)
|
||||
} else {
|
||||
result += MLine.immediate(ADDD, constant)
|
||||
}
|
||||
}
|
||||
result.toList
|
||||
}
|
||||
def compileWordBitwise(ctx: CompilationContext,
|
||||
params: List[Expression],
|
||||
fromScratch: Boolean,
|
||||
opcodeB: MOpcode.Value,
|
||||
opcodeA: MOpcode.Value,
|
||||
opcodeB: MOpcode.Value,
|
||||
op: MathOperator.Value,
|
||||
empty: Int): List[MLine] = {
|
||||
???
|
||||
val (constant, variable) = split(ctx, params, op, empty)
|
||||
val addendReads = variable
|
||||
.map(addend => M6809ExpressionCompiler.compileToD(ctx, addend))
|
||||
.map(code => complexityD(code) -> code).sortBy(_._1).map(_._2)
|
||||
val result = ListBuffer[MLine]()
|
||||
for (load <- addendReads) {
|
||||
if (result.isEmpty && fromScratch) {
|
||||
result ++= load
|
||||
} else {
|
||||
load match {
|
||||
case List(l@MLine0(LDD, Absolute(false), addr)) =>
|
||||
result += l.copy(opcode = opcodeA)
|
||||
result += l.copy(opcode = opcodeB, parameter = addr + 1)
|
||||
case List(l@MLine0(LDD, Immediate, c)) =>
|
||||
result += l.copy(opcode = opcodeA, parameter = c.hiByte)
|
||||
result += l.copy(opcode = opcodeB, parameter = c.loByte)
|
||||
case _ =>
|
||||
result += MLine.pp(PSHS, M6809Register.D)
|
||||
result ++= load
|
||||
result += MLine.accessAndPullS(opcodeA)
|
||||
result += MLine.accessAndPullS(opcodeB)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!constant.isProvably(empty)) {
|
||||
if (result.isEmpty) {
|
||||
result += MLine.immediate(LDD, constant)
|
||||
} else {
|
||||
result += MLine.immediate(opcodeA, constant.hiByte)
|
||||
result += MLine.immediate(opcodeB, constant.loByte)
|
||||
}
|
||||
}
|
||||
result.toList
|
||||
}
|
||||
|
||||
def compileByteShiftForB(ctx: CompilationContext, rhs:Expression, left: Boolean): List[MLine] = {
|
||||
val op = if (left) MOpcode.ASL else MOpcode.LSR
|
||||
ctx.env.eval(rhs) match {
|
||||
case Some(NumericConstant(0, _)) => Nil
|
||||
case Some(NumericConstant(n, _)) => List.fill(n.toInt)(MLine.inherentB(op))
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
|
||||
def compileWordShiftForD(ctx: CompilationContext, rhs:Expression, left: Boolean): List[MLine] = {
|
||||
val op = if (left) List(MLine.inherentB(ASL), MLine.inherentA(ROL)) else List(MLine.inherentA(LSR), MLine.inherentB(ROR))
|
||||
ctx.env.eval(rhs) match {
|
||||
case Some(NumericConstant(0, _)) => Nil
|
||||
case Some(NumericConstant(n, _)) => List.fill(n.toInt)(op).flatten
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import millfork.assembly.m6809.{DAccumulatorIndexed, Indexed, MLine, MOpcode, Tw
|
||||
import millfork.compiler.{AbstractExpressionCompiler, BranchIfFalse, BranchIfTrue, BranchSpec, ComparisonType, CompilationContext, NoBranching}
|
||||
import millfork.node.{DerefExpression, Expression, FunctionCallExpression, GeneratedConstantExpression, IndexedExpression, LhsExpression, LiteralExpression, M6809Register, SumExpression, VariableExpression}
|
||||
import millfork.assembly.m6809.MOpcode._
|
||||
import millfork.env.{AssemblyParamSignature, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, FunctionInMemory, M6809RegisterVariable, MacroFunction, MathOperator, MemoryVariable, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, Type, Variable, VariablePointy}
|
||||
import millfork.env.{AssemblyParamSignature, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, FunctionInMemory, FunctionPointerType, M6809RegisterVariable, MacroFunction, MathOperator, MemoryVariable, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, ThingInMemory, Type, Variable, VariableInMemory, VariablePointy}
|
||||
|
||||
import scala.collection.GenTraversableOnce
|
||||
|
||||
@ -116,8 +116,11 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case Some(ix) => List(MLine.absolute(LDX, v.addr)) -> (ix * v.elementType.size).quickSimplify
|
||||
case _ =>
|
||||
v.indexType.size match {
|
||||
case 1 =>
|
||||
(compileToD(ctx, index) :+ MLine(LEAX, DAccumulatorIndexed(M6809Register.X, indirect = false), Constant.Zero)) -> Constant.Zero
|
||||
case 1 | 2 =>
|
||||
(compileToD(ctx, index) ++ List(
|
||||
MLine.absolute(LDX, v.addr),
|
||||
MLine(LEAX, DAccumulatorIndexed(M6809Register.X, indirect = false), Constant.Zero)
|
||||
)) -> Constant.Zero
|
||||
}
|
||||
}
|
||||
prepareIndex ++ (targetSize match {
|
||||
@ -133,35 +136,94 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case e@SumExpression(expressions, decimal) =>
|
||||
getArithmeticParamMaxSize(ctx, expressions.map(_._2)) match {
|
||||
case 1 => M6809Buitins.compileByteSum(ctx, e, fromScratch = true) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordSum(ctx, e, fromScratch = false) ++ targetifyD(ctx, target)
|
||||
case 2 => M6809Buitins.compileWordSum(ctx, e, fromScratch = true) ++ targetifyD(ctx, target)
|
||||
}
|
||||
case fce@FunctionCallExpression(functionName, params) =>
|
||||
functionName match {
|
||||
case "not" => ???
|
||||
case "nonet" => ???
|
||||
case "nonet" =>
|
||||
if (params.length != 1) {
|
||||
ctx.log.error("Invalid number of parameters", fce.position)
|
||||
Nil
|
||||
} else {
|
||||
ctx.env.eval(params.head) match {
|
||||
case Some(c) =>
|
||||
target match {
|
||||
case MExpressionTarget.NOTHING => Nil
|
||||
case _ => List(MLine.immediate(toLd(target), c))
|
||||
}
|
||||
case _ =>
|
||||
compileToB(ctx, params.head) ++ List(MLine.immediate(LDA, 0), MLine.inherentA(ROL)) ++ targetifyD(ctx, target)
|
||||
}
|
||||
}
|
||||
case "hi" =>
|
||||
compileToD(ctx, params.head) ++ targetifyA(ctx, target, isSigned = false)
|
||||
if (params.length != 1) {
|
||||
ctx.log.error("Invalid number of parameters", fce.position)
|
||||
Nil
|
||||
} else {
|
||||
compileToD(ctx, params.head) ++ targetifyA(ctx, target, isSigned = false)
|
||||
}
|
||||
case "lo" =>
|
||||
compileToD(ctx, params.head) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case "call" => ???
|
||||
if (params.length != 1) {
|
||||
ctx.log.error("Invalid number of parameters", fce.position)
|
||||
Nil
|
||||
} else {
|
||||
compileToD(ctx, params.head) ++ targetifyB(ctx, target, isSigned = false)
|
||||
}
|
||||
case "call" =>
|
||||
params match {
|
||||
case List(fp) =>
|
||||
getExpressionType(ctx, fp) match {
|
||||
case FunctionPointerType(_, _, _, _, Some(v)) if (v.name == "void") =>
|
||||
compileToX(ctx, fp) :+ MLine.absolute(JSR, env.get[ThingInMemory]("call"))
|
||||
case _ =>
|
||||
ctx.log.error("Not a function pointer", fp.position)
|
||||
compile(ctx, fp, MExpressionTarget.NOTHING)
|
||||
}
|
||||
case List(fp, param) =>
|
||||
getExpressionType(ctx, fp) match {
|
||||
case FunctionPointerType(_, _, _, Some(pt), Some(v)) =>
|
||||
if (pt.size > 2 || pt.size < 1) {
|
||||
ctx.log.error("Invalid parameter type", param.position)
|
||||
compile(ctx, fp, MExpressionTarget.NOTHING) ++ compile(ctx, param, MExpressionTarget.NOTHING)
|
||||
} else if (getExpressionType(ctx, param).isAssignableTo(pt)) {
|
||||
// TODO: optimal compile order
|
||||
pt.size match {
|
||||
case 1 =>
|
||||
compileToB(ctx, param) ++ stashBIfNeeded(ctx, compileToX(ctx, fp)) :+ MLine.absolute(JSR, env.get[ThingInMemory]("call"))
|
||||
case 2 =>
|
||||
compileToD(ctx, param) ++ stashDIfNeeded(ctx, compileToX(ctx, fp)) :+ MLine.absolute(JSR, env.get[ThingInMemory]("call"))
|
||||
}
|
||||
} else {
|
||||
ctx.log.error("Invalid parameter type", param.position)
|
||||
compile(ctx, fp, MExpressionTarget.NOTHING) ++ compile(ctx, param, MExpressionTarget.NOTHING)
|
||||
}
|
||||
case _ =>
|
||||
ctx.log.error("Not a function pointer", fp.position)
|
||||
compile(ctx, fp, MExpressionTarget.NOTHING) ++ compile(ctx, param, MExpressionTarget.NOTHING)
|
||||
}
|
||||
case _ =>
|
||||
ctx.log.error("Invalid call syntax", fce.position)
|
||||
Nil
|
||||
}
|
||||
case "*" => ???
|
||||
case "*'" => ???
|
||||
case "*'" => ctx.log.error("Decimal multiplication not implemented yet", fce.position); Nil
|
||||
case "/" => ???
|
||||
case "%%" => ???
|
||||
case "&" =>
|
||||
getArithmeticParamMaxSize(ctx, params) match {
|
||||
case 1 => M6809Buitins.compileByteBitwise(ctx, params, fromScratch = true, ANDB, MathOperator.And, 0xff) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordBitwise(ctx, params, fromScratch = true, ANDA, ANDB, MathOperator.And, 0xffff) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordBitwise(ctx, params, fromScratch = true, ANDA, ANDB, MathOperator.And, 0xffff) ++ targetifyD(ctx, target)
|
||||
}
|
||||
case "|" =>
|
||||
getArithmeticParamMaxSize(ctx, params) match {
|
||||
case 1 => M6809Buitins.compileByteBitwise(ctx, params, fromScratch = true, ORB, MathOperator.Or, 0) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordBitwise(ctx, params, fromScratch = true, ORA, ORB, MathOperator.Or, 0) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordBitwise(ctx, params, fromScratch = true, ORA, ORB, MathOperator.Or, 0) ++ targetifyD(ctx, target)
|
||||
}
|
||||
case "^" =>
|
||||
getArithmeticParamMaxSize(ctx, params) match {
|
||||
case 1 => M6809Buitins.compileByteBitwise(ctx, params, fromScratch = true, EORB, MathOperator.Exor, 0) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordBitwise(ctx, params, fromScratch = true, EORA, EORB, MathOperator.Exor, 0) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => M6809Buitins.compileWordBitwise(ctx, params, fromScratch = true, EORA, EORB, MathOperator.Exor, 0) ++ targetifyD(ctx, target)
|
||||
}
|
||||
case "&&" =>
|
||||
assertBool(ctx, "&&", params)
|
||||
@ -190,7 +252,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
compileTransitiveRelation(ctx, "==", params, target, branches) { (l, r) =>
|
||||
size match {
|
||||
case 1 => M6809Comparisons.compile8BitComparison(ctx, ComparisonType.Equal, l, r, branches)
|
||||
case 2 => ???
|
||||
case 2 => ctx.log.error("Word equality comparison not implemented yet", fce.position); Nil
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
@ -199,7 +261,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
compileTransitiveRelation(ctx, "!=", params, target, branches) { (l, r) =>
|
||||
size match {
|
||||
case 1 => M6809Comparisons.compile8BitComparison(ctx, ComparisonType.NotEqual, l, r, branches)
|
||||
case 2 => ???
|
||||
case 2 => ctx.log.error("Word inequality comparison not implemented yet", fce.position); Nil
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
@ -235,27 +297,44 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
case "<<" => ???
|
||||
case "<<" =>
|
||||
getArithmeticParamMaxSize(ctx, params) match {
|
||||
case 1 => compileToB(ctx, params(0)) ++ M6809Buitins.compileByteShiftForB(ctx, params(1), left = true) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => compileToD(ctx, params(0)) ++ M6809Buitins.compileWordShiftForD(ctx, params(1), left = true) ++ targetifyD(ctx, target)
|
||||
}
|
||||
case ">>" => ???
|
||||
case ">>>>" => ???
|
||||
getArithmeticParamMaxSize(ctx, params) match {
|
||||
case 1 => compileToB(ctx, params(0)) ++ M6809Buitins.compileByteShiftForB(ctx, params(1), left = false) ++ targetifyB(ctx, target, isSigned = false)
|
||||
case 2 => compileToD(ctx, params(0)) ++ M6809Buitins.compileWordShiftForD(ctx, params(1), left = false) ++ targetifyD(ctx, target)
|
||||
}
|
||||
case ">>>>" =>
|
||||
// TODO: this words, but is really suboptimal
|
||||
getArithmeticParamMaxSize(ctx, params) match {
|
||||
case 1 | 2 => compileToD(ctx, params(0)) ++
|
||||
List(MLine.immediate(ANDA, 1)) ++
|
||||
M6809Buitins.compileWordShiftForD(ctx, params(1), left = false) ++
|
||||
targetifyB(ctx, target, isSigned = false)
|
||||
}
|
||||
case "<<'" => ???
|
||||
case ">>'" => ???
|
||||
case "+=" =>
|
||||
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
|
||||
size match {
|
||||
case 1 => M6809Buitins.perform8BitInPlace(ctx, l, r, ADDB)
|
||||
case _ => ???
|
||||
case 2 => M6809Buitins.perform16BitInPlace(ctx, l, r, ADDD, commutative = true)
|
||||
case _ => ctx.log.error("Long addition not implemented yet", fce.position); Nil
|
||||
}
|
||||
case "+'=" => ???
|
||||
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 "-'=" => ???
|
||||
case "*=" => ???
|
||||
case "*'=" => ???
|
||||
case "*'=" => ctx.log.error("Decimal multiplication not implemented yet", fce.position); Nil
|
||||
case "/=" => ???
|
||||
case "%%=" => ???
|
||||
case "&=" =>
|
||||
@ -276,9 +355,33 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case 1 => M6809Buitins.perform8BitInPlace(ctx, l, r, EORB)
|
||||
case _ => ???
|
||||
}
|
||||
case "<<=" => ???
|
||||
case "<<=" =>
|
||||
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
|
||||
// TODO: optimize shifts directly in memory
|
||||
size match {
|
||||
case 1 => compileAddressToX(ctx, l) ++
|
||||
List(MLine.indexedX(LDB, Constant.Zero)) ++
|
||||
M6809Buitins.compileByteShiftForB(ctx, r, left = true) ++
|
||||
List(MLine.indexedX(STB, Constant.Zero))
|
||||
case 2 => compileAddressToX(ctx, l) ++
|
||||
List(MLine.indexedX(LDD, Constant.Zero)) ++
|
||||
M6809Buitins.compileWordShiftForD(ctx, r, left = true) ++
|
||||
List(MLine.indexedX(STD, Constant.Zero))
|
||||
}
|
||||
case "<<'=" => ???
|
||||
case ">>=" => ???
|
||||
case ">>=" =>
|
||||
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
|
||||
// TODO: optimize shifts directly in memory
|
||||
size match {
|
||||
case 1 => compileAddressToX(ctx, l) ++
|
||||
List(MLine.indexedX(LDB, Constant.Zero)) ++
|
||||
M6809Buitins.compileByteShiftForB(ctx, r, left = false) ++
|
||||
List(MLine.indexedX(STB, Constant.Zero))
|
||||
case 2 => compileAddressToX(ctx, l) ++
|
||||
List(MLine.indexedX(LDD, Constant.Zero)) ++
|
||||
M6809Buitins.compileWordShiftForD(ctx, r, left = false) ++
|
||||
List(MLine.indexedX(STD, Constant.Zero))
|
||||
}
|
||||
case ">>'=" => ???
|
||||
case ">>>>=" => ???
|
||||
case _ =>
|
||||
@ -401,8 +504,13 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
}
|
||||
|
||||
def stashBIfNeeded(ctx: CompilationContext, lines: List[MLine]): List[MLine] = {
|
||||
// TODO: only push if needed
|
||||
MLine.pp(PSHS, M6809Register.B) :: (lines :+ MLine.pp(PULS, M6809Register.B))
|
||||
if (lines.exists(_.changesRegister(M6809Register.B))) MLine.pp(PSHS, M6809Register.B) :: (lines :+ MLine.pp(PULS, M6809Register.B))
|
||||
else lines
|
||||
}
|
||||
|
||||
def stashDIfNeeded(ctx: CompilationContext, lines: List[MLine]): List[MLine] = {
|
||||
if (lines.exists(_.changesRegister(M6809Register.D))) MLine.pp(PSHS, M6809Register.D) :: (lines :+ MLine.pp(PULS, M6809Register.D))
|
||||
else lines
|
||||
}
|
||||
|
||||
def storeB(ctx: CompilationContext, target: LhsExpression): List[MLine] = {
|
||||
@ -415,6 +523,9 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case IndexedExpression(name, index) =>
|
||||
ctx.env.getPointy(name) match {
|
||||
case p: ConstantPointy =>
|
||||
if (p.readOnly) {
|
||||
ctx.log.error("Writing to a constant array", target.position)
|
||||
}
|
||||
val (variableIndex, constOffset) = ctx.env.evalVariableAndConstantSubParts(index)
|
||||
val effectiveBase = (p.value + constOffset).quickSimplify
|
||||
variableIndex match {
|
||||
@ -428,7 +539,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case Some(ix) => List(MLine.absolute(LDX, v.addr), MLine.indexedX(STB, ix * v.elementType.size))
|
||||
case _ =>
|
||||
v.indexType.size match {
|
||||
case 1 =>
|
||||
case 1 | 2 =>
|
||||
stashBIfNeeded(ctx,
|
||||
compileToD(ctx, index) :+ MLine(LEAX, DAccumulatorIndexed(M6809Register.X, indirect = false), Constant.Zero)) :+
|
||||
MLine.indexedX(STB, Constant.Zero)
|
||||
@ -448,7 +559,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
val variable = ctx.env.get[Variable](name)
|
||||
List(MLine.variable(ctx, STD, variable))
|
||||
case DerefExpression(inner, offset, _) =>
|
||||
compileToX(ctx, inner) :+ MLine(STD, Indexed(M6809Register.X, indirect = false), NumericConstant(offset, 2))
|
||||
stashDIfNeeded(ctx, compileToX(ctx, inner)) :+ MLine(STD, Indexed(M6809Register.X, indirect = false), NumericConstant(offset, 2))
|
||||
}
|
||||
}
|
||||
|
||||
@ -475,6 +586,28 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
||||
case MExpressionTarget.U => List(MLine.tfr(M6809Register.D, M6809Register.U))
|
||||
}
|
||||
|
||||
def compileAddressToX(ctx: CompilationContext, expr: LhsExpression): List[MLine] = {
|
||||
expr match {
|
||||
case VariableExpression(name) =>
|
||||
val variable = ctx.env.get[VariableInMemory](name)
|
||||
List(MLine.immediate(MOpcode.LDX, variable.toAddress))
|
||||
case DerefExpression(inner, offset, _) =>
|
||||
compileToX(ctx, inner) :+ MLine.indexedX(MOpcode.LEAX, Constant(offset))
|
||||
case IndexedExpression(aname, index) =>
|
||||
ctx.env.getPointy(aname) match {
|
||||
case p: VariablePointy => compileToD(ctx, index #*# p.elementType.size) ++ List(MLine.absolute(ADDD, p.addr), MLine.tfr(M6809Register.D, M6809Register.X))
|
||||
case p: ConstantPointy =>
|
||||
if (p.sizeInBytes.exists(_ < 255)) {
|
||||
compileToB(ctx, index #*# p.elementType.size) ++ List(MLine.immediate(LDX, p.value), MLine.inherent(ABX))
|
||||
} else {
|
||||
compileToX(ctx, index #*# p.elementType.size) :+ MLine.indexedX(LEAX, p.value)
|
||||
}
|
||||
case p:StackVariablePointy => compileToD(ctx, index #*# p.elementType.size) ++ List(MLine.variablestack(ctx, ADDD, p.offset), MLine.tfr(M6809Register.D, M6809Register.X))
|
||||
}
|
||||
case _ => ???
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private def compileTransitiveRelation(ctx: CompilationContext,
|
||||
operator: String,
|
||||
|
@ -20,6 +20,7 @@ object M6809StatementCompiler extends AbstractStatementCompiler[MLine] {
|
||||
case ReturnStatement(Some(e)) =>
|
||||
// TODO: clean stack
|
||||
// TODO: RTI
|
||||
AbstractExpressionCompiler.checkAssignmentType(ctx, e, ctx.function.returnType)
|
||||
val rts = List(MLine.inherent(RTS))
|
||||
val eval = ctx.function.returnType match {
|
||||
case FatBooleanType =>
|
||||
@ -42,7 +43,9 @@ object M6809StatementCompiler extends AbstractStatementCompiler[MLine] {
|
||||
???
|
||||
}
|
||||
case Assignment(destination, source) =>
|
||||
AbstractExpressionCompiler.getExpressionType(ctx, destination).size match {
|
||||
val destinationType = AbstractExpressionCompiler.getExpressionType(ctx, destination)
|
||||
AbstractExpressionCompiler.checkAssignmentType(ctx, source, destinationType)
|
||||
destinationType.size match {
|
||||
case 1 => (M6809ExpressionCompiler.compileToB(ctx, source) ++ M6809ExpressionCompiler.storeB(ctx, destination)) -> Nil
|
||||
case 2 => (M6809ExpressionCompiler.compileToD(ctx, source) ++ M6809ExpressionCompiler.storeD(ctx, destination)) -> Nil
|
||||
}
|
||||
@ -68,7 +71,8 @@ object M6809StatementCompiler extends AbstractStatementCompiler[MLine] {
|
||||
}
|
||||
case _ =>
|
||||
println(statement)
|
||||
???
|
||||
ctx.log.error("Not implemented yet", statement.position)
|
||||
Nil -> Nil
|
||||
}
|
||||
code._1.map(_.positionIfEmpty(statement.position)) -> code._2.map(_.positionIfEmpty(statement.position))
|
||||
}
|
||||
|
@ -44,6 +44,8 @@ sealed trait Expression extends Node {
|
||||
case SumExpression(params, false) => SumExpression((false -> this) :: params, decimal = false)
|
||||
case _ => SumExpression(List(false -> this, false -> that), decimal = false)
|
||||
}
|
||||
def #*#(smallInt: Int): Expression =
|
||||
if (smallInt == 1) this else FunctionCallExpression("*", List(this, LiteralExpression(smallInt, 1).pos(this.position))).pos(this.position)
|
||||
def #-#(smallInt: Int): Expression = (this #-# LiteralExpression(smallInt, 1).pos(this.position)).pos(this.position)
|
||||
def #-#(that: Expression): Expression = SumExpression(List(false -> this, true -> that), decimal = false)
|
||||
|
||||
|
@ -211,7 +211,7 @@ class M6809Assembler(program: Program,
|
||||
index + 4
|
||||
case _ =>
|
||||
// TODO
|
||||
throw new IllegalArgumentException("Not supported: " + instr)
|
||||
throw new IllegalArgumentException("Not supported: " + instr + " " + instr.productIterator.mkString("/"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -468,7 +468,11 @@ class ArraySuite extends FunSuite with Matchers with AppendedClues {
|
||||
"""
|
||||
| array(word) a[7] @$c000
|
||||
| void main () {
|
||||
| // the 6809 backend is apparently too smart right now and this actually works!:
|
||||
| a[0] += 2
|
||||
| #if ARCH_6809
|
||||
| a[0]*'a[1]
|
||||
| #endif
|
||||
| }
|
||||
""".stripMargin)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuCrossPlatformBenchmarkRun, EmuUnoptimizedCrossPlatformRun, EmuUnoptimizedRun}
|
||||
import millfork.test.emu.{EmuCrossPlatformBenchmarkRun, EmuUnoptimizedCrossPlatformRun, EmuUnoptimizedRun, ShouldNotCompile}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
@ -366,6 +366,29 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
|
||||
}
|
||||
}
|
||||
|
||||
test("Decimal multiplication by non-constant") {
|
||||
ShouldNotCompile(
|
||||
"""
|
||||
| volatile byte x
|
||||
| void main() {
|
||||
| byte tmp
|
||||
| tmp = 3
|
||||
| tmp *'= x
|
||||
| }
|
||||
|""".stripMargin)
|
||||
}
|
||||
|
||||
test("Decimal multiplication of two variables") {
|
||||
ShouldNotCompile(
|
||||
"""
|
||||
| volatile byte x
|
||||
| void main() {
|
||||
| byte tmp
|
||||
| tmp = x *' x
|
||||
| }
|
||||
|""".stripMargin)
|
||||
}
|
||||
|
||||
test("Decimal comparison") {
|
||||
// CMP#0 shouldn't be elided after a decimal operation.
|
||||
// Currently no emulator used for testing can catch that.
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{AppendedClues, FunSuite, Matchers}
|
||||
class FunctionPointerSuite extends FunSuite with Matchers with AppendedClues{
|
||||
|
||||
test("Function pointers 1") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Motorola6809)(
|
||||
"""
|
||||
|
|
||||
| byte output @$c000
|
||||
@ -100,7 +100,7 @@ class FunctionPointerSuite extends FunSuite with Matchers with AppendedClues{
|
||||
}
|
||||
|
||||
test("Function pointers 3") {
|
||||
EmuUnoptimizedCrossPlatformRun (Cpu.Mos, Cpu.Z80)(
|
||||
EmuUnoptimizedCrossPlatformRun (Cpu.Mos, Cpu.Z80, Cpu.Motorola6809)(
|
||||
"""
|
||||
| const byte COUNT = 128
|
||||
| array(word) output0[COUNT] @$c000
|
||||
@ -117,7 +117,7 @@ class FunctionPointerSuite extends FunSuite with Matchers with AppendedClues{
|
||||
|
|
||||
""".stripMargin) { m =>
|
||||
for (i <- 0 until 0x80) {
|
||||
m.readByte(0xc000 + i * 2) should equal(i) withClue ("id " + i)
|
||||
m.readWord(0xc000 + i * 2) should equal(i) withClue ("id " + i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class NonetSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Nonet operations") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(
|
||||
"""
|
||||
| array output [5] @$c000
|
||||
| void main () {
|
||||
@ -45,7 +45,7 @@ class NonetSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Nonet left shift") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)(
|
||||
"""
|
||||
| word output0 @$c000
|
||||
| word output1 @$c002
|
||||
@ -119,7 +119,7 @@ class NonetSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Nonet shift right") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8086)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8086, Cpu.Motorola6809)(
|
||||
"""
|
||||
| byte output0 @$c000
|
||||
| byte output1 @$c002
|
||||
@ -141,7 +141,7 @@ class NonetSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Nonet shift right 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8086)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8086, Cpu.Motorola6809)(
|
||||
"""
|
||||
| byte output0 @$c000
|
||||
| byte output1 @$c002
|
||||
|
@ -9,7 +9,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class ShiftSuite extends FunSuite with Matchers {
|
||||
|
||||
test("In-place shifting") {
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| array output [3] @$c000
|
||||
| void main () {
|
||||
| output[0] = 1
|
||||
@ -20,7 +20,7 @@ class ShiftSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Byte shifting") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| byte output @$c000
|
||||
| void main () {
|
||||
| byte a
|
||||
@ -31,7 +31,7 @@ class ShiftSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shifting") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| byte a
|
||||
@ -70,7 +70,7 @@ class ShiftSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shifting via pseudoregister") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = identity(three() << 7)
|
||||
@ -81,7 +81,7 @@ class ShiftSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Word shifting via pseudoregister 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)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| word w
|
||||
|
@ -9,7 +9,7 @@ import org.scalatest.{AppendedClues, FunSuite, Matchers}
|
||||
class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
|
||||
test("Word addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
@ -21,7 +21,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Cast word addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| byte output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
@ -34,7 +34,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word subtraction") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
@ -46,7 +46,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word subtraction 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
@ -58,7 +58,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word subtraction 3") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Cmos, Cpu.Z80, Cpu.Intel8080, Cpu.Intel8085, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| word a
|
||||
| void main () {
|
||||
@ -73,7 +73,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Byte-to-word addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| word pair
|
||||
| void main () {
|
||||
@ -86,7 +86,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Literal addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = 640
|
||||
@ -96,7 +96,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Array element addition") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| word pair
|
||||
| array b[2]
|
||||
@ -113,7 +113,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("nesdev.com example") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| byte output @$c000
|
||||
| byte tile @$C3A6
|
||||
| array map [256] @$c300
|
||||
@ -135,7 +135,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("nesdev.com example 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| byte output @$c000
|
||||
| byte tile @$C3A6
|
||||
| array map [256] @$c300
|
||||
@ -153,7 +153,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("hi()/lo()") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| array output [7] @$c000
|
||||
| void main () {
|
||||
| output[0] = lo(33)
|
||||
@ -185,7 +185,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word addition 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| word v
|
||||
@ -201,7 +201,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word addition 3") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| byte c
|
||||
@ -217,7 +217,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word addition 4") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| word v
|
||||
@ -254,7 +254,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word bit ops 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| word v
|
||||
@ -270,7 +270,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word shift") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| word v
|
||||
@ -288,7 +288,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word shift 2") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = five()
|
||||
@ -303,7 +303,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word shift 3") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = five()
|
||||
@ -318,7 +318,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word shift 4") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = five()
|
||||
@ -333,7 +333,7 @@ class WordMathSuite extends FunSuite with Matchers with AppendedClues {
|
||||
}
|
||||
|
||||
test("Word shift 5") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086)("""
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Sixteen, Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Intel8086, Cpu.Motorola6809)("""
|
||||
| word output @$c000
|
||||
| void main () {
|
||||
| output = five()
|
||||
|
@ -100,7 +100,7 @@ class EmuM6809Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizat
|
||||
log.verbosity = 999
|
||||
var effectiveSource = source
|
||||
if (!source.contains("_panic")) effectiveSource += "\n void _panic(){while(true){}}"
|
||||
// if (source.contains("call(")) effectiveSource += "\nnoinline asm word call(word d) {\n\n}\n"
|
||||
if (source.contains("call(")) effectiveSource += "\nnoinline asm word call(word d) {\nJMP ,X\n}\n"
|
||||
log.setSource(Some(effectiveSource.linesIterator.toIndexedSeq))
|
||||
val PreprocessingResult(preprocessedSource, features, _) = Preprocessor.preprocessForTest(options, effectiveSource)
|
||||
val parserF = M6809Parser("", preprocessedSource, "", options, features)
|
||||
|
@ -8,7 +8,7 @@ import millfork.compiler.{CompilationContext, LabelGenerator}
|
||||
import millfork.compiler.mos.MosCompiler
|
||||
import millfork.env.{Environment, InitializedArray, InitializedMemoryVariable, NormalFunction}
|
||||
import millfork.node.StandardCallGraph
|
||||
import millfork.parser.{MosParser, PreprocessingResult, Preprocessor, Z80Parser}
|
||||
import millfork.parser.{M6809Parser, MosParser, PreprocessingResult, Preprocessor, Z80Parser}
|
||||
import millfork._
|
||||
import millfork.compiler.m6809.M6809Compiler
|
||||
import millfork.compiler.z80.Z80Compiler
|
||||
@ -23,6 +23,7 @@ object ShouldNotCompile extends Matchers {
|
||||
def apply(source: String): Unit = {
|
||||
checkCase(Cpu.Mos, source)
|
||||
checkCase(Cpu.Z80, source)
|
||||
checkCase(Cpu.Motorola6809, source)
|
||||
}
|
||||
|
||||
private def checkCase(cpu: Cpu.Value, source: String) {
|
||||
@ -40,6 +41,8 @@ object ShouldNotCompile extends Matchers {
|
||||
platform.cpuFamily match {
|
||||
case CpuFamily.M6502 =>
|
||||
effectiveSource += "\nnoinline asm word call(word ax) {\nJMP ((__reg.b2b3))\n}\n"
|
||||
case CpuFamily.M6809 =>
|
||||
effectiveSource += "\nnoinline asm word call(word d) {\nJMP ,x\n}\n"
|
||||
case CpuFamily.I80 =>
|
||||
if (options.flag(CompilationFlag.UseIntelSyntaxForInput))
|
||||
effectiveSource += "\nnoinline asm word call(word de) {\npush d\nret\n}\n"
|
||||
@ -54,6 +57,8 @@ object ShouldNotCompile extends Matchers {
|
||||
platform.cpuFamily match {
|
||||
case CpuFamily.M6502 =>
|
||||
MosParser("", preprocessedSource, "", options, features)
|
||||
case CpuFamily.M6809 =>
|
||||
M6809Parser("", preprocessedSource, "", options, features)
|
||||
case CpuFamily.I80 =>
|
||||
Z80Parser("", preprocessedSource, "", options, features, options.flag(CompilationFlag.UseIntelSyntaxForInput))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user