mirror of
https://github.com/KarolS/millfork.git
synced 2025-03-28 08:30:13 +00:00
6809: Implement more things
This commit is contained in:
parent
6cd639a23a
commit
f39fd67a89
@ -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 _ => ???
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user