1
0
mirror of https://github.com/KarolS/millfork.git synced 2025-03-18 18:29:29 +00:00

6809: Implement +', -' and <<' operators for bytes

This commit is contained in:
Karol Stasiak 2020-06-11 02:39:59 +02:00
parent 2d19537ed3
commit 78a680c0d6
5 changed files with 135 additions and 25 deletions

View File

@ -88,7 +88,7 @@ object M6809Buitins {
case (false, false) => MathOperator.Plus
case (true, false) => MathOperator.Minus
case (false, true) => MathOperator.DecimalPlus
case (false, true) => MathOperator.DecimalMinus
case (true, true) => MathOperator.DecimalMinus
},
constant, c
).quickSimplify
@ -133,27 +133,51 @@ object M6809Buitins {
val result = ListBuffer[MLine]()
for ((neg, load) <- addendReads) {
if (result.isEmpty && fromScratch) {
result ++= load
if (neg) result += MLine.inherentB(NEG)
if (expr.decimal) {
if (load.nonEmpty && load.last.opcode == LDB) {
result ++= load.init
result += load.last.copy(opcode = LDA)
} else {
result ++= load
result += MLine.tfr(M6809Register.B, M6809Register.A)
}
if (neg) ???
} else {
result ++= load
if (neg) result += MLine.inherentB(NEG)
}
} else {
load match {
case List(l@MLine0(LDB, _, _)) =>
if (neg) {
result += l.copy(opcode = sub)
if (expr.decimal) ???
if (expr.decimal) {
result += MLine.pp(PSHS, M6809Register.A)
result += MLine.immediate(LDA, 0x9a)
result += l.copy(opcode = SUBA)
result += MLine.accessAndPullS(ADDA)
result += MLine.inherent(DAA)
} else {
result += l.copy(opcode = sub)
}
} else {
result += l.copy(opcode = add)
if (expr.decimal) result += MLine.inherent(DAA)
}
case _ =>
if (expr.decimal) {
result += MLine.pp(PSHS, M6809Register.A)
result ++= load
result += MLine.pp(PULS, M6809Register.A)
if (neg) {
???
if (expr.decimal) ???
result += MLine.pp(PSHS, M6809Register.A)
result ++= load
result += MLine.pp(PSHS, M6809Register.B)
result += MLine.immediate(LDA, 0x9a)
result += MLine.accessAndPullS(SUBA)
result += MLine.accessAndPullS(ADDA)
result += MLine.inherent(DAA)
} else {
result += MLine.pp(PSHS, M6809Register.A)
result ++= load
result += MLine.pp(PULS, M6809Register.A)
result += MLine.pp(PSHS, M6809Register.B)
result += MLine.accessAndPullS(ADDA)
result += MLine.inherent(DAA)
}

View File

@ -0,0 +1,48 @@
package millfork.compiler.m6809
import millfork.assembly.m6809.MLine
import millfork.compiler.CompilationContext
import millfork.node.Expression
import millfork.assembly.m6809.MOpcode._
import millfork.env.NumericConstant
import millfork.node.M6809Register._
/**
* @author Karol Stasiak
*/
object M6809DecimalBuiltins {
def compileByteDecimalShiftLeft(ctx: CompilationContext, lhs: Option[Expression], rhs: Expression): List[MLine] = {
val load = lhs match {
case None => List(MLine.indexedX(LDA, 0))
case Some(l) => M6809ExpressionCompiler.compileToA(ctx, l)
}
val loop = ctx.env.eval(rhs) match {
case Some(NumericConstant(0, _)) => Nil
case Some(NumericConstant(1, _)) => List(
MLine.pp(PSHS, A),
MLine.accessAndPullS(ADDA),
MLine.inherent(DAA)
)
case _ =>
val labelSkip = ctx.nextLabel("ss")
val labelRepeat = ctx.nextLabel("sr")
M6809ExpressionCompiler.stashAIfNeeded(ctx, M6809ExpressionCompiler.compileToB(ctx, rhs)) ++ List(
MLine.label(labelRepeat),
MLine.immediate(CMPB, 0),
MLine.shortBranch(BEQ, labelSkip),
MLine.pp(PSHS, A),
MLine.accessAndPullS(ADDA),
MLine.inherent(DAA),
MLine.inherentB(DEC),
MLine.shortBranch(BRA, labelRepeat),
MLine.label(labelSkip)
)
}
val store = lhs match {
case None => List(MLine.indexedX(STA, 0))
case Some(l) => Nil
}
load ++ loop ++ store
}
}

View File

@ -345,7 +345,12 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
M6809Buitins.compileWordShiftForD(ctx, params(1), left = false) ++
targetifyB(ctx, target, isSigned = false)
}
case "<<'" => ???
case "<<'" =>
assertArithmeticBinary(ctx, params) match {
case (l, r, 1) => M6809DecimalBuiltins.compileByteDecimalShiftLeft(ctx, Some(l), r) ++ targetifyA(ctx, target, isSigned = false)
case (l, r, 2) => ???
case (l, r, _) => ???
}
case ">>'" => ???
case "+=" =>
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
@ -354,7 +359,22 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
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 =>
val lc = compileAddressToX(ctx, l)
val rc = compileToA(ctx, r)
val add = List(MLine.indexedX(ADDA, 0), MLine.inherent(DAA), MLine.indexedX(STA, 0))
(lc.exists(_.changesRegister(M6809Register.A)), rc.exists(_.changesRegister(M6809Register.X))) match {
case (false, false) => rc ++ lc ++ add
case (false, true) => rc ++ lc ++ add
case (true, false) => lc ++ rc ++ add
case (true, true) => rc ++ stashAIfNeeded(ctx, lc) ++ add
}
case 2 => ???
case _ => ???
}
case "-=" =>
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
size match {
@ -362,7 +382,17 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
case 2 => M6809Buitins.perform16BitInPlace(ctx, l, r, SUBD, commutative = false)
case _ => ???
}
case "-'=" => ???
case "-'=" =>
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
size match {
case 1 =>
val lc = compileAddressToX(ctx, l)
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 "*=" =>
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
size match {
@ -412,7 +442,13 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
case 2 =>
handleInPlaceModification(ctx, l, 2, M6809Buitins.compileWordShiftForD(ctx, r, left = true))
}
case "<<'=" => ???
case "<<'=" =>
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
size match {
case 1 =>
compileAddressToX(ctx, l) ++ M6809DecimalBuiltins.compileByteDecimalShiftLeft(ctx, None, r)
case 2 => ???
}
case ">>=" =>
val (l, r, size) = assertArithmeticAssignmentLike(ctx, params)
// TODO: optimize shifts directly in memory

View File

@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
class ByteDecimalMathSuite extends FunSuite with Matchers {
test("Decimal byte addition") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| byte output @$c000
| byte a
@ -22,7 +22,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("Decimal byte addition 2") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| byte output @$c000
| byte a
@ -62,7 +62,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("Decimal byte subtraction") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| byte output @$c000
| byte a
@ -74,7 +74,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("In-place decimal byte addition") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| array output[3] @$c000
| byte a
@ -88,7 +88,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("In-place decimal byte addition 2") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| array output[3] @$c000
| void main () {
@ -108,7 +108,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("In-place decimal byte subtraction") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| byte output @$c000
| byte a
@ -181,7 +181,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("Flag switching test") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| byte output @$c000
| void main () {
@ -192,7 +192,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("Flag switching test 2") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| byte output @$c000
| void main () {
@ -203,7 +203,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("Flag switching test 3") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| byte output @$c000
| void main () {
@ -214,7 +214,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("Decimal left shift test") {
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| byte output @$c000
| void main () {
@ -229,7 +229,7 @@ class ByteDecimalMathSuite extends FunSuite with Matchers {
}
test("Decimal left shift test 2") {
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086)(
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp, Cpu.Ricoh, Cpu.Intel8086, Cpu.Motorola6809)(
"""
| byte output @$c000
| void main () {

View File

@ -22,6 +22,8 @@ class M6809Memory(memoryBank: MemoryBank, resetVector: Int) extends MemorySegmen
override def load(addr: Int): Int = {
if (!memoryBank.readable(addr)) {
val start = addr & 0xff00
(0 until 0x100).grouped(16).map(range => (start + range.head).toHexString + range.map(i => memoryBank.output(start + i)).map(v => f" $v%02X").mkString("")).foreach(println)
println(s"Accessing memory for read at $$${addr.toHexString}")
???
}