mirror of
https://github.com/mcanlas/6502-opcodes.git
synced 2024-05-28 21:41:31 +00:00
hardcode registers to improve type inference opportunities
This commit is contained in:
parent
627bfcbeab
commit
ca2333ccc5
|
@ -1,7 +1,13 @@
|
|||
package com.htmlism.scratchpad
|
||||
|
||||
object Load:
|
||||
def const[R: Register, A: Encoded.Byte](x: A): Asm1[R] =
|
||||
def constA[B: Encoded.Byte](x: B): Asm1[Reg.A] =
|
||||
Const(x)
|
||||
|
||||
def constX[B: Encoded.Byte](x: B): Asm1[Reg.X] =
|
||||
Const(x)
|
||||
|
||||
def constY[B: Encoded.Byte](x: B): Asm1[Reg.Y] =
|
||||
Const(x)
|
||||
|
||||
case class Const[R, A: Encoded.Byte](x: A)(using R: Register[R]) extends Asm1[R]:
|
||||
|
|
|
@ -2,14 +2,14 @@ package com.htmlism.scratchpad
|
|||
|
||||
// https://mads.atari8.info/mads_eng.html#_mv
|
||||
object Move:
|
||||
def const[R: Register, A: WriteLease.ByteAddress, X: Encoded.Byte](x: X): Asm2[R, A] =
|
||||
def constA[A, X: Encoded.Byte](x: X, dest: WriteLease.ByteAddress[A]): Asm2[Reg.A, A] =
|
||||
Load
|
||||
.const[R, X](x)
|
||||
.widenWith[A] andThen Store.from[R, A]
|
||||
.constA(x)
|
||||
.widenWith[A] andThen Store.fromA(dest)
|
||||
|
||||
def from[R: Register, A: ReadLease.ByteAddress, B: WriteLease.ByteAddress]: Asm3[R, A, B] =
|
||||
Asm3Instructions(List(""))
|
||||
|
||||
object Word:
|
||||
def const[R: Register, A: WriteLease.WordAddress, X: Encoded.Word](x: X): Asm2[R, A] =
|
||||
def const[R: Register, A, X: Encoded.Word](x: X, dest: WriteLease.ByteAddress[A]): Asm2[R, A] =
|
||||
Asm2Instructions(List(""))
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
package com.htmlism.scratchpad
|
||||
|
||||
object Store:
|
||||
def from[R: Register, A: WriteLease.ByteAddress]: Asm2[R, A] =
|
||||
Byte[R, A]()
|
||||
def fromA[B](dest: WriteLease.ByteAddress[B]): Asm2[Reg.A, B] =
|
||||
Byte[Reg.A, B](dest)
|
||||
|
||||
case class Byte[R, A]()(using R: Register[R], A: WriteLease.ByteAddress[A]) extends Asm2[R, A]:
|
||||
def fromX[B](dest: WriteLease.ByteAddress[B]): Asm2[Reg.X, B] =
|
||||
Byte[Reg.X, B](dest)
|
||||
|
||||
def fromY[B](dest: WriteLease.ByteAddress[B]): Asm2[Reg.Y, B] =
|
||||
Byte[Reg.Y, B](dest)
|
||||
|
||||
case class Byte[R, A](dest: WriteLease.ByteAddress[A])(using R: Register[R]) extends Asm2[R, A]:
|
||||
def xs: List[String] =
|
||||
List("ST" + R.name)
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package com.htmlism.scratchpad
|
||||
|
||||
trait WriteLease[A]
|
||||
trait WriteLease[A]:
|
||||
def canon: A
|
||||
|
||||
def to(f: A => Int): WriteLease.ByteAddress[A] =
|
||||
WriteLease.ByteAddress(f(canon))
|
||||
|
||||
object WriteLease:
|
||||
trait ByteAddress[A]
|
||||
case class ByteAddress[A](address: Int)
|
||||
|
||||
trait WordAddress[A]
|
||||
case class WordAddress[A](address: Int)
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package com.htmlism
|
||||
|
||||
package object scratchpad:
|
||||
type A =
|
||||
Register.A
|
||||
object Reg:
|
||||
type A =
|
||||
Register.A
|
||||
|
||||
type X =
|
||||
Register.X
|
||||
type X =
|
||||
Register.X
|
||||
|
||||
type Y =
|
||||
Register.Y
|
||||
type Y =
|
||||
Register.Y
|
||||
|
|
|
@ -6,12 +6,26 @@ object ComplicatedResourceSuite extends FunSuite:
|
|||
def headAddr: Int =
|
||||
address
|
||||
|
||||
def tailAddres: Int =
|
||||
def tailAddr: Int =
|
||||
address + 1
|
||||
|
||||
def setHead(x: Int)(using W: WriteLease[A]): Asm1[Register.A] =
|
||||
Load.Const[Register.A, Int](x)
|
||||
def setHead(x: Int)(using W: WriteLease[A]): Asm2[Register.A, A] =
|
||||
Move.constA(x, W.to(_.headAddr))
|
||||
|
||||
class PlayerOne extends Player[PlayerOne](40)
|
||||
|
||||
object PlayerOne extends PlayerOne:
|
||||
given write: WriteLease[PlayerOne] with
|
||||
def canon: PlayerOne =
|
||||
PlayerOne
|
||||
|
||||
class PlayerTwo extends Player[PlayerTwo](80)
|
||||
|
||||
object PlayerTwo extends PlayerTwo:
|
||||
given write: WriteLease[PlayerTwo] with
|
||||
def canon: PlayerTwo =
|
||||
PlayerTwo
|
||||
|
||||
test("use write lease") {
|
||||
expect.eql(List("LDA", "STA"), PlayerOne.setHead(0)(using PlayerOne.write).xs)
|
||||
}
|
||||
|
|
|
@ -12,23 +12,23 @@ class ExampleRegister
|
|||
class FeatureSpec extends AnyFunSuite with Matchers:
|
||||
test("zero page address as write only supports writing") {
|
||||
ExampleRegister
|
||||
.writeConst(2)[A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
|
||||
.writeConst(2)[Reg.A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
|
||||
}
|
||||
|
||||
test("zero page address as read/write supports writing") {
|
||||
ExampleRegister
|
||||
.writeConst(2)[A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
|
||||
.writeConst(2)[Reg.A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
|
||||
}
|
||||
|
||||
test("writing to an address can use A, X, and Y registers for bouncing") {
|
||||
ExampleRegister
|
||||
.writeConst(2)[A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
|
||||
.writeConst(2)[Reg.A] shouldBe "LDA 2 STA 1 ; example = 2, via A"
|
||||
|
||||
ExampleRegister
|
||||
.writeConst(2)[X] shouldBe "LDX 2 STX 1 ; example = 2, via X"
|
||||
.writeConst(2)[Reg.X] shouldBe "LDX 2 STX 1 ; example = 2, via X"
|
||||
|
||||
ExampleRegister
|
||||
.writeConst(2)[Y] shouldBe "LDY 2 STY 1 ; example = 2, via Y"
|
||||
.writeConst(2)[Reg.Y] shouldBe "LDY 2 STY 1 ; example = 2, via Y"
|
||||
}
|
||||
|
||||
ignore("the write payload is a typesafe enum") {}
|
||||
|
@ -36,4 +36,4 @@ class FeatureSpec extends AnyFunSuite with Matchers:
|
|||
// intializations must be constant
|
||||
// cannot involve reading from a register, that is a side-effect
|
||||
// can also support 16-bit initializations
|
||||
ignore("initializations of the same value and register are aggregated") {}
|
||||
ignore("initializations of the same value and register are aggReg.Ated") {}
|
||||
|
|
|
@ -7,13 +7,13 @@ object RegisterSuite extends FunSuite:
|
|||
ev
|
||||
|
||||
test("the accumulator is a register") {
|
||||
expect.eql("A", reg[A].name)
|
||||
expect.eql("A", reg[Reg.A].name)
|
||||
}
|
||||
|
||||
test("X is a register") {
|
||||
expect.eql("X", reg[X].name)
|
||||
expect.eql("X", reg[Reg.X].name)
|
||||
}
|
||||
|
||||
test("Y is a register") {
|
||||
expect.eql("Y", reg[Y].name)
|
||||
expect.eql("Y", reg[Reg.Y].name)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user