• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use gdbstub::arch::Registers;
2 use gdbstub::internal::LeBytes;
3 use num_traits::PrimInt;
4 
5 /// TI-MSP430 registers.
6 ///
7 /// The register width is set based on the `<U>` type. For 16-bit MSP430 CPUs
8 /// this should be `u16` and for 20-bit MSP430 CPUs (CPUX) this should be `u32`.
9 #[derive(Debug, Default, Clone, Eq, PartialEq)]
10 pub struct Msp430Regs<U> {
11     /// Program Counter (R0)
12     pub pc: U,
13     /// Stack Pointer (R1)
14     pub sp: U,
15     /// Status Register (R2)
16     pub sr: U,
17     /// General Purpose Registers (R4-R15)
18     pub r: [U; 12],
19 }
20 
21 impl<U> Registers for Msp430Regs<U>
22 where
23     U: PrimInt + LeBytes + Default + core::fmt::Debug,
24 {
25     type ProgramCounter = U;
26 
pc(&self) -> Self::ProgramCounter27     fn pc(&self) -> Self::ProgramCounter {
28         self.pc
29     }
30 
gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))31     fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) {
32         macro_rules! write_le_bytes {
33             ($value:expr) => {
34                 let mut buf = [0; 4];
35                 // infallible (register size a maximum of 32-bits)
36                 let len = $value.to_le_bytes(&mut buf).unwrap();
37                 let buf = &buf[..len];
38                 for b in buf {
39                     write_byte(Some(*b));
40                 }
41             };
42         }
43 
44         write_le_bytes!(&self.pc);
45         write_le_bytes!(&self.sp);
46         write_le_bytes!(&self.sr);
47         (0..core::mem::size_of::<U>()).for_each(|_| write_byte(None)); // Constant Generator (CG/R3)
48         for reg in self.r.iter() {
49             write_le_bytes!(reg);
50         }
51     }
52 
gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>53     fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> {
54         let ptrsize = core::mem::size_of::<U>();
55 
56         // Ensure bytes contains enough data for all 16 registers
57         if bytes.len() < ptrsize * 16 {
58             return Err(());
59         }
60 
61         let mut regs = bytes
62             .chunks_exact(ptrsize)
63             .map(|c| U::from_le_bytes(c).unwrap());
64 
65         self.pc = regs.next().ok_or(())?;
66         self.sp = regs.next().ok_or(())?;
67         self.sr = regs.next().ok_or(())?;
68 
69         // Constant Generator (CG/R3) should always be 0
70         if regs.next().ok_or(())? != U::zero() {
71             return Err(());
72         }
73 
74         for reg in self.r.iter_mut() {
75             *reg = regs.next().ok_or(())?
76         }
77 
78         if regs.next().is_some() {
79             return Err(());
80         }
81 
82         Ok(())
83     }
84 }
85