use gdbstub::arch::Registers;
use gdbstub::internal::LeBytes;
use num_traits::PrimInt;
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct RiscvCoreRegs<U> {
pub x: [U; 32],
pub pc: U,
}
impl<U> Registers for RiscvCoreRegs<U>
where
U: PrimInt + LeBytes + Default + core::fmt::Debug,
{
type ProgramCounter = U;
fn pc(&self) -> Self::ProgramCounter {
self.pc
}
fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) {
macro_rules! write_le_bytes {
($value:expr) => {
let mut buf = [0; 16];
let len = $value.to_le_bytes(&mut buf).unwrap();
let buf = &buf[..len];
for b in buf {
write_byte(Some(*b));
}
};
}
for reg in self.x.iter() {
write_le_bytes!(reg);
}
write_le_bytes!(&self.pc);
}
fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> {
let ptrsize = core::mem::size_of::<U>();
if !bytes.len().is_multiple_of(ptrsize) {
return Err(());
}
let mut regs = bytes
.chunks_exact(ptrsize)
.map(|c| U::from_le_bytes(c).unwrap());
for reg in self.x.iter_mut() {
*reg = regs.next().ok_or(())?
}
self.pc = regs.next().ok_or(())?;
if regs.next().is_some() {
return Err(());
}
Ok(())
}
}