1 use core::convert::TryInto;
2 use gdbstub::arch::Registers;
3 
4 /// AArch64 core registers.
5 ///
6 /// Registers from the `org.gnu.gdb.aarch64.core` and `org.gnu.gdb.aarch64.fpu`
7 /// [AArch64 Standard GDB Target Features](https://sourceware.org/gdb/onlinedocs/gdb/AArch64-Features.html).
8 #[derive(Debug, Default, Clone, Eq, PartialEq)]
9 pub struct AArch64CoreRegs {
10     /// General Purpose Registers (X0-X30)
11     pub x: [u64; 31],
12     /// Stack Pointer
13     pub sp: u64,
14     /// Program Counter
15     pub pc: u64,
16     /// Process State (GDB uses the AArch32 CPSR name)
17     pub cpsr: u32,
18     /// FP & SIMD Registers (V0-V31)
19     pub v: [u128; 32],
20     /// Floating-point Control Register
21     pub fpcr: u32,
22     /// Floating-point Status Register
23     pub fpsr: u32,
24 }
25 
26 impl Registers for AArch64CoreRegs {
27     type ProgramCounter = u64;
28 
pc(&self) -> Self::ProgramCounter29     fn pc(&self) -> Self::ProgramCounter {
30         self.pc
31     }
32 
gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))33     fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) {
34         macro_rules! write_bytes {
35             ($var: expr) => {
36                 for b in $var.to_le_bytes() {
37                     write_byte(Some(b))
38                 }
39             };
40         }
41 
42         for reg in self.x.iter() {
43             write_bytes!(reg);
44         }
45         write_bytes!(self.sp);
46         write_bytes!(self.pc);
47         write_bytes!(self.cpsr);
48         for reg in self.v.iter() {
49             write_bytes!(reg);
50         }
51         write_bytes!(self.fpcr);
52         write_bytes!(self.fpsr);
53     }
54 
gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>55     fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> {
56         const CPSR_OFF: usize = core::mem::size_of::<u64>() * 33;
57         const FPSIMD_OFF: usize = CPSR_OFF + core::mem::size_of::<u32>();
58         const FPCR_OFF: usize = FPSIMD_OFF + core::mem::size_of::<u128>() * 32;
59         const END: usize = FPCR_OFF + core::mem::size_of::<u32>() * 2;
60 
61         if bytes.len() < END {
62             return Err(());
63         }
64 
65         let mut regs = bytes[0..CPSR_OFF]
66             .chunks_exact(core::mem::size_of::<u64>())
67             .map(|c| u64::from_le_bytes(c.try_into().unwrap()));
68 
69         for reg in self.x.iter_mut() {
70             *reg = regs.next().ok_or(())?
71         }
72         self.sp = regs.next().ok_or(())?;
73         self.pc = regs.next().ok_or(())?;
74 
75         let mut regs = bytes[CPSR_OFF..FPSIMD_OFF]
76             .chunks_exact(core::mem::size_of::<u32>())
77             .map(|c| u32::from_le_bytes(c.try_into().unwrap()));
78 
79         self.cpsr = regs.next().ok_or(())?;
80 
81         let mut regs = bytes[FPSIMD_OFF..FPCR_OFF]
82             .chunks_exact(core::mem::size_of::<u128>())
83             .map(|c| u128::from_le_bytes(c.try_into().unwrap()));
84 
85         for reg in self.v.iter_mut() {
86             *reg = regs.next().ok_or(())?
87         }
88 
89         let mut regs = bytes[FPCR_OFF..]
90             .chunks_exact(core::mem::size_of::<u32>())
91             .map(|c| u32::from_le_bytes(c.try_into().unwrap()));
92 
93         self.fpcr = regs.next().ok_or(())?;
94         self.fpsr = regs.next().ok_or(())?;
95 
96         Ok(())
97     }
98 }
99