1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-02 18:29:50 +00:00

6809: Implement more things

This commit is contained in:
Karol Stasiak 2019-12-15 23:48:02 +01:00
parent 6cd639a23a
commit f39fd67a89
4 changed files with 137 additions and 28 deletions

View File

@ -32,6 +32,10 @@ object MLine {
def longBranch(opcode: MOpcode.Value, label: String): MLine = longBranch(opcode, Label(label))
def shortBranch(opcode: MOpcode.Value, label: Label): MLine = MLine(opcode, Relative, label.toAddress)
def shortBranch(opcode: MOpcode.Value, label: String): MLine = shortBranch(opcode, Label(label))
def tfr(source: M6809Register.Value, target: M6809Register.Value): MLine = MLine(TFR, TwoRegisters(source, target), Constant.Zero)
def pp(opcode: MOpcode.Value, registers: M6809Register.Value*): MLine = MLine(opcode, RegisterSet(registers.toSet), Constant.Zero)
@ -42,6 +46,9 @@ object MLine {
def indexedX(opcode: MOpcode.Value, offset: Constant): MLine =
MLine(opcode, Indexed(M6809Register.X, indirect = false), offset)
def indexedX(opcode: MOpcode.Value, offset: Int): MLine =
MLine(opcode, Indexed(M6809Register.X, indirect = false), Constant(offset))
def accessAndPullS(opcode: MOpcode.Value): MLine =
MLine(opcode, PostIncremented(M6809Register.S, 1, indirect = false), Constant.Zero)
@ -74,9 +81,10 @@ object MLine {
variable match {
case v: VariableInMemory => MLine.absolute(opcode, v.toAddress)
case v: StackVariable =>
if (ctx.options.flag(CompilationFlag.UseUForStack)) MLine(opcode, Indexed(M6809Register.U, indirect = false), NumericConstant(v.baseOffset, 1))
else if (ctx.options.flag(CompilationFlag.UseYForStack)) MLine(opcode, Indexed(M6809Register.Y, indirect = false), NumericConstant(v.baseOffset, 1))
else MLine(opcode, Indexed(M6809Register.S, indirect = false), NumericConstant(v.baseOffset + ctx.extraStackOffset, 1))
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))
case _ => ???
}
}

View File

@ -54,6 +54,28 @@ object M6809Buitins {
}
}
def perform16BitInPlace(ctx: CompilationContext, l: LhsExpression, r: Expression, opcodeA: MOpcode.Value, opcodeB: 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), _)), _) =>
rc ++ List(ldl.copy(opcode = opcodeA), ldl.copy(opcode = opcodeB, parameter = ldl.parameter + 1), ldl.copy(opcode = STD))
case (_, List(ldr@MLine0(LDD, Absolute(false), _))) if lc.last.opcode == LDD =>
lc ++ List(ldr.copy(opcode = opcodeA), ldr.copy(opcode = opcodeB, parameter = ldr.parameter + 1), lc.last.copy(opcode = STD))
case (_, List(ldr@MLine0(LDD, Immediate, _))) if lc.last.opcode == LDD =>
lc ++ List(ldr.copy(opcode = opcodeA, parameter = ldr.parameter.hiByte), ldr.copy(opcode = opcodeB, parameter = ldr.parameter.loByte), 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.accessAndPullS(opcodeA), MLine.accessAndPullS(opcodeB), lc.last.copy(opcode = STD))
case _ if lc.last.opcode == LDD =>
// TODO: preserve X?
rc ++ List(MLine.pp(PSHS, M6809Register.D)) ++ lc ++ List(MLine.accessAndPullS(opcodeA), MLine.accessAndPullS(opcodeB), lc.last.copy(opcode = STD))
case _ =>
println(lc)
???
}
}
def split(ctx: CompilationContext, expr: SumExpression): (Constant, List[(Boolean, Expression)]) = {
var constant = Constant.Zero
@ -283,7 +305,18 @@ object M6809Buitins {
ctx.env.eval(rhs) match {
case Some(NumericConstant(0, _)) => Nil
case Some(NumericConstant(n, _)) => List.fill(n.toInt)(MLine.inherentB(op))
case _ => ???
case _ =>
val loop = ctx.nextLabel("sr")
val skip = ctx.nextLabel("ss")
M6809ExpressionCompiler.stashBIfNeeded(ctx, M6809ExpressionCompiler.compileToX(ctx, rhs)) ++ List(
MLine.label(loop),
MLine.indexedX(LEAX, -1),
MLine.immediate(CMPX, -1),
MLine.shortBranch(BEQ, skip),
MLine.inherentB(op),
MLine.shortBranch(BRA, loop),
MLine.label(skip)
)
}
}
@ -291,8 +324,21 @@ object M6809Buitins {
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(8, _)) =>
if (left) List(MLine.tfr(M6809Register.B, M6809Register.A), MLine.immediate(LDB, 0))
else List(MLine.tfr(M6809Register.A, M6809Register.B), MLine.immediate(LDA, 0))
case Some(NumericConstant(n, _)) => List.fill(n.toInt)(op).flatten
case _ => ???
case _ =>
val loop = ctx.nextLabel("sr")
val skip = ctx.nextLabel("ss")
M6809ExpressionCompiler.stashDIfNeeded(ctx, M6809ExpressionCompiler.compileToX(ctx, rhs)) ++ List(
MLine.label(loop),
MLine.indexedX(LEAX, -1),
MLine.immediate(CMPX, -1),
MLine.shortBranch(BEQ, skip))++op++List(
MLine.shortBranch(BRA, loop),
MLine.label(skip)
)
}
}

