1 use crate::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 { gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))17 fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) { 18 macro_rules! write_bytes { 19 ($bytes:expr) => { 20 for b in $bytes { 21 write_byte(Some(*b)) 22 } 23 }; 24 } 25 26 write_bytes!(&self.pc.to_le_bytes()); 27 write_bytes!(&self.sp.to_le_bytes()); 28 write_bytes!(&self.sr.to_le_bytes()); 29 (0..4).for_each(|_| write_byte(None)); // Constant Generator (CG/R3) 30 for reg in self.r.iter() { 31 write_bytes!(®.to_le_bytes()); 32 } 33 } 34 gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>35 fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { 36 // ensure bytes.chunks_exact(2) won't panic 37 if bytes.len() % 2 != 0 { 38 return Err(()); 39 } 40 41 use core::convert::TryInto; 42 let mut regs = bytes 43 .chunks_exact(2) 44 .map(|c| u16::from_le_bytes(c.try_into().unwrap())); 45 46 self.pc = regs.next().ok_or(())?; 47 self.sp = regs.next().ok_or(())?; 48 self.sr = regs.next().ok_or(())?; 49 50 // Constant Generator (CG/R3) should always be 0 51 if regs.next().ok_or(())? != 0 { 52 return Err(()); 53 } 54 55 for reg in self.r.iter_mut() { 56 *reg = regs.next().ok_or(())? 57 } 58 59 if regs.next().is_some() { 60 return Err(()); 61 } 62 63 Ok(()) 64 } 65 } 66