diff options
Diffstat (limited to 'src/AddressingModes.scala')
-rw-r--r-- | src/AddressingModes.scala | 112 |
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 +} |