1use core::num::NonZeroUsize;
8
9use gdbstub::arch::{Arch, RegId, Registers};
10
11#[derive(Debug, Default, Clone, PartialEq, Eq)]
13pub struct Rv32CoreRegs {
14 pub x: [u32; 32],
15 pub pc: u32,
16}
17
18impl Registers for Rv32CoreRegs {
19 type ProgramCounter = u32;
20
21 fn pc(&self) -> u32 {
22 self.pc
23 }
24
25 fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) {
26 for r in self.x.iter().chain(core::iter::once(&self.pc)) {
27 for b in r.to_le_bytes() {
28 write_byte(Some(b));
29 }
30 }
31 }
32
33 fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> {
34 if bytes.len() < 33 * 4 {
36 return Err(());
37 }
38 for (i, chunk) in bytes.chunks(4).enumerate().take(33) {
39 if chunk.len() < 4 {
40 break;
41 }
42 let v = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
43 if i < 32 {
44 self.x[i] = v;
45 } else {
46 self.pc = v;
47 }
48 }
49 Ok(())
50 }
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
55pub enum Rv32RegId {
56 Gpr(u8),
57 Pc,
58}
59
60impl RegId for Rv32RegId {
61 fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
62 let size = NonZeroUsize::new(4);
63 match id {
64 0..=31 => Some((Rv32RegId::Gpr(id as u8), size)),
65 32 => Some((Rv32RegId::Pc, size)),
66 _ => None,
67 }
68 }
69
70 fn to_raw_id(&self) -> Option<usize> {
71 Some(match self {
72 Rv32RegId::Gpr(n) => *n as usize,
73 Rv32RegId::Pc => 32,
74 })
75 }
76}
77
78pub enum Rv32 {}
80
81impl Arch for Rv32 {
82 type Usize = u32;
83 type Registers = Rv32CoreRegs;
84 type BreakpointKind = usize;
85 type RegId = Rv32RegId;
86
87 fn target_description_xml() -> Option<&'static str> {
88 Some(r#"<target version="1.0"><architecture>riscv:rv32</architecture></target>"#)
90 }
91}