package ixee.re.disasm import ixee.cryptopals.utils.ByteUtils._ import ixee.cryptopals.utils.FunctionUtils._ import scala.collection.mutable.Map sealed trait OpCode { def instrName: String override def toString: String = instrName } sealed trait NoOpCode extends OpCode sealed trait OneOpCode extends OpCode sealed trait TwoOpCode extends OpCode object Opcodes { def opcodes: Map[Int, OpCode] = noOpCodes ++ oneOpCodes ++ twoOpCodes val noOpCodes: Map[Int, NoOpCode] = Map() val oneOpCodes: Map[Int, OneOpCode] = Map() val twoOpCodes: Map[Int, TwoOpCode] = Map() def apply(value: Int) = opcodes.get(value) def noOp(value: Int) = noOpCodes.get(value) def oneOp(value: Int) = oneOpCodes.get(value) def twoOp(value: Int) = twoOpCodes.get(value) object NoOpCodes { val Prefix = 0x01 case class Code(value: Byte, name: String) extends NoOpCode { def instrName = name } object Code { def apply(value: Int, name: String) = new Code(value.toByte, name).tap(code => noOpCodes += ((((Prefix << 3) + value) << 10) -> code)) } Code(0x00, "JNE") Code(0x01, "JEQ") Code(0x02, "JNC") Code(0x03, "JC ") Code(0x04, "JN ") Code(0x05, "JGE") Code(0x06, "JL ") Code(0x07, "JMP") } object OneOpCodes { val Prefix = 0x04 case class Code(value: Byte, name: String) extends OneOpCode { def instrName = name } object Code { def apply(value: Int, name: String) = new Code(value.toByte, name).tap(code => oneOpCodes += ((((Prefix << 3) + value) << 7) -> code)) } Code(0x00, "RRC") Code(0x01, "SWPB") Code(0x02, "RRA") Code(0x03, "SXT") Code(0x04, "PUSH") Code(0x05, "CALL") Code(0x06, "RETI") // Code(0x07, "NotImplemented") } object TwoOpCodes { val Prefix = 0x1 case class Code(value: Byte, name: String) extends TwoOpCode { def instrName = name } object Code { def apply(value: Int, name: String) = new Code(value.toByte, name).tap(code => twoOpCodes += ((value @<< 12) -> code)) } Code(0x04, "MOV") Code(0x05, "ADD") Code(0x06, "ADDC") Code(0x07, "SUBC") Code(0x08, "SUB") Code(0x09, "CMP") Code(0x0a, "DADD") Code(0x0b, "BIT") Code(0x0c, "BIC") Code(0x0d, "BIS") Code(0x0e, "XOR") Code(0x0f, "AND") } // forces the various opcode bodies to be evaluated. kinda weird, but it works so welp. NoOpCodes OneOpCodes TwoOpCodes }