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