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