1use crate::common::{Expr, Ident, Jump, Size, Value};
2
3use std::cmp::PartialEq;
4
5
6#[derive(Debug, Clone)]
15pub struct Register {
16 pub size: Size,
17 pub kind: RegKind
18}
19
20#[derive(Debug, Clone)]
21pub enum RegKind {
22 Static(RegId),
23 Dynamic(RegFamily, Expr),
24}
25
26#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
29pub enum RegId {
30 RAX = 0x00, RCX = 0x01, RDX = 0x02, RBX = 0x03,
32 RSP = 0x04, RBP = 0x05, RSI = 0x06, RDI = 0x07,
33 R8 = 0x08, R9 = 0x09, R10 = 0x0A, R11 = 0x0B,
34 R12 = 0x0C, R13 = 0x0D, R14 = 0x0E, R15 = 0x0F,
35
36 RIP = 0x15,
38
39 AH = 0x24, CH = 0x25, DH = 0x26, BH = 0x27,
41
42 ST0 = 0x30, ST1 = 0x31, ST2 = 0x32, ST3 = 0x33,
44 ST4 = 0x34, ST5 = 0x35, ST6 = 0x36, ST7 = 0x37,
45
46 MMX0 = 0x40, MMX1 = 0x41, MMX2 = 0x42, MMX3 = 0x43,
48 MMX4 = 0x44, MMX5 = 0x45, MMX6 = 0x46, MMX7 = 0x47,
49
50 XMM0 = 0x50, XMM1 = 0x51, XMM2 = 0x52, XMM3 = 0x53,
52 XMM4 = 0x54, XMM5 = 0x55, XMM6 = 0x56, XMM7 = 0x57,
53 XMM8 = 0x58, XMM9 = 0x59, XMM10 = 0x5A, XMM11 = 0x5B,
54 XMM12 = 0x5C, XMM13 = 0x5D, XMM14 = 0x5E, XMM15 = 0x5F,
55
56 ES = 0x60, CS = 0x61, SS = 0x62, DS = 0x63,
58 FS = 0x64, GS = 0x65,
59
60 CR0 = 0x70, CR1 = 0x71, CR2 = 0x72, CR3 = 0x73,
62 CR4 = 0x74, CR5 = 0x75, CR6 = 0x76, CR7 = 0x77,
63 CR8 = 0x78, CR9 = 0x79, CR10 = 0x7A, CR11 = 0x7B,
64 CR12 = 0x7C, CR13 = 0x7D, CR14 = 0x7E, CR15 = 0x7F,
65
66 DR0 = 0x80, DR1 = 0x81, DR2 = 0x82, DR3 = 0x83,
68 DR4 = 0x84, DR5 = 0x85, DR6 = 0x86, DR7 = 0x87,
69 DR8 = 0x88, DR9 = 0x89, DR10 = 0x8A, DR11 = 0x8B,
70 DR12 = 0x8C, DR13 = 0x8D, DR14 = 0x8E, DR15 = 0x8F,
71
72 BND0 = 0x90, BND1 = 0x91, BND2 = 0x92, BND3 = 0x93
74}
75
76#[derive(Debug, PartialOrd, PartialEq, Ord, Eq, Hash, Clone, Copy)]
77pub enum RegFamily {
78 LEGACY = 0,
79 RIP = 1,
80 HIGHBYTE = 2,
81 FP = 3,
82 MMX = 4,
83 XMM = 5,
84 SEGMENT = 6,
85 CONTROL = 7,
86 DEBUG = 8,
87 BOUND = 9
88}
89
90impl Register {
91 pub fn new_static(size: Size, id: RegId) -> Register {
92 Register {size, kind: RegKind::Static(id) }
93 }
94
95 pub fn new_dynamic(size: Size, family: RegFamily, id: Expr) -> Register {
96 Register {size, kind: RegKind::Dynamic(family, id) }
97 }
98
99 pub fn size(&self) -> Size {
100 self.size
101 }
102}
103
104impl RegKind {
105 pub fn code(&self) -> Option<u8> {
106 match *self {
107 RegKind::Static(code) => Some(code.code()),
108 RegKind::Dynamic(_, _) => None
109 }
110 }
111
112 pub fn family(&self) -> RegFamily {
113 match *self {
114 RegKind::Static(code) => code.family(),
115 RegKind::Dynamic(family, _) => family
116 }
117 }
118
119 pub fn is_dynamic(&self) -> bool {
120 match *self {
121 RegKind::Static(_) => false,
122 RegKind::Dynamic(_, _) => true
123 }
124 }
125
126 pub fn is_extended(&self) -> bool {
127 match self.family() {
128 RegFamily::LEGACY |
129 RegFamily::XMM |
130 RegFamily::CONTROL |
131 RegFamily::DEBUG => self.code().unwrap_or(8) > 7,
132 _ => false
133 }
134 }
135
136 pub fn encode(&self) -> u8 {
137 self.code().unwrap_or(0)
138 }
139
140 pub fn from_number(id: u8) -> RegKind {
141 RegKind::Static(RegId::from_number(id))
142 }
143}
144
145impl PartialEq<Register> for Register {
146 fn eq(&self, other: &Register) -> bool {
147 if self.size == other.size {
148 if let RegKind::Static(code) = self.kind {
149 if let RegKind::Static(other_code) = other.kind {
150 return code == other_code
151 }
152 }
153 }
154 false
155 }
156}
157
158impl PartialEq<RegId> for Register {
159 fn eq(&self, other: &RegId) -> bool {
160 self.kind == *other
161 }
162}
163
164impl PartialEq<RegId> for RegKind {
165 fn eq(&self, other: &RegId) -> bool {
166 match *self {
167 RegKind::Static(id) => id == *other,
168 RegKind::Dynamic(_, _) => false
169 }
170 }
171}
172
173impl PartialEq<RegId> for Option<Register> {
175 fn eq(&self, other: &RegId) -> bool {
176 match *self {
177 Some(ref a) => a == other,
178 None => false
179 }
180 }
181}
182
183impl PartialEq<RegId> for Option<RegKind> {
184 fn eq(&self, other: &RegId) -> bool {
185 match *self {
186 Some(ref a) => a == other,
187 None => false
188 }
189 }
190}
191
192impl RegId {
193 pub fn code(self) -> u8 {
194 self as u8 & 0xF
195 }
196
197 pub fn family(self) -> RegFamily {
198 match self as u8 >> 4 {
199 0 => RegFamily::LEGACY,
200 1 => RegFamily::RIP,
201 2 => RegFamily::HIGHBYTE,
202 3 => RegFamily::FP,
203 4 => RegFamily::MMX,
204 5 => RegFamily::XMM,
205 6 => RegFamily::SEGMENT,
206 7 => RegFamily::CONTROL,
207 8 => RegFamily::DEBUG,
208 9 => RegFamily::BOUND,
209 _ => unreachable!()
210 }
211 }
212
213 pub fn from_number(id: u8) -> RegId {
214 match id {
215 0 => RegId::RAX,
216 1 => RegId::RCX,
217 2 => RegId::RDX,
218 3 => RegId::RBX,
219 4 => RegId::RSP,
220 5 => RegId::RBP,
221 6 => RegId::RSI,
222 7 => RegId::RDI,
223 8 => RegId::R8,
224 9 => RegId::R9,
225 10 => RegId::R10,
226 11 => RegId::R11,
227 12 => RegId::R12,
228 13 => RegId::R13,
229 14 => RegId::R14,
230 15 => RegId::R15,
231 _ => panic!("invalid register code {:?}", id)
232 }
233 }
234}
235
236#[derive(Debug)]
241pub enum MemoryRefItem {
242 ScaledRegister(Register, isize),
243 Register(Register),
244 Displacement(Expr)
245}
246
247#[derive(Debug)]
252pub enum RawArg {
253 TypeMappedRaw {
255 nosplit: bool,
256 value_size: Option<Size>,
257 disp_size: Option<Size>,
258 base_reg: Register,
259 scale: Scale,
260 scaled_items: Vec<MemoryRefItem>,
261 attribute: Option<Ident>,
262 },
263 IndirectRaw {
265 nosplit: bool,
266 value_size: Option<Size>,
267 disp_size: Option<Size>,
268 items: Vec<MemoryRefItem>,
269 },
270 Direct {
272 reg: Register
273 },
274 JumpTarget {
276 jump: Jump,
277 size: Option<Size>
278 },
279 IndirectJumpTarget {
281 jump: Jump,
282 size: Option<Size>
283 },
284 Immediate {
286 value: Expr,
287 size: Option<Size>
288 },
289 Invalid
291}
292
293#[derive(Debug)]
294pub enum CleanArg {
295 Indirect {
297 nosplit: bool,
298 size: Option<Size>,
299 disp_size: Option<Size>,
300 base: Option<Register>,
301 index: Option<(Register, isize, Option<Expr>)>,
302 disp: Option<Value>
303 },
304 Direct {
306 reg: Register
307 },
308 JumpTarget {
310 jump: Jump,
311 size: Option<Size>
312 },
313 IndirectJumpTarget {
315 jump: Jump,
316 size: Option<Size>
317 },
318 Immediate {
320 value: Value,
321 }
322}
323
324#[derive(Debug)]
325pub enum SizedArg {
326 Indirect {
329 disp_size: Option<Size>,
330 base: Option<Register>,
331 index: Option<(Register, isize, Option<Expr>)>,
332 disp: Option<Value>
333 },
334 Direct {
336 reg: Register
337 },
338 JumpTarget {
340 jump: Jump,
341 size: Size
342 },
343 IndirectJumpTarget {
345 jump: Jump
346 },
347 Immediate {
349 value: Value,
350 }
351}
352
353#[derive(Debug)]
354pub enum Scale {
355 One,
356 Two,
357 Four,
358 Eight,
359}
360
361#[derive(Debug)]
366pub struct Instruction {
367 pub idents: Vec<Ident>
368}