diff options
author | Joel Galenson <jgalenson@google.com> | 2021-08-03 21:23:32 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-08-03 21:23:32 +0000 |
commit | bd0fc1143e7ad56e6c189d21b1d5ab24006a8122 (patch) | |
tree | c39c3a7ddb6c612daf46e1921f2ca6e98e1f56b1 /src/ppc/reg/common.rs | |
parent | 861ca6705fbacabc9b281bd5b901be70b9125677 (diff) | |
parent | e54eca01fafc67f5e293bb7b4a3959e9313ba06b (diff) | |
download | gdbstub_arch-bd0fc1143e7ad56e6c189d21b1d5ab24006a8122.tar.gz |
Import gdbstub_arch-0.1.0 am: 52a992f950 am: e54eca01fa
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/gdbstub_arch/+/1783794
Change-Id: I4f8d69e99766caeeb819038fddc0db343d0a2b2a
Diffstat (limited to 'src/ppc/reg/common.rs')
-rw-r--r-- | src/ppc/reg/common.rs | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/ppc/reg/common.rs b/src/ppc/reg/common.rs new file mode 100644 index 0000000..45bdb1c --- /dev/null +++ b/src/ppc/reg/common.rs @@ -0,0 +1,166 @@ +use gdbstub::arch::Registers; + +use super::PpcVector; + +use core::convert::TryInto; + +/// 32-bit PowerPC core registers, FPU registers, and AltiVec SIMD registers. +/// +/// Sources: +/// * https://github.com/bminor/binutils-gdb/blob/master/gdb/features/rs6000/powerpc-altivec32.xml +/// * https://github.com/bminor/binutils-gdb/blob/master/gdb/features/rs6000/power-core.xml +/// * https://github.com/bminor/binutils-gdb/blob/master/gdb/features/rs6000/power-fpu.xml +/// * https://github.com/bminor/binutils-gdb/blob/master/gdb/features/rs6000/power-altivec.xml +#[derive(Debug, Default, Clone, PartialEq)] +pub struct PowerPcCommonRegs { + /// General purpose registers + pub r: [u32; 32], + /// Floating Point registers + pub f: [f64; 32], + /// Program counter + pub pc: u32, + /// Machine state + pub msr: u32, + /// Condition register + pub cr: u32, + /// Link register + pub lr: u32, + /// Count register + pub ctr: u32, + /// Integer exception register + pub xer: u32, + /// Floating-point status and control register + pub fpscr: u32, + /// Vector registers + pub vr: [PpcVector; 32], + /// Vector status and control register + pub vscr: u32, + /// Vector context save register + pub vrsave: u32, +} + +impl Registers for PowerPcCommonRegs { + type ProgramCounter = u32; + + fn pc(&self) -> Self::ProgramCounter { + self.pc + } + + fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) { + macro_rules! write_bytes { + ($bytes:expr) => { + for b in $bytes { + write_byte(Some(*b)) + } + }; + } + + macro_rules! write_regs { + ($($reg:ident),*) => { + $( + write_bytes!(&self.$reg.to_be_bytes()); + )* + } + } + + for reg in &self.r { + write_bytes!(®.to_be_bytes()); + } + + for reg in &self.f { + write_bytes!(®.to_be_bytes()); + } + + write_regs!(pc, msr, cr, lr, ctr, xer, fpscr); + + for ® in &self.vr { + let reg: u128 = reg; + write_bytes!(®.to_be_bytes()); + } + + write_regs!(vscr, vrsave); + } + + fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { + if bytes.len() < 0x3a4 { + return Err(()); + } + + let mut regs = bytes[0..0x80] + .chunks_exact(4) + .map(|x| u32::from_be_bytes(x.try_into().unwrap())); + + for reg in &mut self.r { + *reg = regs.next().ok_or(())?; + } + + let mut regs = bytes[0x80..0x180] + .chunks_exact(8) + .map(|x| f64::from_be_bytes(x.try_into().unwrap())); + + for reg in &mut self.f { + *reg = regs.next().ok_or(())?; + } + + macro_rules! parse_regs { + ($start:literal..$end:literal, $($reg:ident),*) => { + let mut regs = bytes[$start..$end] + .chunks_exact(4) + .map(|x| u32::from_be_bytes(x.try_into().unwrap())); + $( + self.$reg = regs.next().ok_or(())?; + )* + } + } + + parse_regs!(0x180..0x19c, pc, msr, cr, lr, ctr, xer, fpscr); + + let mut regs = bytes[0x19c..0x39c] + .chunks_exact(0x10) + .map(|x| u128::from_be_bytes(x.try_into().unwrap())); + + for reg in &mut self.vr { + *reg = regs.next().ok_or(())?; + } + + parse_regs!(0x39c..0x3a4, vscr, vrsave); + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn ppc_core_round_trip() { + let regs_before = PowerPcCommonRegs { + r: [1; 32], + pc: 2, + msr: 3, + cr: 4, + lr: 5, + ctr: 6, + xer: 7, + fpscr: 8, + f: [9.0; 32], + vr: [52; 32], + vrsave: 10, + vscr: 11, + }; + + let mut data = vec![]; + + regs_before.gdb_serialize(|x| { + data.push(x.unwrap_or(b'x')); + }); + + assert_eq!(data.len(), 0x3a4); + + let mut regs_after = PowerPcCommonRegs::default(); + regs_after.gdb_deserialize(&data).unwrap(); + + assert_eq!(regs_before, regs_after); + } +} |