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