1 use core::convert::TryInto; 2 use gdbstub::arch::Registers; 3 use gdbstub::internal::LeBytes; 4 use num_traits::PrimInt; 5 6 /// MIPS registers. 7 /// 8 /// The register width is set to `u32` or `u64` based on the `<U>` type. 9 /// 10 /// Source: <https://github.com/bminor/binutils-gdb/blob/master/gdb/features/mips-cpu.xml> 11 #[derive(Debug, Default, Clone, Eq, PartialEq)] 12 pub struct MipsCoreRegs<U> { 13 /// General purpose registers (R0-R31) 14 pub r: [U; 32], 15 /// Low register (regnum 33) 16 pub lo: U, 17 /// High register (regnum 34) 18 pub hi: U, 19 /// Program Counter (regnum 37) 20 pub pc: U, 21 /// CP0 registers 22 pub cp0: MipsCp0Regs<U>, 23 /// FPU registers 24 pub fpu: MipsFpuRegs<U>, 25 } 26 27 /// MIPS CP0 (coprocessor 0) registers. 28 /// 29 /// Source: <https://github.com/bminor/binutils-gdb/blob/master/gdb/features/mips-cp0.xml> 30 #[derive(Debug, Default, Clone, Eq, PartialEq)] 31 pub struct MipsCp0Regs<U> { 32 /// Status register (regnum 32) 33 pub status: U, 34 /// Bad Virtual Address register (regnum 35) 35 pub badvaddr: U, 36 /// Exception Cause register (regnum 36) 37 pub cause: U, 38 } 39 40 /// MIPS FPU registers. 41 /// 42 /// Source: <https://github.com/bminor/binutils-gdb/blob/master/gdb/features/mips-fpu.xml> 43 #[derive(Debug, Default, Clone, Eq, PartialEq)] 44 pub struct MipsFpuRegs<U> { 45 /// FP registers (F0-F31) starting at regnum 38 46 pub r: [U; 32], 47 /// Floating-point Control Status register 48 pub fcsr: U, 49 /// Floating-point Implementation Register 50 pub fir: U, 51 } 52 53 /// MIPS DSP registers. 54 /// 55 /// Source: <https://github.com/bminor/binutils-gdb/blob/master/gdb/features/mips-dsp.xml> 56 #[derive(Debug, Default, Clone, Eq, PartialEq)] 57 pub struct MipsDspRegs<U> { 58 /// High 1 register (regnum 72) 59 pub hi1: U, 60 /// Low 1 register (regnum 73) 61 pub lo1: U, 62 /// High 2 register (regnum 74) 63 pub hi2: U, 64 /// Low 2 register (regnum 75) 65 pub lo2: U, 66 /// High 3 register (regnum 76) 67 pub hi3: U, 68 /// Low 3 register (regnum 77) 69 pub lo3: U, 70 /// DSP Control register (regnum 78) 71 /// Note: This register will always be 32-bit regardless of the target 72 /// <https://sourceware.org/gdb/current/onlinedocs/gdb/MIPS-Features.html#MIPS-Features> 73 pub dspctl: u32, 74 /// Restart register (regnum 79) 75 pub restart: U, 76 } 77 78 /// MIPS core and DSP registers. 79 /// 80 /// Source: <https://github.com/bminor/binutils-gdb/blob/master/gdb/features/mips-dsp-linux.xml> 81 #[derive(Debug, Default, Clone, Eq, PartialEq)] 82 pub struct MipsCoreRegsWithDsp<U> { 83 /// Core registers 84 pub core: MipsCoreRegs<U>, 85 /// DSP registers 86 pub dsp: MipsDspRegs<U>, 87 } 88 89 impl<U> Registers for MipsCoreRegs<U> 90 where 91 U: PrimInt + LeBytes + Default + core::fmt::Debug, 92 { 93 type ProgramCounter = U; 94 pc(&self) -> Self::ProgramCounter95 fn pc(&self) -> Self::ProgramCounter { 96 self.pc 97 } 98 gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))99 fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) { 100 macro_rules! write_le_bytes { 101 ($value:expr) => { 102 let mut buf = [0; 16]; 103 // infallible (unless digit is a >128 bit number) 104 let len = $value.to_le_bytes(&mut buf).unwrap(); 105 let buf = &buf[..len]; 106 for b in buf { 107 write_byte(Some(*b)); 108 } 109 }; 110 } 111 112 // Write GPRs 113 for reg in self.r.iter() { 114 write_le_bytes!(reg); 115 } 116 117 // Status register is regnum 32 118 write_le_bytes!(&self.cp0.status); 119 120 // Low and high registers are regnums 33 and 34 121 write_le_bytes!(&self.lo); 122 write_le_bytes!(&self.hi); 123 124 // Badvaddr and Cause registers are regnums 35 and 36 125 write_le_bytes!(&self.cp0.badvaddr); 126 write_le_bytes!(&self.cp0.cause); 127 128 // Program Counter is regnum 37 129 write_le_bytes!(&self.pc); 130 131 // Write FPRs 132 for reg in self.fpu.r.iter() { 133 write_le_bytes!(reg); 134 } 135 136 // Write FCSR and FIR registers 137 write_le_bytes!(&self.fpu.fcsr); 138 write_le_bytes!(&self.fpu.fir); 139 } 140 gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>141 fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { 142 let ptrsize = core::mem::size_of::<U>(); 143 144 // Ensure bytes contains enough data for all 72 registers 145 if bytes.len() < ptrsize * 72 { 146 return Err(()); 147 } 148 149 // All core registers are the same size 150 let mut regs = bytes 151 .chunks_exact(ptrsize) 152 .map(|c| U::from_le_bytes(c).unwrap()); 153 154 // Read GPRs 155 for reg in self.r.iter_mut() { 156 *reg = regs.next().ok_or(())? 157 } 158 159 // Read Status register 160 self.cp0.status = regs.next().ok_or(())?; 161 162 // Read Low and High registers 163 self.lo = regs.next().ok_or(())?; 164 self.hi = regs.next().ok_or(())?; 165 166 // Read Badvaddr and Cause registers 167 self.cp0.badvaddr = regs.next().ok_or(())?; 168 self.cp0.cause = regs.next().ok_or(())?; 169 170 // Read the Program Counter 171 self.pc = regs.next().ok_or(())?; 172 173 // Read FPRs 174 for reg in self.fpu.r.iter_mut() { 175 *reg = regs.next().ok_or(())? 176 } 177 178 // Read FCSR and FIR registers 179 self.fpu.fcsr = regs.next().ok_or(())?; 180 self.fpu.fir = regs.next().ok_or(())?; 181 182 Ok(()) 183 } 184 } 185 186 impl<U> Registers for MipsCoreRegsWithDsp<U> 187 where 188 U: PrimInt + LeBytes + Default + core::fmt::Debug, 189 { 190 type ProgramCounter = U; 191 pc(&self) -> Self::ProgramCounter192 fn pc(&self) -> Self::ProgramCounter { 193 self.core.pc 194 } 195 gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))196 fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) { 197 macro_rules! write_le_bytes { 198 ($value:expr) => { 199 let mut buf = [0; 16]; 200 // infallible (unless digit is a >128 bit number) 201 let len = $value.to_le_bytes(&mut buf).unwrap(); 202 let buf = &buf[..len]; 203 for b in buf { 204 write_byte(Some(*b)); 205 } 206 }; 207 } 208 209 // Serialize the core registers first 210 self.core.gdb_serialize(&mut write_byte); 211 212 // Write the DSP registers 213 write_le_bytes!(&self.dsp.hi1); 214 write_le_bytes!(&self.dsp.lo1); 215 write_le_bytes!(&self.dsp.hi2); 216 write_le_bytes!(&self.dsp.lo2); 217 write_le_bytes!(&self.dsp.hi3); 218 write_le_bytes!(&self.dsp.lo3); 219 220 for b in &self.dsp.dspctl.to_le_bytes() { 221 write_byte(Some(*b)); 222 } 223 224 write_le_bytes!(&self.dsp.restart); 225 } 226 gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>227 fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { 228 // Deserialize the core registers first 229 self.core.gdb_deserialize(bytes)?; 230 231 // Ensure bytes contains enough data for all 79 registers of target-width 232 // and the dspctl register which is always 4 bytes 233 let ptrsize = core::mem::size_of::<U>(); 234 if bytes.len() < (ptrsize * 79) + 4 { 235 return Err(()); 236 } 237 238 // Calculate the offsets to the DSP registers based on the ptrsize 239 let dspregs_start = ptrsize * 72; 240 let dspctl_start = ptrsize * 78; 241 242 // Read up until the dspctl register 243 let mut regs = bytes[dspregs_start..dspctl_start] 244 .chunks_exact(ptrsize) 245 .map(|c| U::from_le_bytes(c).unwrap()); 246 247 self.dsp.hi1 = regs.next().ok_or(())?; 248 self.dsp.lo1 = regs.next().ok_or(())?; 249 self.dsp.hi2 = regs.next().ok_or(())?; 250 self.dsp.lo2 = regs.next().ok_or(())?; 251 self.dsp.hi3 = regs.next().ok_or(())?; 252 self.dsp.lo3 = regs.next().ok_or(())?; 253 254 // Dspctl will always be a u32 255 self.dsp.dspctl = 256 u32::from_le_bytes(bytes[dspctl_start..dspctl_start + 4].try_into().unwrap()); 257 258 // Only 4 or 8 bytes should remain to be read 259 self.dsp.restart = U::from_le_bytes( 260 bytes[dspctl_start + 4..] 261 .chunks_exact(ptrsize) 262 .next() 263 .ok_or(())?, 264 ) 265 .unwrap(); 266 267 Ok(()) 268 } 269 } 270