6502-opcodes/src/main/scala/com/htmlism/mos6502/dsl/DslDemo.scala

160 lines
3.6 KiB
Scala
Raw Normal View History

2020-08-13 04:16:30 +00:00
package com.htmlism.mos6502.dsl
2020-08-21 07:11:27 +00:00
import scala.collection.immutable.ListSet
2020-08-13 04:16:30 +00:00
import scala.collection.mutable.ListBuffer
2020-08-15 06:04:21 +00:00
2023-10-03 20:15:10 +00:00
import cats.syntax.all.*
2020-08-15 06:04:21 +00:00
2023-10-03 20:15:10 +00:00
import com.htmlism.mos6502.model.*
2020-08-13 04:16:30 +00:00
2022-02-14 23:11:45 +00:00
object DslDemo extends App:
2020-08-13 04:16:30 +00:00
val cpu =
new CPU
import registers.{A, X}
// address demonstration
2020-08-13 04:21:15 +00:00
withAssemblyContext { implicit ctx =>
2020-08-13 04:16:30 +00:00
val payloadLocation =
0x01.z
cpu.A = 0x40
A.add(payloadLocation)
}
// a becomes others
2020-08-13 04:21:15 +00:00
withAssemblyContext { implicit ctx =>
2020-08-13 04:16:30 +00:00
cpu.A = cpu.X
cpu.A = cpu.Y
}
// demonstrate first example
2020-08-13 04:21:15 +00:00
withAssemblyContext { implicit ctx =>
2020-08-15 07:52:11 +00:00
cpu.A = 0xc0
2020-08-13 04:16:30 +00:00
cpu.X = cpu.A
X.incr
A.add(0xc4)
}
2022-02-14 23:11:45 +00:00
def withAssemblyContext(f: AssemblyContext => Unit): Unit =
2020-08-13 04:21:15 +00:00
val ctx: AssemblyContext =
new AssemblyContext
f(ctx)
2020-08-13 04:16:30 +00:00
ctx.printOut()
println()
println()
2022-02-14 23:11:45 +00:00
object registers:
2020-08-13 04:16:30 +00:00
sealed trait Register
sealed trait DestinationA
2020-08-16 15:33:49 +00:00
sealed trait IndexRegister
2022-02-14 23:11:45 +00:00
case object A extends Register:
2023-06-19 09:30:17 +00:00
def add[A](x: A)(using ctx: AssemblyContext, ev: Operand[A]): Unit =
2022-02-14 23:11:45 +00:00
ev.operandType match
2020-08-15 03:06:09 +00:00
case ValueLiteral =>
ctx.push(ADC, x, s"add LITERAL to a")
case MemoryLocation =>
ctx.push(ADC, x, s"add ADDR to a")
2020-08-13 04:16:30 +00:00
2022-02-14 23:11:45 +00:00
case object X extends Register with DestinationA with IndexRegister:
2023-06-19 09:30:17 +00:00
def incr(using ctx: AssemblyContext): Unit =
2020-08-14 20:54:29 +00:00
ctx.push(INX, "incr x")
2020-08-16 15:33:49 +00:00
2023-06-19 09:30:17 +00:00
def loop(s: String, spec: RangeSpec)(f: AssemblyContext => Unit)(using ctx: AssemblyContext): Unit =
2020-08-21 08:04:35 +00:00
val (start, stop, instruction) =
2022-02-14 23:11:45 +00:00
spec match
2020-08-21 08:04:35 +00:00
case Incrementing(from, to) =>
(from, to, INX)
2020-08-16 15:33:49 +00:00
2020-08-21 08:04:35 +00:00
case Decrementing(from, to) =>
(from, to, DEX)
2020-08-16 15:33:49 +00:00
ctx.push(LDX, start)
label(s)
f(ctx)
2020-08-21 08:04:35 +00:00
ctx.push(instruction)
2020-08-16 15:33:49 +00:00
ctx.push(CPX, stop)
ctx.branch(BNE, s)
2020-08-13 04:16:30 +00:00
2020-08-16 15:33:49 +00:00
case object Y extends Register with DestinationA with IndexRegister
2020-08-13 04:16:30 +00:00
2022-02-14 23:11:45 +00:00
class CPU:
2020-08-13 04:16:30 +00:00
def A: registers.A.type =
registers.A
2023-06-19 09:30:17 +00:00
def A_=[A](x: A)(using ctx: AssemblyContext, ev: Operand[A]): Unit =
2020-08-15 03:22:13 +00:00
ctx.push(LDA, x, "set A to " + ev.toShow(x))
2020-08-13 04:42:21 +00:00
2023-06-19 09:30:17 +00:00
def A_=(reg: registers.DestinationA)(using ctx: AssemblyContext): Unit =
2022-02-14 23:11:45 +00:00
reg match
2020-08-14 20:54:29 +00:00
case registers.X =>
ctx.push(TXA)
case registers.Y =>
ctx.push(TYA)
2020-08-13 04:16:30 +00:00
def X: registers.X.type =
registers.X
2023-06-19 09:30:17 +00:00
def X_=(reg: registers.A.type)(using ctx: AssemblyContext): Unit =
2020-08-14 20:54:29 +00:00
ctx.push(TAX, s"set x to register $reg")
2020-08-13 04:16:30 +00:00
def Y: registers.Y.type =
registers.Y
2023-06-19 09:30:17 +00:00
def Y_=(reg: registers.A.type)(using ctx: AssemblyContext): Unit =
2020-08-14 20:54:29 +00:00
ctx.push(TAY, s"set x to register $reg")
2020-08-13 04:16:30 +00:00
2022-02-14 23:11:45 +00:00
class AssemblyContext:
2020-08-15 05:27:13 +00:00
private val xs: ListBuffer[Statement] =
2020-08-13 04:16:30 +00:00
ListBuffer()
2020-08-21 07:11:27 +00:00
private var jumps: ListSet[Subroutine] =
ListSet()
2020-08-14 20:54:29 +00:00
def push(instruction: Instruction): Unit =
xs.append(UnaryInstruction(instruction, None))
def push(instruction: Instruction, s: String): Unit =
xs.append(UnaryInstruction(instruction, s.some))
2020-08-13 04:30:00 +00:00
2020-08-16 15:33:49 +00:00
def label(s: String): Unit =
2020-08-16 06:17:04 +00:00
xs.append(Label(s))
2020-08-15 04:49:07 +00:00
def push[A: Operand](instruction: Instruction, x: A): Unit =
2020-08-14 20:54:29 +00:00
xs.append(InstructionWithOperand(instruction, x, None))
2020-08-13 04:30:00 +00:00
2020-08-15 04:49:07 +00:00
def push[A: Operand](instruction: Instruction, x: A, s: String): Unit =
2020-08-14 20:54:29 +00:00
xs.append(InstructionWithOperand(instruction, x: A, s.some))
2020-08-13 04:16:30 +00:00
2020-08-16 15:33:49 +00:00
def branch(instruction: Instruction, label: String): Unit =
xs.append(BranchingInstruction(instruction, label))
2020-08-21 07:11:27 +00:00
def addJump(subroutine: Subroutine): Unit =
jumps = jumps + subroutine
2022-02-14 23:11:45 +00:00
def printOut(): Unit =
2020-08-15 04:49:07 +00:00
xs.map(_.toAsm)
2020-08-14 21:08:59 +00:00
.foreach(println)
2020-08-15 05:27:13 +00:00
def triplets: List[(String, Option[String], Option[String])] =
2020-08-15 06:04:21 +00:00
xs.map(_.toTriplet).toList
2020-08-16 04:58:25 +00:00
def toFragment: AsmFragment =
AsmFragment(xs.toList)
2020-08-21 07:11:27 +00:00
def getJumps: ListSet[Subroutine] =
jumps