summaryrefslogtreecommitdiff
path: root/src/AddressingModes.scala
blob: 30ad69671b50095ec871edb470b68a7f859ebdd2 (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
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package ixee.re.disasm

import ixee.cryptopals.utils.ByteUtils._
import ixee.cryptopals.utils.FunctionUtils._

import scala.collection.mutable.Map

sealed trait AddressingMode {
  def name: String
  def wide: Boolean
  override def toString: String = name
  def nameifyRegister(reg: Int): String = reg match {
    case 0 => "pc"
    case 1 => "sp"
    case 2 => "sr"
    case 3 => "cg"
    case num @ _ => s"r$num"
  }
}

sealed trait NormMode extends AddressingMode {
  def wide = false
  def stringifyWith(reg: Int): String
}

sealed trait WideMode extends AddressingMode {
  def wide = true
  def stringifyWith(reg: Int, word: 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 {
  trait AddressingMode extends OneOpAddressing with TwoOpSourceAddressing

  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 with NormMode {
      modeMap += as -> this
      def stringifyWith(reg: Int): String = stringifier(nameifyRegister(reg))
    }
    case class ExtraByteMode(as: Int, name: String, stringifier: (String, Int) => String) extends AddressingMode with WideMode {
      modeMap += as -> this
      def stringifyWith(reg: Int, const: Int): String = stringifier(nameifyRegister(reg), const)
    }

    def apply(x: Int): Option[AddressingMode] = modeMap.get(x)
  }

  object PCModes extends Modes {
    ExtraByteMode(3, "NextWord", (reg, byte) => s"${if (byte < 0) "-" else ""}0x${"%x".format(Math.abs(byte))}")
  }
  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)
    ExtraByteMode(1, "Indexed", (reg, byte) => s"${if (byte < 0) "-" else ""}0x${"%x".format(Math.abs(byte))}($reg)")
    Mode(2, "RegisterIndirect", reg => s"@$reg")
    Mode(3, "IndirectAutoInc", reg => s"@$reg+")
  }

  PCModes
  SRModes
  CGModes
  General
}


object TwoOpDestAddressingModes {
  trait AddressingMode extends TwoOpDestAddressing

  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()

    case class Mode(as: Int, name: String, stringifier: String => String) extends AddressingMode with NormMode {
      modeMap += as -> this
      def stringifyWith(reg: Int): String = stringifier(nameifyRegister(reg))
    }
    case class ExtraByteMode(as: Int, name: String, stringifier: (String, Int) => String) extends AddressingMode with WideMode {
      modeMap += as -> this
      def stringifyWith(reg: Int, const: Int): String = stringifier(nameifyRegister(reg), const)
    }

    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 {
    ExtraByteMode(1, "Absolute", (reg, byte) => s"&${"%4x".format(byte)}")
  }
  object General extends Modes {
    Mode(0, "RegisterDirect", reg => s"$reg")
    ExtraByteMode(1, "Indexed", (reg, byte) => s"${if (byte < 0) "-" else ""}0x${"%x".format(Math.abs(byte))}($reg)")
  }

  PCModes
  SRModes
  General
}