/
arm_core.rs
111 lines (96 loc) · 2.84 KB
/
arm_core.rs
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
use crate::arch::{RegId, Registers};
/// 32-bit ARM core register identifier.
#[derive(Debug, Clone, Copy)]
pub enum ArmCoreRegId {
/// General purpose registers (R0-R12)
Gpr(u8),
/// Stack Pointer (R13)
Sp,
/// Link Register (R14)
Lr,
/// Program Counter (R15)
Pc,
/// Floating point registers (F0-F7)
Fpr(u8),
/// Floating point status
Fps,
/// Current Program Status Register (cpsr)
Cpsr,
}
impl RegId for ArmCoreRegId {
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
match id {
0..=12 => Some((Self::Gpr(id as u8), 4)),
13 => Some((Self::Sp, 4)),
14 => Some((Self::Lr, 4)),
15 => Some((Self::Pc, 4)),
16..=23 => Some((Self::Fpr(id as u8), 4)),
25 => Some((Self::Cpsr, 4)),
_ => None,
}
}
}
/// 32-bit ARM core registers.
///
/// Source: https://github.com/bminor/binutils-gdb/blob/master/gdb/features/arm/arm-core.xml
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct ArmCoreRegs {
/// General purpose registers (R0-R12)
pub r: [u32; 13],
/// Stack Pointer (R13)
pub sp: u32,
/// Link Register (R14)
pub lr: u32,
/// Program Counter (R15)
pub pc: u32,
/// Current Program Status Register (cpsr)
pub cpsr: u32,
}
impl Registers for ArmCoreRegs {
type RegId = ArmCoreRegId;
fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) {
macro_rules! write_bytes {
($bytes:expr) => {
for b in $bytes {
write_byte(Some(*b))
}
};
}
for reg in self.r.iter() {
write_bytes!(®.to_le_bytes());
}
write_bytes!(&self.sp.to_le_bytes());
write_bytes!(&self.lr.to_le_bytes());
write_bytes!(&self.pc.to_le_bytes());
// Floating point registers (unused)
for _ in 0..25 {
(0..4).for_each(|_| write_byte(None))
}
write_bytes!(&self.cpsr.to_le_bytes());
}
fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> {
// ensure bytes.chunks_exact(4) won't panic
if bytes.len() % 4 != 0 {
return Err(());
}
use core::convert::TryInto;
let mut regs = bytes
.chunks_exact(4)
.map(|c| u32::from_le_bytes(c.try_into().unwrap()));
for reg in self.r.iter_mut() {
*reg = regs.next().ok_or(())?
}
self.sp = regs.next().ok_or(())?;
self.lr = regs.next().ok_or(())?;
self.pc = regs.next().ok_or(())?;
// Floating point registers (unused)
for _ in 0..25 {
regs.next().ok_or(())?;
}
self.cpsr = regs.next().ok_or(())?;
if regs.next().is_some() {
return Err(());
}
Ok(())
}
}