View File

@ -11,7 +11,7 @@ import millfork.assembly.m6809.MOpcode._
object M6809Comparisons {
def isTrivial(lc: List[MLine]): Boolean = lc match {
case List(MLine0(LDB, _, _)) => true
case List(MLine0(LDB | LDD, _, _)) => true
case _ => false
}
@ -25,7 +25,7 @@ object M6809Comparisons {
case ComparisonType.GreaterOrEqualUnsigned => BCC
case ComparisonType.LessUnsigned => BCS
case ComparisonType.GreaterUnsigned => BHI
case ComparisonType.LessOrEqualSigned => BLS
case ComparisonType.LessOrEqualUnsigned => BLS
case ComparisonType.GreaterSigned => BGT
case ComparisonType.GreaterOrEqualSigned => BGE
case ComparisonType.LessSigned => BLT
@ -45,4 +45,34 @@ object M6809Comparisons {
}
}
def compile16BitComparison(ctx: CompilationContext, comparisonType: ComparisonType.Value, l: Expression, r: Expression, branches: BranchSpec): scala.List[MLine] = {
val jump = branches match {
case BranchIfFalse(label) => return compile16BitComparison(ctx, ComparisonType.negate(comparisonType), l, r, branches.flip)
case BranchIfTrue(label) => List(MLine.longBranch(
comparisonType match {
case ComparisonType.Equal => BEQ
case ComparisonType.NotEqual => BNE
case ComparisonType.GreaterOrEqualUnsigned => BCC
case ComparisonType.LessUnsigned => BCS
case ComparisonType.GreaterUnsigned => BHI
case ComparisonType.LessOrEqualUnsigned => BLS
case ComparisonType.GreaterSigned => BGT
case ComparisonType.GreaterOrEqualSigned => BGE
case ComparisonType.LessSigned => BLT
case ComparisonType.LessOrEqualSigned => BLE
},
label
))
case _ => Nil
}
val lc = M6809ExpressionCompiler.compileToD(ctx, l)
val rc = M6809ExpressionCompiler.compileToD(ctx, r)
if (isTrivial(lc) && !isTrivial(rc)) return compile16BitComparison(ctx, ComparisonType.flip(comparisonType), r, l, branches)
if (isTrivial(rc)) {
lc ++ rc.map(_.copy(opcode = CMPD)) ++ jump
} else {
rc ++ List(MLine.pp(PSHS, M6809Register.D)) ++ lc ++ List(MLine.accessAndPullSTwice(CMPD)) ++ jump
}
}
}

View File

