x64_asm/assembler/resource/operand/
gpr.rs

1use fmt::Formatter;
2use std::fmt;
3
4#[allow(dead_code)]
5#[derive(Eq, Ord, PartialOrd, PartialEq, Debug, Clone, Copy)]
6pub enum GeneralPurposeRegister {
7    // 8bit general-purpose registers
8    AH,
9    BH,
10    CH,
11    DH,
12    AL,
13    BL,
14    CL,
15    DL,
16
17    // 16bit general-purpose registers
18    AX,
19    BX,
20    CX,
21    DX,
22    SI,
23    DI,
24    BP,
25    SP,
26
27    // 32bit general-purpose registers
28    /// Accumulator Register
29    EAX,
30
31    /// (Stack) Base Pointer Register
32    EBP,
33    /// Stack Pointer Register
34    ESP,
35    /// Destination Index Register
36    EDI,
37    /// Source Index Register
38    ESI,
39    /// Data Register
40    EDX,
41    /// Counter Register
42    ECX,
43    /// Base Register
44    EBX,
45
46    // 64bit general-purpose registers
47    /// Accumulator Register
48    RAX,
49
50    /// (Stack) Base Pointer Register
51    RBP,
52    /// Stack Pointer Register
53    RSP,
54    /// Destination Index Register
55    RDI,
56    /// Source Index Register
57    RSI,
58    /// Data Register
59    RDX,
60    /// Counter Register
61    RCX,
62    /// Base Register
63    RBX,
64
65    // x64 appended registers
66    R8,
67    R9,
68    R10,
69    R11,
70    R12,
71    R13,
72    R14,
73    R15,
74}
75
76#[allow(dead_code)]
77impl GeneralPurposeRegister {
78    /// register code
79    pub fn number(&self) -> u8 {
80        match self {
81            GeneralPurposeRegister::AL
82            | GeneralPurposeRegister::AX
83            | GeneralPurposeRegister::EAX
84            | GeneralPurposeRegister::RAX => 0,
85            GeneralPurposeRegister::CL
86            | GeneralPurposeRegister::CX
87            | GeneralPurposeRegister::ECX
88            | GeneralPurposeRegister::RCX => 1,
89            GeneralPurposeRegister::DL
90            | GeneralPurposeRegister::DX
91            | GeneralPurposeRegister::EDX
92            | GeneralPurposeRegister::RDX => 2,
93            GeneralPurposeRegister::BL
94            | GeneralPurposeRegister::BX
95            | GeneralPurposeRegister::EBX
96            | GeneralPurposeRegister::RBX => 3,
97            GeneralPurposeRegister::AH
98            | GeneralPurposeRegister::SP
99            | GeneralPurposeRegister::ESP
100            | GeneralPurposeRegister::RSP => 4,
101            GeneralPurposeRegister::CH
102            | GeneralPurposeRegister::BP
103            | GeneralPurposeRegister::EBP
104            | GeneralPurposeRegister::RBP => 5,
105            GeneralPurposeRegister::DH
106            | GeneralPurposeRegister::SI
107            | GeneralPurposeRegister::ESI
108            | GeneralPurposeRegister::RSI => 6,
109            GeneralPurposeRegister::BH
110            | GeneralPurposeRegister::DI
111            | GeneralPurposeRegister::EDI
112            | GeneralPurposeRegister::RDI => 7,
113
114            GeneralPurposeRegister::R8 => 8,
115            GeneralPurposeRegister::R9 => 9,
116            GeneralPurposeRegister::R10 => 10,
117            GeneralPurposeRegister::R11 => 11,
118            GeneralPurposeRegister::R12 => 12,
119            GeneralPurposeRegister::R13 => 13,
120            GeneralPurposeRegister::R14 => 14,
121            GeneralPurposeRegister::R15 => 15,
122        }
123    }
124
125    pub fn size(&self) -> RegisterSize {
126        match self {
127            // 8bit
128            GeneralPurposeRegister::AL
129            | GeneralPurposeRegister::CL
130            | GeneralPurposeRegister::DL
131            | GeneralPurposeRegister::BL
132            | GeneralPurposeRegister::AH
133            | GeneralPurposeRegister::CH
134            | GeneralPurposeRegister::DH
135            | GeneralPurposeRegister::BH => RegisterSize::S8,
136
137            // 32bit
138            GeneralPurposeRegister::EAX
139            | GeneralPurposeRegister::ECX
140            | GeneralPurposeRegister::EDX
141            | GeneralPurposeRegister::EBX
142            | GeneralPurposeRegister::ESP
143            | GeneralPurposeRegister::EBP
144            | GeneralPurposeRegister::ESI
145            | GeneralPurposeRegister::EDI => RegisterSize::S32,
146            _ => RegisterSize::S64,
147        }
148    }
149
150    /// check whether a register is expanded after x64.
151    /// 拡張されたレジスタかどうかのチェック
152    /// REX prefixに用いる
153    pub fn is_expanded(&self) -> bool {
154        match self {
155            Self::R8
156            | Self::R9
157            | Self::R10
158            | Self::R11
159            | Self::R12
160            | Self::R13
161            | Self::R14
162            | Self::R15 => true,
163            _ => false,
164        }
165    }
166
167    pub fn to_str(&self) -> &'static str {
168        match self {
169            // 8bit general-purpose registers
170            GeneralPurposeRegister::AH => "ah",
171            GeneralPurposeRegister::BH => "bh",
172            GeneralPurposeRegister::CH => "ch",
173            GeneralPurposeRegister::DH => "dh",
174            GeneralPurposeRegister::AL => "al",
175            GeneralPurposeRegister::BL => "bl",
176            GeneralPurposeRegister::CL => "cl",
177            GeneralPurposeRegister::DL => "dl",
178
179            // 16bit general-purpose registers
180            GeneralPurposeRegister::AX => "ax",
181            GeneralPurposeRegister::BX => "bx",
182            GeneralPurposeRegister::CX => "cx",
183            GeneralPurposeRegister::DX => "dx",
184            GeneralPurposeRegister::SP => "sp",
185            GeneralPurposeRegister::BP => "bp",
186            GeneralPurposeRegister::DI => "di",
187            GeneralPurposeRegister::SI => "si",
188
189            // 32bit general-purpose registers
190            Self::EAX => "eax",
191            Self::ECX => "ecx",
192            Self::EDX => "edx",
193            Self::EBX => "ebx",
194            Self::ESP => "esp",
195            Self::EBP => "ebp",
196            Self::ESI => "esi",
197            Self::EDI => "edi",
198
199            // 64bit general-purpose registers
200            Self::RAX => "rax",
201            Self::RCX => "rcx",
202            Self::RDX => "rdx",
203            Self::RBX => "rbx",
204            Self::RSP => "rsp",
205            Self::RBP => "rbp",
206            Self::RSI => "rsi",
207            Self::RDI => "rdi",
208            Self::R8 => "r8",
209            Self::R9 => "r9",
210            Self::R10 => "r10",
211            Self::R11 => "r11",
212            Self::R12 => "r12",
213            Self::R13 => "r13",
214            Self::R14 => "r14",
215            Self::R15 => "r15",
216        }
217    }
218
219    pub fn new_8bit_from_code(code: usize) -> Self {
220        match code {
221            0 => GeneralPurposeRegister::AL,
222            1 => GeneralPurposeRegister::CL,
223            2 => GeneralPurposeRegister::DL,
224            3 => GeneralPurposeRegister::BL,
225            4 => GeneralPurposeRegister::AH,
226            5 => GeneralPurposeRegister::CH,
227            6 => GeneralPurposeRegister::DH,
228            7 => GeneralPurposeRegister::BH,
229            _ => unimplemented!(),
230        }
231    }
232    pub fn new_16bit_from_code(code: usize) -> Self {
233        match code {
234            0 => GeneralPurposeRegister::AX,
235            1 => GeneralPurposeRegister::CX,
236            2 => GeneralPurposeRegister::DX,
237            3 => GeneralPurposeRegister::BX,
238            4 => GeneralPurposeRegister::SP,
239            5 => GeneralPurposeRegister::BP,
240            6 => GeneralPurposeRegister::SI,
241            7 => GeneralPurposeRegister::DI,
242            _ => unimplemented!(),
243        }
244    }
245    pub fn new_32bit_from_code(code: usize) -> Self {
246        match code {
247            0 => GeneralPurposeRegister::EAX,
248            1 => GeneralPurposeRegister::ECX,
249            2 => GeneralPurposeRegister::EDX,
250            3 => GeneralPurposeRegister::EBX,
251            4 => GeneralPurposeRegister::ESP,
252            5 => GeneralPurposeRegister::EBP,
253            6 => GeneralPurposeRegister::ESI,
254            7 => GeneralPurposeRegister::EDI,
255            _ => unimplemented!(),
256        }
257    }
258
259    pub fn new_64bit_from_code(code: usize) -> Self {
260        match code {
261            0 => GeneralPurposeRegister::RAX,
262            1 => GeneralPurposeRegister::RCX,
263            2 => GeneralPurposeRegister::RDX,
264            3 => GeneralPurposeRegister::RBX,
265            4 => GeneralPurposeRegister::RSP,
266            5 => GeneralPurposeRegister::RBP,
267            6 => GeneralPurposeRegister::RSI,
268            7 => GeneralPurposeRegister::RDI,
269            8 => GeneralPurposeRegister::R8,
270            9 => GeneralPurposeRegister::R9,
271            10 => GeneralPurposeRegister::R10,
272            11 => GeneralPurposeRegister::R11,
273            12 => GeneralPurposeRegister::R12,
274            13 => GeneralPurposeRegister::R13,
275            14 => GeneralPurposeRegister::R14,
276            15 => GeneralPurposeRegister::R15,
277            _ => unimplemented!(),
278        }
279    }
280
281    pub fn from_at_string(s: &str) -> Self {
282        match s {
283            // 32bit
284            "%eax" => GeneralPurposeRegister::EAX,
285            "%ecx" => GeneralPurposeRegister::ECX,
286            "%edx" => GeneralPurposeRegister::EDX,
287            "%ebx" => GeneralPurposeRegister::EBX,
288            "%esp" => GeneralPurposeRegister::ESP,
289            "%ebp" => GeneralPurposeRegister::EBP,
290            "%esi" => GeneralPurposeRegister::ESI,
291            "%edi" => GeneralPurposeRegister::EDI,
292
293            // 64bit
294            "%rax" => GeneralPurposeRegister::RAX,
295            "%rcx" => GeneralPurposeRegister::RCX,
296            "%rdx" => GeneralPurposeRegister::RDX,
297            "%rbx" => GeneralPurposeRegister::RBX,
298            "%rsp" => GeneralPurposeRegister::RSP,
299            "%rbp" => GeneralPurposeRegister::RBP,
300            "%rsi" => GeneralPurposeRegister::RSI,
301            "%rdi" => GeneralPurposeRegister::RDI,
302            "%r8" => GeneralPurposeRegister::R8,
303            "%r9" => GeneralPurposeRegister::R9,
304            "%r10" => GeneralPurposeRegister::R10,
305            "%r11" => GeneralPurposeRegister::R11,
306            "%r12" => GeneralPurposeRegister::R12,
307            "%r13" => GeneralPurposeRegister::R13,
308            "%r14" => GeneralPurposeRegister::R14,
309            "%r15" => GeneralPurposeRegister::R15,
310            _ => panic!("{} is not a register", s),
311        }
312    }
313
314    pub fn to_8bit(&self) -> Self {
315        Self::new_8bit_from_code(self.number() as usize)
316    }
317    pub fn to_16bit(&self) -> Self {
318        Self::new_16bit_from_code(self.number() as usize)
319    }
320    pub fn to_32bit(&self) -> Self {
321        Self::new_32bit_from_code(self.number() as usize)
322    }
323
324    pub fn to_64bit(&self) -> Self {
325        Self::new_64bit_from_code(self.number() as usize)
326    }
327
328    pub fn to_intel_string(&self) -> String {
329        self.to_str().to_string()
330    }
331
332    pub fn to_at_string(&self) -> String {
333        format!("%{}", self.to_str())
334    }
335}
336
337impl fmt::Display for GeneralPurposeRegister {
338    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
339        write!(f, "Register::{}", self.to_str())
340    }
341}
342
343#[allow(dead_code)]
344#[derive(Eq, Ord, PartialOrd, PartialEq, Debug, Clone, Copy)]
345pub enum RegisterSize {
346    S8,
347    S16,
348    S32,
349    S64,
350}