1 use core::num::NonZeroUsize;
2 use gdbstub::arch::RegId;
3
4 /// TI-MSP430 register identifier.
5 ///
6 /// GDB does not provide a XML file for the MSP430.
7 /// The best file to reference is [msp430-tdep.c](https://github.com/bminor/binutils-gdb/blob/master/gdb/msp430-tdep.c).
8 #[derive(Debug, Clone, Copy)]
9 #[non_exhaustive]
10 pub enum Msp430RegId<U> {
11 /// Program Counter (R0)
12 Pc,
13 /// Stack Pointer (R1)
14 Sp,
15 /// Status Register (R2)
16 Sr,
17 /// Constant Generator (R3)
18 Cg,
19 /// General Purpose Registers (R4-R15)
20 Gpr(u8),
21 #[doc(hidden)]
22 _Size(core::marker::PhantomData<U>),
23 }
24
from_raw_id<U>(id: usize) -> Option<(Msp430RegId<U>, Option<NonZeroUsize>)>25 fn from_raw_id<U>(id: usize) -> Option<(Msp430RegId<U>, Option<NonZeroUsize>)> {
26 let reg = match id {
27 0 => Msp430RegId::Pc,
28 1 => Msp430RegId::Sp,
29 2 => Msp430RegId::Sr,
30 3 => Msp430RegId::Cg,
31 4..=15 => Msp430RegId::Gpr((id as u8) - 4),
32 _ => return None,
33 };
34
35 let ptrsize = core::mem::size_of::<U>();
36 Some((reg, Some(NonZeroUsize::new(ptrsize)?)))
37 }
38
39 impl RegId for Msp430RegId<u16> {
from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)>40 fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
41 from_raw_id::<u16>(id)
42 }
43 }
44
45 impl RegId for Msp430RegId<u32> {
from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)>46 fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
47 from_raw_id::<u32>(id)
48 }
49 }
50
51 #[cfg(test)]
52 mod tests {
53 use gdbstub::arch::RegId;
54 use gdbstub::arch::Registers;
55
test<Rs: Registers, RId: RegId>()56 fn test<Rs: Registers, RId: RegId>() {
57 // Obtain the data length written by `gdb_serialize` by passing a custom
58 // closure.
59 let mut serialized_data_len = 0;
60 let counter = |b: Option<u8>| {
61 if b.is_some() {
62 serialized_data_len += 1;
63 }
64 };
65 Rs::default().gdb_serialize(counter);
66
67 // The `Msp430Regs` implementation does not increment the size for
68 // the CG register since it will always be the constant zero.
69 serialized_data_len += RId::from_raw_id(3).unwrap().1.unwrap().get();
70
71 // Accumulate register sizes returned by `from_raw_id`.
72 let mut i = 0;
73 let mut sum_reg_sizes = 0;
74 while let Some((_, size)) = RId::from_raw_id(i) {
75 sum_reg_sizes += size.unwrap().get();
76 i += 1;
77 }
78
79 assert_eq!(serialized_data_len, sum_reg_sizes);
80 }
81
82 #[test]
test_msp430()83 fn test_msp430() {
84 test::<crate::msp430::reg::Msp430Regs<u16>, crate::msp430::reg::id::Msp430RegId<u16>>()
85 }
86
87 #[test]
test_msp430x()88 fn test_msp430x() {
89 test::<crate::msp430::reg::Msp430Regs<u32>, crate::msp430::reg::id::Msp430RegId<u32>>()
90 }
91 }
92