summaryrefslogtreecommitdiff
path: root/src/Opcodes.scala
blob: 7207f48062cb43dc8cb6baa894b7d3a0e1336312 (plain)
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
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
}