use core::num::NonZeroUsize;
use gdbstub::arch::RegId;
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub enum MipsRegId<U> {
Gpr(u8),
Status,
Lo,
Hi,
Badvaddr,
Cause,
Pc,
Fpr(u8),
Fcsr,
Fir,
Hi1,
Lo1,
Hi2,
Lo2,
Hi3,
Lo3,
Dspctl,
Restart,
#[doc(hidden)]
_Size(core::marker::PhantomData<U>),
}
fn from_raw_id<U>(id: usize) -> Option<(MipsRegId<U>, Option<NonZeroUsize>)> {
let reg = match id {
0..=31 => MipsRegId::Gpr(id as u8),
32 => MipsRegId::Status,
33 => MipsRegId::Lo,
34 => MipsRegId::Hi,
35 => MipsRegId::Badvaddr,
36 => MipsRegId::Cause,
37 => MipsRegId::Pc,
38..=69 => MipsRegId::Fpr((id as u8) - 38),
70 => MipsRegId::Fcsr,
71 => MipsRegId::Fir,
72 => MipsRegId::Hi1,
73 => MipsRegId::Lo1,
74 => MipsRegId::Hi2,
75 => MipsRegId::Lo2,
76 => MipsRegId::Hi3,
77 => MipsRegId::Lo3,
78 => return Some((MipsRegId::Dspctl, Some(NonZeroUsize::new(4)?))),
79 => MipsRegId::Restart,
_ => return None,
};
let ptrsize = core::mem::size_of::<U>();
Some((reg, Some(NonZeroUsize::new(ptrsize)?)))
}
impl RegId for MipsRegId<u32> {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
from_raw_id::<u32>(id)
}
}
impl RegId for MipsRegId<u64> {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
from_raw_id::<u64>(id)
}
}
#[cfg(test)]
mod tests {
use gdbstub::arch::RegId;
use gdbstub::arch::Registers;
fn test<Rs: Registers, RId: RegId>() {
let mut serialized_data_len = 0;
let counter = |b: Option<u8>| {
if b.is_some() {
serialized_data_len += 1;
}
};
Rs::default().gdb_serialize(counter);
let mut i = 0;
let mut sum_reg_sizes = 0;
while let Some((_, size)) = RId::from_raw_id(i) {
sum_reg_sizes += size.unwrap().get();
i += 1;
}
assert_eq!(serialized_data_len, sum_reg_sizes);
}
#[test]
fn test_mips32() {
test::<crate::mips::reg::MipsCoreRegsWithDsp<u32>, crate::mips::reg::id::MipsRegId<u32>>()
}
#[test]
fn test_mips64() {
test::<crate::mips::reg::MipsCoreRegsWithDsp<u64>, crate::mips::reg::id::MipsRegId<u64>>()
}
}