1 use gdbstub::arch::Registers; 2 3 /// 16-bit TI-MSP430 registers. 4 #[derive(Debug, Default, Clone, Eq, PartialEq)] 5 pub struct Msp430Regs { 6 /// Program Counter (R0) 7 pub pc: u16, 8 /// Stack Pointer (R1) 9 pub sp: u16, 10 /// Status Register (R2) 11 pub sr: u16, 12 /// General Purpose Registers (R4-R15) 13 pub r: [u16; 11], 14 } 15 16 impl Registers for Msp430Regs { 17 type ProgramCounter = u16; 18 pc(&self) -> Self::ProgramCounter19 fn pc(&self) -> Self::ProgramCounter { 20 self.pc 21 } 22 gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))23 fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) { 24 macro_rules! write_bytes { 25 ($bytes:expr) => { 26 for b in $bytes { 27 write_byte(Some(*b)) 28 } 29 }; 30 } 31 32 write_bytes!(&self.pc.to_le_bytes()); 33 write_bytes!(&self.sp.to_le_bytes()); 34 write_bytes!(&self.sr.to_le_bytes()); 35 (0..4).for_each(|_| write_byte(None)); // Constant Generator (CG/R3) 36 for reg in self.r.iter() { 37 write_bytes!(®.to_le_bytes()); 38 } 39 } 40 gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>41 fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { 42 // ensure bytes.chunks_exact(2) won't panic 43 if bytes.len() % 2 != 0 { 44 return Err(()); 45 } 46 47 use core::convert::TryInto; 48 let mut regs = bytes 49 .chunks_exact(2) 50 .map(|c| u16::from_le_bytes(c.try_into().unwrap())); 51 52 self.pc = regs.next().ok_or(())?; 53 self.sp = regs.next().ok_or(())?; 54 self.sr = regs.next().ok_or(())?; 55 56 // Constant Generator (CG/R3) should always be 0 57 if regs.next().ok_or(())? != 0 { 58 return Err(()); 59 } 60 61 for reg in self.r.iter_mut() { 62 *reg = regs.next().ok_or(())? 63 } 64 65 if regs.next().is_some() { 66 return Err(()); 67 } 68 69 Ok(()) 70 } 71 } 72