summaryrefslogtreecommitdiff
path: root/src/AddressingModes.scala
blob: f51176825d8445d5918768f5e8a69412c0db5a66 (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
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()
    case class Mode(as: Int, name: String, stringifier: String => String) extends AddressingMode(as, name, stringifier) {
      def Mode(as: Int, name: String, stringifier: String => String) = this(as, name, stringifier).tap(modeMap += as -> _)
    }

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

  object PCModes extends Modes {
    Mode(3, "NextWord", reg => s"@PC+ (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
}