1use crate::prelude::*;
2use crate::{cpu_arch_state, CPUArchPtr};
3
4use strum::IntoEnumIterator;
5use strum_macros::{EnumIter, EnumString, ToString};
6
7#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[repr(transparent)]
12pub struct SyscallPc(target_ulong);
13
14impl SyscallPc {
15 pub fn pc(self) -> target_ulong {
16 self.0
17 }
18}
19
20impl Reg {
21 pub fn iter() -> RegIter {
23 <Self as IntoEnumIterator>::iter()
24 }
25}
26
27#[cfg(feature = "i386")]
32#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, EnumIter, ToString)]
33pub enum Reg {
34 EAX = 0,
35 ECX = 1,
36 EDX = 2,
37 EBX = 3,
38 ESP = 4,
39 EBP = 5,
40 ESI = 6,
41 EDI = 7,
42}
43
44#[cfg(feature = "i386")]
46static RET_REGS: &'static [Reg] = &[Reg::EAX];
47
48#[cfg(feature = "x86_64")]
51#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, EnumIter, ToString)]
52pub enum Reg {
53 RAX = 0,
54 RCX = 1,
55 RDX = 2,
56 RBX = 3,
57 RSP = 4,
58 RBP = 5,
59 RSI = 6,
60 RDI = 7,
61 R8 = 8,
62 R9 = 9,
63 R10 = 10,
64 R11 = 11,
65 R12 = 12,
66 R13 = 13,
67 R14 = 14,
68 R15 = 15,
69}
70
71#[cfg(feature = "x86_64")]
73static RET_REGS: &'static [Reg] = &[Reg::RAX];
74
75#[cfg(feature = "arm")]
77#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, EnumIter, ToString)]
78pub enum Reg {
79 R0 = 0,
80 R1 = 1,
81 R2 = 2,
82 R3 = 3,
83 R4 = 4,
84 R5 = 5,
85 R6 = 6,
86 R7 = 7,
87 R8 = 8,
88 R9 = 9,
89 R10 = 10,
90 R11 = 11,
91 R12 = 12,
92 LR = 14,
93 SP = 13,
94 IP = 15,
95}
96
97#[cfg(feature = "arm")]
99static RET_REGS: &'static [Reg] = &[Reg::R0, Reg::R1, Reg::R2, Reg::R3];
100
101#[cfg(feature = "aarch64")]
103#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, EnumIter, ToString)]
104pub enum Reg {
105 X0 = 0,
106 X1 = 1,
107 X2 = 2,
108 X3 = 3,
109 X4 = 4,
110 X5 = 5,
111 X6 = 6,
112 X7 = 7,
113 X8 = 8,
114 X9 = 9,
115 X10 = 10,
116 X11 = 11,
117 X12 = 12,
118 LR = 13,
119 SP = 14,
120 IP = 15,
121}
122
123#[cfg(feature = "aarch64")]
125static RET_REGS: &'static [Reg] = &[Reg::X0, Reg::X1, Reg::X2, Reg::X3];
126
127#[cfg(any(
129 feature = "mips",
130 feature = "mipsel",
131 feature = "mips64",
132 feature = "mips64el"
133))]
134#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, EnumIter, ToString)]
135pub enum Reg {
136 ZERO = 0,
137 AT = 1,
138 V0 = 2,
139 V1 = 3,
140 A0 = 4,
141 A1 = 5,
142 A2 = 6,
143 A3 = 7,
144 T0 = 8,
145 T1 = 9,
146 T2 = 10,
147 T3 = 11,
148 T4 = 12,
149 T5 = 13,
150 T6 = 14,
151 T7 = 15,
152 S0 = 16,
153 S1 = 17,
154 S2 = 18,
155 S3 = 19,
156 S4 = 20,
157 S5 = 21,
158 S6 = 22,
159 S7 = 23,
160 T8 = 24,
161 T9 = 25,
162 K0 = 26,
163 K1 = 27,
164 GP = 28,
165 SP = 29,
166 FP = 30,
167 RA = 31,
168}
169
170#[cfg(any(
172 feature = "mips",
173 feature = "mipsel",
174 feature = "mips64",
175 feature = "mips64el"
176))]
177static RET_REGS: &'static [Reg] = &[Reg::V0, Reg::V1];
178
179#[cfg(feature = "ppc")]
182#[derive(Debug, Copy, Clone, PartialEq, Eq, EnumString, EnumIter, ToString)]
183pub enum Reg {
184 R0 = 0,
185 R1 = 1,
186 R2 = 2,
187 R3 = 3,
188 R4 = 4,
189 R5 = 5,
190 R6 = 6,
191 R7 = 7,
192 R8 = 8,
193 R9 = 9,
194 R10 = 10,
195 R11 = 11,
196 R12 = 12,
197 R13 = 13,
198 R14 = 14,
199 R15 = 15,
200 R16 = 16,
201 R17 = 17,
202 R18 = 18,
203 R19 = 19,
204 R20 = 20,
205 R21 = 21,
206 R22 = 22,
207 R23 = 23,
208 R24 = 24,
209 R25 = 25,
210 R26 = 26,
211 R27 = 27,
212 R28 = 28,
213 R29 = 29,
214 R30 = 30,
215 R31 = 31,
216 LR = 100, }
218
219#[cfg(feature = "ppc")]
221static RET_REGS: &'static [Reg] = &[Reg::R3, Reg::R4];
222
223pub fn reg_sp() -> Reg {
227 #[cfg(feature = "i386")]
228 return Reg::ESP;
229
230 #[cfg(feature = "x86_64")]
231 return Reg::RSP;
232
233 #[cfg(any(
234 feature = "arm",
235 feature = "aarch64",
236 feature = "mips",
237 feature = "mipsel",
238 feature = "mips64",
239 feature = "mips64el"
240 ))]
241 return Reg::SP;
242
243 #[cfg(any(feature = "ppc"))]
244 return Reg::R1;
245}
246
247pub fn reg_ret_val() -> &'static [Reg] {
250 return &RET_REGS;
251}
252
253pub fn reg_ret_addr() -> Option<Reg> {
255 #[cfg(feature = "i386")]
256 return None;
257
258 #[cfg(feature = "x86_64")]
259 return None;
260
261 #[cfg(any(feature = "arm", feature = "aarch64", feature = "ppc"))]
262 return Some(Reg::LR);
263
264 #[cfg(any(
265 feature = "mips",
266 feature = "mipsel",
267 feature = "mips64",
268 feature = "mips64el"
269 ))]
270 return Some(Reg::RA);
271}
272
273pub fn get_reg<T: Into<Reg>>(cpu: &CPUState, reg: T) -> target_ulong {
275 let cpu_arch = cpu_arch_state!(cpu);
276 let val;
277
278 #[cfg(any(feature = "i386", feature = "x86_64", feature = "arm"))]
279 unsafe {
280 val = (*cpu_arch).regs[reg.into() as usize];
281 }
282
283 #[cfg(feature = "aarch64")]
284 unsafe {
285 val = (*cpu_arch).xregs[reg.into() as usize];
286 }
287
288 #[cfg(any(
289 feature = "mips",
290 feature = "mipsel",
291 feature = "mips64",
292 feature = "mips64el"
293 ))]
294 unsafe {
295 val = (*cpu_arch).active_tc.gpr[reg.into() as usize];
296 }
297
298 #[cfg(any(feature = "ppc"))]
299 unsafe {
300 let reg_enum = reg.into();
301 if reg_enum == Reg::LR {
302 val = (*cpu_arch).lr;
303 } else {
304 val = (*cpu_arch).gpr[reg_enum as usize];
305 }
306 }
307
308 val
309}
310
311pub fn set_reg<T: Into<Reg>>(cpu: &CPUState, reg: T, val: target_ulong) {
313 let cpu_arch = cpu_arch_state!(cpu);
314
315 #[cfg(any(feature = "i386", feature = "x86_64", feature = "arm"))]
316 unsafe {
317 (*cpu_arch).regs[reg.into() as usize] = val;
318 }
319
320 #[cfg(any(
321 feature = "mips",
322 feature = "mipsel",
323 feature = "mips64",
324 feature = "mips64el"
325 ))]
326 unsafe {
327 (*cpu_arch).active_tc.gpr[reg.into() as usize] = val;
328 }
329
330 #[cfg(any(feature = "ppc"))]
331 unsafe {
332 let reg_enum = reg.into();
333 if reg_enum == Reg::LR {
334 (*cpu_arch).lr = val;
335 } else {
336 (*cpu_arch).gpr[reg_enum as usize] = val;
337 }
338 }
339
340 #[cfg(feature = "aarch64")]
341 unsafe {
342 (*cpu_arch).xregs[reg.into() as usize] = val;
343 }
344}
345
346pub fn get_pc(cpu: &CPUState) -> target_ulong {
347 let cpu_arch = cpu_arch_state!(cpu);
348 let val;
349
350 #[cfg(any(feature = "x86_64", feature = "i386"))]
351 unsafe {
352 val = (*cpu_arch).eip;
353 }
354
355 #[cfg(feature = "arm")]
356 unsafe {
357 val = (*cpu_arch).regs[15];
358 }
359
360 #[cfg(feature = "aarch64")]
361 unsafe {
362 val = (*cpu_arch).pc;
363 }
364
365 #[cfg(feature = "ppc")]
366 unsafe {
367 val = (*cpu_arch).nip;
368 }
369
370 #[cfg(any(
371 feature = "mips",
372 feature = "mipsel",
373 feature = "mips64",
374 feature = "mips64el"
375 ))]
376 unsafe {
377 val = (*cpu_arch).active_tc.PC;
378 }
379
380 val
381}
382
383pub fn set_pc(cpu: &mut CPUState, pc: target_ulong) {
384 let cpu_arch = cpu_arch_state!(cpu);
385
386 #[cfg(any(feature = "x86_64", feature = "i386"))]
387 unsafe {
388 (*cpu_arch).eip = pc;
389 }
390
391 #[cfg(feature = "arm")]
392 unsafe {
393 (*cpu_arch).regs[15] = pc;
394 }
395
396 #[cfg(feature = "aarch64")]
397 unsafe {
398 (*cpu_arch).pc = pc;
399 }
400
401 #[cfg(feature = "ppc")]
402 unsafe {
403 (*cpu_arch).nip = pc;
404 }
405
406 #[cfg(any(
407 feature = "mips",
408 feature = "mipsel",
409 feature = "mips64",
410 feature = "mips64el"
411 ))]
412 unsafe {
413 (*cpu_arch).active_tc.PC = pc;
414 }
415}
416
417pub fn dump_regs(cpu: &CPUState) {
421 for reg in Reg::iter() {
422 println!("{:?}:\t0x{:016x}", reg, get_reg(cpu, reg));
423 }
424}