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