just checking in

This commit is contained in:
Mark Canlas 2018-05-05 14:23:21 -04:00
parent fcdeb9ffe2
commit e250dfb67e
8 changed files with 376 additions and 2 deletions

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
*.class
*.log
.idea
target

3
build.sbt Normal file
View File

@ -0,0 +1,3 @@
initialCommands in console := "import com.htmlism._"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test"

1
project/build.properties Normal file
View File

@ -0,0 +1 @@
sbt.version=1.0.3

View File

@ -0,0 +1,15 @@
package com.htmlism
sealed trait AddressingMode
case object Immediate extends AddressingMode
case object ZeroPage extends AddressingMode
case object ZeroPageX extends AddressingMode
case object Absolute extends AddressingMode
case object AbsoluteX extends AddressingMode
case object AbsoluteY extends AddressingMode
case object IndirectX extends AddressingMode
case object IndirectY extends AddressingMode
case object Accumulator extends AddressingMode
case object Implied extends AddressingMode
case object NoMode extends AddressingMode

View File

@ -0,0 +1,95 @@
package com.htmlism
sealed trait Instruction { def theme: String; def color: String }
case object NoInstruction extends Instruction { def theme: String = "noop"; def color: String = "white" }
sealed trait Logical extends Instruction { def theme: String = "logical"; def color: String = "OliveDrab" }
case object AND extends Logical
case object EOR extends Logical
case object ORA extends Logical
case object BIT extends Logical
sealed trait Arithmetic extends Instruction { def theme: String = "arithmetic"; def color: String = "CadetBlue" }
case object ADC extends Arithmetic
case object SBC extends Arithmetic
case object CMP extends Arithmetic
case object CPX extends Arithmetic
case object CPY extends Arithmetic
sealed trait Load extends Instruction { def theme: String = "load"; def color: String = "BurlyWood" }
case object LDA extends Load
case object LDX extends Load
case object LDY extends Load
sealed trait Store extends Instruction { def theme: String = "store"; def color: String = "Bisque" }
case object STA extends Store
case object STX extends Store
case object STY extends Store
sealed trait Shift extends Instruction { def theme: String = "shift"; def color: String = "SlateBlue" }
case object ASL extends Shift
case object LSR extends Shift
case object ROL extends Shift
case object ROR extends Shift
sealed trait Increment extends Instruction { def theme: String = "increment"; def color: String = "LightPink" }
case object INC extends Increment
case object INX extends Increment
case object INY extends Increment
sealed trait Decrement extends Instruction { def theme: String = "decrement"; def color: String = "Khaki" }
case object DEC extends Decrement
case object DEX extends Decrement
case object DEY extends Decrement
sealed trait Jump extends Instruction { def theme: String = "jump"; def color: String = "Salmon" }
case object JMP extends Jump
case object JSR extends Jump
case object RTS extends Jump
sealed trait Branch extends Instruction { def theme: String = "branch"; def color: String = "DodgerBlue" }
case object BCC extends Branch
case object BCS extends Branch
case object BEQ extends Branch
case object BMI extends Branch
case object BNE extends Branch
case object BPL extends Branch
case object BVC extends Branch
case object BVS extends Branch
sealed trait System extends Instruction { def theme: String = "system"; def color: String = "Peru" }
case object BRK extends System
case object NOP extends System
case object RTI extends System
sealed trait Stack extends Instruction { def theme: String = "stack"; def color: String = "Wheat" }
case object TSX extends Stack
case object TXS extends Stack
case object PHA extends Stack
case object PHP extends Stack
case object PLA extends Stack
case object PLP extends Stack
sealed trait Transfer extends Instruction { def theme: String = "transfer"; def color: String = "Teal" }
case object TAX extends Transfer
case object TAY extends Transfer
case object TXA extends Transfer
case object TYA extends Transfer
sealed trait Clear extends Instruction { def theme: String = "clear"; def color: String = "LightSteelBlue" }
case object CLC extends Clear
case object CLD extends Clear
case object CLI extends Clear
case object CLV extends Clear
sealed trait SetFlag extends Instruction { def theme: String = "set"; def color: String = "Thistle" }
case object SEC extends SetFlag
case object SED extends SetFlag
case object SEI extends SetFlag

View File

