summaryrefslogtreecommitdiff
path: root/src/AddressingModes.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/AddressingModes.scala')
-rw-r--r--src/AddressingModes.scala112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/AddressingModes.scala b/src/AddressingModes.scala
new file mode 100644
index 0000000..e37bbe2
--- /dev/null
+++ b/src/AddressingModes.scala
@@ -0,0 +1,112 @@
+package ixee.re.disasm
+
+import ixee.cryptopals.utils.ByteUtils._
+import ixee.cryptopals.utils.FunctionUtils._
+
+import scala.collection.mutable.Map
+
+sealed trait AddressingMode {
+ def modeName: String
+ override def toString: String = modeName
+ def nameifyRegister(reg: Int): String = reg match {
+ case 0 => "pc"
+ case 1 => "sp"
+ case 2 => "sr"
+ case 3 => "cg"
+ case num @ _ => s"r$num"
+ }
+ def stringifyWith(reg: Int): String
+}
+
+sealed trait OneOpAddressing extends AddressingMode
+sealed trait TwoOpAddressing extends AddressingMode
+sealed trait TwoOpSourceAddressing extends TwoOpAddressing
+sealed trait TwoOpDestAddressing extends TwoOpAddressing
+
+object TwoOpSourceAddressingModes {
+ // just alias the apply over to make names look right at call sites.
+ // think hard about refactoring this
+ def apply(register: Int, mode: Int): Option[TwoOpSourceAddressing] = OneOpAddressingModes(register, mode)
+}
+
+object OneOpAddressingModes {
+ case class AddressingMode(as: Int, name: String, stringifier: String => String) extends OneOpAddressing with TwoOpSourceAddressing {
+ def modeName = name
+ def stringifyWith(reg: Int): String = stringifier(nameifyRegister(reg))
+ }
+
+ def apply(register: Int, mode: Int): Option[AddressingMode] = register match {
+ case 0 => PCModes(mode) orElse General(mode)
+ case 2 => SRModes(mode) orElse General(mode)
+ case 3 => CGModes(mode) orElse General(mode)
+ case _ => General(mode)
+ }
+
+ trait Modes {
+ private val modeMap: Map[Int, AddressingMode] = Map()
+ def Mode(as: Int, name: String, stringifier: String => String) = AddressingMode(as, name, stringifier).tap(modeMap += as -> _)
+
+ def apply(x: Int): Option[AddressingMode] = modeMap.get(x)
+ }
+
+ object PCModes extends Modes {
+ Mode(3, "NextWord", reg => s"@$reg+ (next word)")
+ }
+ object SRModes extends Modes {
+ Mode(2, "Const4", reg => "#4")
+ Mode(3, "Const8", reg => "#8")
+ }
+ object CGModes extends Modes {
+ Mode(0, "Const0", reg => "#0")
+ Mode(1, "Const1", reg => "#1")
+ Mode(2, "Const2", reg => "#2")
+ Mode(3, "ConstNeg1", reg => "#-1")
+ }
+ object General extends Modes {
+ Mode(0, "RegisterDirect", ident)
+ Mode(1, "Indexed", reg => s"@PC+($reg)")
+ Mode(2, "RegisterIndirect", reg => s"@$reg")
+ Mode(3, "IndirectAutoInc", reg => s"@$reg+")
+ }
+
+ PCModes
+ SRModes
+ CGModes
+ General
+}
+
+
+object TwoOpDestAddressingModes {
+ case class AddressingMode(as: Int, name: String, stringifier: String => String) extends TwoOpDestAddressing {
+ def modeName = name
+ def stringifyWith(reg: Int): String = stringifier(nameifyRegister(reg))
+ }
+
+ def apply(register: Int, mode: Int): Option[AddressingMode] = register match {
+ case 0 => PCModes(mode) orElse General(mode)
+ case 2 => SRModes(mode) orElse General(mode)
+ case _ => General(mode)
+ }
+
+ trait Modes {
+ private val modeMap: Map[Int, AddressingMode] = Map()
+ def Mode(as: Int, name: String, stringifier: String => String) = AddressingMode(as, name, stringifier).tap(modeMap += as -> _)
+
+ def apply(x: Int): Option[AddressingMode] = modeMap.get(x)
+ }
+
+ object PCModes extends Modes {
+ Mode(1, "Symbolic", reg => s"<??> (symbolic? x(PC)?")
+ }
+ object SRModes extends Modes {
+ Mode(1, "Absolute", reg => s"&@PC+ (value at nextWord)")
+ }
+ object General extends Modes {
+ Mode(0, "RegisterDirect", reg => s"$reg")
+ Mode(1, "Indexed", reg => s"@PC+($reg)")
+ }
+
+ PCModes
+ SRModes
+ General
+}