1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
package ixee.re.disasm
import ixee.cryptopals.utils.ByteUtils._
import ixee.cryptopals.utils.FunctionUtils._
import scala.collection.mutable.Map
sealed trait Instruction
case class NoOpInst(code: NoOpCode, offset: Int) extends Instruction {
override def toString: String = {
s"$code -> $offset"
}
}
case class OneOpInst(code: OneOpCode, byte: Boolean, dest: Int, addressMode: OneOpAddressing) extends Instruction {
override def toString: String = {
val byteStr = if (byte) ".B" else " "
s"$code$byteStr ${addressMode.stringifyWith(dest)}"
}
}
case class TwoOpInst(code: TwoOpCode, byte: Boolean, src: Int, srcMode: TwoOpSourceAddressing, dest: Int, dstMode: TwoOpDestAddressing) extends Instruction {
override def toString: String = {
val byteStr = if (byte) ".B" else " "
s"$code$byteStr ${srcMode.stringifyWith(src)}, ${dstMode.stringifyWith(dest)}"
}
}
object NoOp {
def info(bytes: (Byte, Byte)): (Int, Int) = {
val op = (bytes._1 & 0xfc) >> 2
val offset = ((bytes._1 & 0x03) << 8) | bytes._2
(op, offset)
}
def apply(bytes: (Byte, Byte)): Option[NoOpInst] = {
val (opVal, offset) = info(bytes)
for {
opcode <- Opcodes.noOp(opVal << 10)
} yield NoOpInst(opcode, offset)
}
}
object OneOp {
def info(bytes: (Byte, Byte)): (Int, Int, Int, Int) = {
val dest = (bytes._2 & 0x0f)
val destMode = ((bytes._2 & 0x30) >> 4)
val byteBit = ((bytes._2 & 0x40) >> 6)
val opcode = ((bytes._1 & 0xff) << 1) | ((bytes._2 & 0x80) >> 7)
(opcode, byteBit, dest, destMode)
}
def apply(bytes: (Byte, Byte)): Option[OneOpInst] = {
val (opVal, byteInstr, dest, rawDestMode) = info(bytes)
for {
opcode <- Opcodes.oneOp(opVal << 7)
isByteOp = if (byteInstr == 1) true else false
destMode <- OneOpAddressingModes(dest, rawDestMode)
} yield OneOpInst(opcode, isByteOp, dest, destMode)
}
}
object TwoOp {
def info(bytes: (Byte, Byte)): (Int, Int, Int, Int, Int, Int) = {
val dest = (bytes._2 & 0x0f)
val sourceMode = (bytes._2 & 0x30) >> 4
val byteBit = (bytes._2 & 0x40) >> 6
val destMode = (bytes._2 & 0x80) >> 7
val source = (bytes._1 & 0x0f)
val opcode = (bytes._1 & 0xf0) >> 4
(opcode, byteBit, source, destMode, dest, sourceMode)
}
def apply(bytes: (Byte, Byte)): Option[TwoOpInst] = {
val (opVal, byteInstr, source, rawDestMode, dest, rawSourceMode) = info(bytes)
for {
opcode <- Opcodes.twoOp(opVal << 12)
isByteOp = if (byteInstr == 1) true else false
destMode <- TwoOpDestAddressingModes(dest, rawDestMode)
sourceMode <- TwoOpSourceAddressingModes(source, rawSourceMode)
} yield TwoOpInst(opcode, isByteOp, source, sourceMode, dest, destMode)
}
}
object Instruction {
def apply(instruction: (Byte, Byte)): Option[Instruction] = NoOp(instruction) orElse OneOp(instruction) orElse TwoOp(instruction)
def littleEndian(instruction: String): Option[Instruction] = {
val instr = Integer.parseInt(instruction, 16)
val hi = (instr & 0xff00) >> 8
val lo = instr & 0x00ff
apply((hi.toByte, lo.toByte))
}
def apply(instruction: String): Option[Instruction] = {
val instr = Integer.parseInt(instruction, 16)
val hi = (instr & 0xff00) >> 8
val lo = instr & 0x00ff
apply((lo.toByte, hi.toByte))
}
def noOp(instruction: (Byte, Byte)): Option[NoOpInst] = NoOp.apply(instruction)
def oneOp(instruction: (Byte, Byte)): Option[OneOpInst] = OneOp.apply(instruction)
def twoOp(instruction: (Byte, Byte)): Option[TwoOpInst] = TwoOp.apply(instruction)
def isNoOp(instruction: (Byte ,Byte)) = noOp(instruction).isDefined
def isOneOp(instruction: (Byte, Byte)) = oneOp(instruction).isDefined
def isTwoOp(instruction: (Byte, Byte)) = twoOp(instruction).isDefined
}
|