@ -0,0 +1,214 @@
package com.htmlism
import java.io.PrintWriter
object MatchOpcodes {
def paddedBinary(n: Int, width: Int) =
String.format(s"%${width}s", Integer.toBinaryString(n)).replace(" ", "0")
def main(args: Array[String]): Unit =
write(args(0))(doStuff)
def doStuff(out: PrintWriter): Unit = {
val generated =
(0 to 255)
.map(n => n -> toOpcode(n))
.collect { case (n, Some(x)) => (n, x) }
.toMap
val injected =
Map(
0x10 -> BPL,
0x30 -> BMI,
0x50 -> BVC,
0x70 -> BVS,
0x90 -> BCC,
0xB0 -> BCS,
0xD0 -> BNE,
0xF0 -> BEQ,
0x00 -> BRK,
0x20 -> JSR,
0x40 -> RTI,
0x60 -> RTS,
0x08 -> PHP,
0x28 -> PLP,
0x48 -> PHA,
0x68 -> PLA,
0x88 -> DEY,
0xA8 -> TAY,
0xC8 -> INY,
0xE8 -> INX,
0x18 -> CLC,
0x38 -> SEC,
0x58 -> CLI,
0x78 -> SEI,
0x98 -> TYA,
0xB8 -> CLV,
0xD8 -> CLD,
0xF8 -> SED,
0x8A -> TXA,
0x9A -> TXS,
0xAA -> TAX,
0xBA -> TSX,
0xCA -> DEX,
0xEA -> NOP
).mapValues(x => x -> Implied)
val lookup = generated ++ injected
out.print("<table>")
// print headers
out.print("<tr>")
out.print("<th/>")
for (c <- wideColumns)
out.print(s"<th>${paddedBinary(c, 5)}</th>")
out.print("</tr>")
for (r <- wideRows) {
out.print("<tr>")
// left header
out.print(s"<th>${paddedBinary(r, 3)}</th>")
for (c <- wideColumns) {
val fullInt = (r << 5) + c
lookup.get(fullInt) match {
case Some((ints, mode)) =>
val hex = f"$fullInt%2X"
out.print(s"<th class=${'"' + ints.theme + '"'} style=${'"' + "background-color: " + ints.color + '"'}>$ints $mode<br>$hex</th>")
case None =>
out.print(s"<td>UNDEF</td>")
}
}
out.print("</tr>")
}
out.print("</table>")
quartile(out, 0, lookup)
quartile(out, 1, lookup)
quartile(out, 2, lookup)
quartile(out, 3, lookup)
}
def quartile(out: PrintWriter, n: Int, lookup: Map[Int, (Instruction, AddressingMode)]) = {
out.print(s"<h2>${paddedBinary(n, 2)}</h2>")
out.print("<table>")
// print headers
out.print("<tr>")
out.print("<th/>")
val columns =
for {
y <- 0 to 1
xx <- Seq(3, 1, 2, 0)
} yield (xx << 1) + y
val rows =
0 to 7
for (c <- columns)
out.print(s"<th>${paddedBinary(c, 3)}</th>")
out.print("</tr>")
for (r <- rows) {
out.print("<tr>")
// left header
out.print(s"<th>${paddedBinary(r, 3)}</th>")
for (c <- columns) {
val fullInt = (r << (3 + 2)) + (c << 2) + n
lookup.get(fullInt) match {
case Some((ints, mode)) =>
val hex = f"$fullInt%2X"
out.print(s"<th class=${'"' + ints.theme + '"'} style=${'"' + "background-color: " + ints.color + '"'}>$ints $mode<br>$hex</th>")
case None =>
out.print(s"<td>UNDEF</td>")
}
}
out.print("</tr>")
}
out.print("</table>")
}
def wideColumns: Seq[Int] =
for {
cc <- 0 to 3
y <- 0 to 1
xx <- 0 to 3
} yield (xx << 3) + (y << 2) + cc
def wideRows: Seq[Int] =
0 to 7
private def write(file: String)(f: PrintWriter => Unit) = {
val out = new PrintWriter(file)
f(out)
out.close()
}
def toOpcode(n: Int): Option[(Instruction, AddressingMode)] = {
val BitPattern = ThreeBits >> ThreeBits >> TwoBits
n match {
case BitPattern(aaabbb, cc) =>
cc match {
case 0 => (c00 _).tupled(aaabbb)
case 1 => (c01 _).tupled(aaabbb)
case 2 => (c10 _).tupled(aaabbb)
case 3 => None
}
}
}
def c01(aaa: Int, bbb: Int): Option[(Instruction, AddressingMode)] = {
val instruction =
Seq(ORA, AND, EOR, ADC, STA, LDA, CMP, SBC)(aaa)
val addressingMode =
Seq(IndirectX, ZeroPage, Immediate, Absolute, IndirectY, ZeroPageX, AbsoluteY, AbsoluteX)(bbb)
Some(instruction -> addressingMode)
}
def c10(aaa: Int, bbb: Int): Option[(Instruction, AddressingMode)] = {
val instruction =
Seq(ASL, ROL, LSR, ROR, STX, LDX, DEC, INC)(aaa)
val addressingMode =
Seq(Immediate, ZeroPage, Accumulator, Absolute, NoMode, ZeroPageX, NoMode, AbsoluteX)(bbb)
Some(instruction -> addressingMode)
}
def c00(aaa: Int, bbb: Int): Option[(Instruction, AddressingMode)] = {
val instruction =
Seq(NoInstruction, BIT, JMP, JMP, STY, LDY, CPY, CPX)(aaa)
val addressingMode =
Seq(Immediate, ZeroPage, NoMode, Absolute, NoMode, ZeroPageX, NoMode, AbsoluteX)(bbb)
Some(instruction -> addressingMode)
}
}

View File

@ -0,0 +1,39 @@
package com.htmlism
trait BitExtractor[A] {
self =>
def length: Int
def unapply(n: Int): Option[A]
def >>[B](that: BitExtractor[B]): BitExtractor[(A, B)] =
new BitExtractor[(A, B)] {
def length: Int = self.length + that.length
def unapply(n: Int): Option[(A, B)] =
for {
b <- that.unapply(n)
shifted = n >> that.length
a <- self.unapply(shifted)
} yield (a, b)
}
}
object AtomExtractor {
def pow(ex: Int, acc: Int = 1): Int =
if (ex == 0)
acc
else
pow(ex - 1, acc * 2)
}
abstract class PrimitiveBitExtractor(val length: Int) extends BitExtractor[Int] {
private lazy val mask = AtomExtractor.pow(length) - 1
def unapply(n: Int): Option[Int] = Some(n & mask)
}
object OneBit extends PrimitiveBitExtractor(1)
object TwoBits extends PrimitiveBitExtractor(2)
object ThreeBits extends PrimitiveBitExtractor(3)

View File

@ -0,0 +1,7 @@
package com.htmlism
import org.scalatest.FlatSpec
class BitMatchingSpec extends FlatSpec {
}