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() case class Mode(as: Int, name: String, stringifier: String => String) extends AddressingMode(as, name, stringifier) { def Mode(as: Int, name: String, stringifier: String => String) = this(as, name, stringifier).tap(modeMap += as -> _) } def apply(x: Int): Option[AddressingMode] = modeMap.get(x) } object PCModes extends Modes { Mode(3, "NextWord", reg => s"@PC+ (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 }