• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use num_traits::PrimInt;
2 
3 use gdbstub::arch::Registers;
4 use gdbstub::internal::LeBytes;
5 
6 /// RISC-V Integer registers.
7 ///
8 /// The register width is set to `u32` or `u64` based on the `<U>` type.
9 ///
10 /// Useful links:
11 /// * [GNU binutils-gdb XML descriptions](https://github.com/bminor/binutils-gdb/blob/master/gdb/features/riscv)
12 /// * [riscv-tdep.h](https://github.com/bminor/binutils-gdb/blob/master/gdb/riscv-tdep.h)
13 #[derive(Debug, Default, Clone, PartialEq)]
14 pub struct RiscvCoreRegs<U> {
15     /// General purpose registers (x0-x31)
16     pub x: [U; 32],
17     /// Program counter
18     pub pc: U,
19 }
20 
21 impl<U> Registers for RiscvCoreRegs<U>
22 where
23     U: PrimInt + LeBytes + Default + core::fmt::Debug,
24 {
25     type ProgramCounter = U;
26 
pc(&self) -> Self::ProgramCounter27     fn pc(&self) -> Self::ProgramCounter {
28         self.pc
29     }
30 
gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))31     fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) {
32         macro_rules! write_le_bytes {
33             ($value:expr) => {
34                 let mut buf = [0; 16];
35                 // infallible (unless digit is a >128 bit number)
36                 let len = $value.to_le_bytes(&mut buf).unwrap();
37                 let buf = &buf[..len];
38                 for b in buf {
39                     write_byte(Some(*b));
40                 }
41             };
42         }
43 
44         // Write GPRs
45         for reg in self.x.iter() {
46             write_le_bytes!(reg);
47         }
48 
49         // Program Counter is regnum 33
50         write_le_bytes!(&self.pc);
51     }
52 
gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>53     fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> {
54         let ptrsize = core::mem::size_of::<U>();
55 
56         // ensure bytes.chunks_exact(ptrsize) won't panic
57         if bytes.len() % ptrsize != 0 {
58             return Err(());
59         }
60 
61         let mut regs = bytes
62             .chunks_exact(ptrsize)
63             .map(|c| U::from_le_bytes(c).unwrap());
64 
65         // Read GPRs
66         for reg in self.x.iter_mut() {
67             *reg = regs.next().ok_or(())?
68         }
69         self.pc = regs.next().ok_or(())?;
70 
71         if regs.next().is_some() {
72             return Err(());
73         }
74 
75         Ok(())
76     }
77 }
78