@ -1,6 +1,6 @@
package millfork.compiler.m6809
import millfork.assembly.m6809.{DAccumulatorIndexed, Indexed, MLine, MOpcode, TwoRegisters}
import millfork.assembly.m6809.{DAccumulatorIndexed, Immediate, Indexed, MLine, MLine0, MOpcode, TwoRegisters}
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._
@ -252,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 => ctx.log.error("Word equality comparison not implemented yet", fce.position); Nil
case 2 => M6809Comparisons.compile16BitComparison(ctx, ComparisonType.Equal, l, r, branches)
case _ => ???
}
}
@ -261,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 => ctx.log.error("Word inequality comparison not implemented yet", fce.position); Nil
case 2 => M6809Comparisons.compile16BitComparison(ctx, ComparisonType.NotEqual, l, r, branches)
case _ => ???
}
}
@ -270,6 +270,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
compileTransitiveRelation(ctx, "<", params, target, branches) { (l, r) =>
size match {
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
case _ => ???
}
}
@ -278,6 +279,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
compileTransitiveRelation(ctx, ">", params, target, branches) { (l, r) =>
size match {
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
case _ => ???
}
}
@ -286,6 +288,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
compileTransitiveRelation(ctx, "<=", params, target, branches) { (l, r) =>
size match {
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
case _ => ???
}
}
@ -294,6 +297,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
compileTransitiveRelation(ctx, ">=", params, target, branches) { (l, r) =>
size match {
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
case _ => ???
}
}
@ -302,13 +306,13 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
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
// TODO: this works, but is really suboptimal
getArithmeticParamMaxSize(ctx, params) match {
case 1 | 2 => compileToD(ctx, params(0)) ++
List(MLine.immediate(ANDA, 1)) ++
@ -341,46 +345,39 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
size match {
case 1 => M6809Buitins.perform8BitInPlace(ctx, l, r, ANDB)
case 2 => M6809Buitins.perform16BitInPlace(ctx, l, r, ANDB, commutative = true)
case _ => ???
}
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, ORB, commutative = true)
case _ => ???
}
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, EORB, commutative = true)
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 1 =>
handleInPlaceModification(ctx, l, 1, M6809Buitins.compileByteShiftForB(ctx, r, left = true))
case 2 =>
handleInPlaceModification(ctx, l, 2, M6809Buitins.compileWordShiftForD(ctx, r, left = true))
}
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 1 => handleInPlaceModification(ctx, l, 1, M6809Buitins.compileByteShiftForB(ctx, r, left = false))
case 2 => handleInPlaceModification(ctx, l, 2, M6809Buitins.compileWordShiftForD(ctx, r, left = false))
}
case ">>'=" => ???
case ">>>>=" => ???
@ -547,6 +544,11 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
else lines
}
def stashXIfNeeded(ctx: CompilationContext, lines: List[MLine]): List[MLine] = {
if (lines.exists(_.changesRegister(M6809Register.X))) MLine.pp(PSHS, M6809Register.X) :: (lines :+ MLine.pp(PULS, M6809Register.X))
else lines
}
def storeB(ctx: CompilationContext, target: LhsExpression): List[MLine] = {
target match {
case VariableExpression(name) =>
@ -642,6 +644,29 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
}
}
def handleInPlaceModification(ctx: CompilationContext, l: LhsExpression, size: Int, r: List[MLine]): List[MLine] = {
compileAddressToX(ctx, l) match {
case List(MLine0(LDX, Immediate, addr)) =>
size match {
case 1 => List(MLine.absolute(LDB, addr)) ++ r ++ List(MLine.absolute(STB, addr))
case 2 => List(MLine.absolute(LDD, addr)) ++ r ++ List(MLine.absolute(STD, addr))
}
case lc =>
size match {
case 1 =>
lc ++
List(MLine.indexedX(LDB, Constant.Zero)) ++
stashXIfNeeded(ctx, r) ++
List(MLine.indexedX(STB, Constant.Zero))
case 2 =>
lc ++
List(MLine.indexedX(LDD, Constant.Zero)) ++
stashXIfNeeded(ctx, r) ++
List(MLine.indexedX(LDD, Constant.Zero))
}
}
}
private def compileTransitiveRelation(ctx: CompilationContext,
operator: String,