use core::num::NonZeroUsize;
use gdbstub::arch::{Arch, RegId, Registers};
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct Rv32CoreRegs {
pub x: [u32; 32],
pub pc: u32,
}
impl Registers for Rv32CoreRegs {
type ProgramCounter = u32;
fn pc(&self) -> u32 {
self.pc
}
fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) {
for r in self.x.iter().chain(core::iter::once(&self.pc)) {
for b in r.to_le_bytes() {
write_byte(Some(b));
}
}
}
fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> {
if bytes.len() < 33 * 4 {
return Err(());
}
for (i, chunk) in bytes.chunks(4).enumerate().take(33) {
if chunk.len() < 4 {
break;
}
let v = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
if i < 32 {
self.x[i] = v;
} else {
self.pc = v;
}
}
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Rv32RegId {
Gpr(u8),
Pc,
}
impl RegId for Rv32RegId {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
let size = NonZeroUsize::new(4);
match id {
0..=31 => Some((Rv32RegId::Gpr(id as u8), size)),
32 => Some((Rv32RegId::Pc, size)),
_ => None,
}
}
fn to_raw_id(&self) -> Option<usize> {
Some(match self {
Rv32RegId::Gpr(n) => *n as usize,
Rv32RegId::Pc => 32,
})
}
}
pub enum Rv32 {}
impl Arch for Rv32 {
type Usize = u32;
type Registers = Rv32CoreRegs;
type BreakpointKind = usize;
type RegId = Rv32RegId;
fn target_description_xml() -> Option<&'static str> {
Some(r#"<target version="1.0"><architecture>riscv:rv32</architecture></target>"#)
}
}