basic looping

This commit is contained in:
Mark Canlas 2020-08-16 11:33:49 -04:00
parent 3f61977efb
commit 8c5ae9c2bc
4 changed files with 58 additions and 4 deletions

View File

@ -56,6 +56,8 @@ object registers {
sealed trait DestinationA
sealed trait IndexRegister
case object A extends Register {
def add[A](x: A)(implicit ctx: AssemblyContext, ev: Operand[A]): Unit =
ev.operandType match {
@ -67,12 +69,36 @@ object registers {
}
}
case object X extends Register with DestinationA {
case object X extends Register with DestinationA with IndexRegister {
def incr(implicit ctx: AssemblyContext): Unit =
ctx.push(INX, "incr x")
def upTo(s: String, start: Int, stop: Int)(f: AssemblyContext => Unit)(implicit ctx: AssemblyContext): Unit = {
ctx.push(LDX, start)
label(s)
f(ctx)
ctx.push(INX)
ctx.push(CPX, stop)
ctx.branch(BNE, s)
}
def downTo(s: String, start: Int, stop: Int)(f: AssemblyContext => Unit)(implicit ctx: AssemblyContext): Unit = {
ctx.push(LDX, start)
label(s)
f(ctx)
ctx.push(DEX)
ctx.push(CPX, stop)
ctx.branch(BNE, s)
}
}
case object Y extends Register with DestinationA
case object Y extends Register with DestinationA with IndexRegister
}
class CPU {
@ -113,7 +139,7 @@ class AssemblyContext {
def push(instruction: Instruction, s: String): Unit =
xs.append(UnaryInstruction(instruction, s.some))
def push(s: String): Unit =
def label(s: String): Unit =
xs.append(Label(s))
def push[A: Operand](instruction: Instruction, x: A): Unit =
@ -122,6 +148,9 @@ class AssemblyContext {
def push[A: Operand](instruction: Instruction, x: A, s: String): Unit =
xs.append(InstructionWithOperand(instruction, x: A, s.some))
def branch(instruction: Instruction, label: String): Unit =
xs.append(BranchingInstruction(instruction, label))
def printOut(): Unit = {
xs.map(_.toAsm)
.foreach(println)

View File

@ -61,3 +61,11 @@ case class Label(s: String) extends Statement {
def toTriplet: (String, Option[String], Option[String]) =
(s, None, None)
}
case class BranchingInstruction(instruction: Instruction, label: String) extends Statement {
def toAsm: String =
Statement.indent + instruction.toString + " " + label
def toTriplet: (String, Option[String], Option[String]) =
(instruction.toString, label.some, None)
}

View File

@ -4,5 +4,5 @@ package syntax
trait AsmSyntax {
def label(s: String)(implicit ctx: AssemblyContext): Unit =
ctx
.push(s)
.label(s)
}

View File

@ -4,6 +4,8 @@ import cats.implicits._
import org.scalatest.flatspec._
import org.scalatest.matchers._
import com.htmlism.mos6502.model._
class Easy6502Spec extends AnyFlatSpec with should.Matchers {
"the three pixel demo" should "have the right instructions" in {
@ -49,6 +51,21 @@ class Easy6502Spec extends AnyFlatSpec with should.Matchers {
)
}
"loop demo" should "compile" in {
val doc =
asmDoc { implicit ctx =>
asm { implicit a =>
registers.X.upTo("incrementing", 2, 5) { implicit a =>
a.push(INY)
}
}
}
println(
doc.toAsm
)
}
def withAssemblyContext(f: AssemblyContext => Unit): AssemblyContext = {
val ctx: AssemblyContext =
new AssemblyContext