1 //! `Register` structs for x86 architectures.
2 
3 use core::convert::TryInto;
4 
5 use crate::arch::Registers;
6 
7 /// `RegId` definitions for x86 architectures.
8 pub mod id;
9 
10 mod core32;
11 mod core64;
12 
13 pub use core32::X86CoreRegs;
14 pub use core64::X86_64CoreRegs;
15 
16 /// 80-bit floating point value
17 pub type F80 = [u8; 10];
18 
19 /// FPU registers
20 #[derive(Debug, Default, Clone, PartialEq)]
21 pub struct X87FpuInternalRegs {
22     /// Floating-point control register
23     pub fctrl: u32,
24     /// Floating-point status register
25     pub fstat: u32,
26     /// Tag word
27     pub ftag: u32,
28     /// FPU instruction pointer segment
29     pub fiseg: u32,
30     /// FPU intstruction pointer offset
31     pub fioff: u32,
32     /// FPU operand segment
33     pub foseg: u32,
34     /// FPU operand offset
35     pub fooff: u32,
36     /// Floating-point opcode
37     pub fop: u32,
38 }
39 
40 impl Registers for X87FpuInternalRegs {
gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>))41     fn gdb_serialize(&self, mut write_byte: impl FnMut(Option<u8>)) {
42         macro_rules! write_bytes {
43             ($bytes:expr) => {
44                 for b in $bytes {
45                     write_byte(Some(*b))
46                 }
47             };
48         }
49 
50         // Note: GDB section names don't make sense unless you read x87 FPU section 8.1:
51         // https://web.archive.org/web/20150123212110/http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-1-manual.pdf
52         write_bytes!(&self.fctrl.to_le_bytes());
53         write_bytes!(&self.fstat.to_le_bytes());
54         write_bytes!(&self.ftag.to_le_bytes());
55         write_bytes!(&self.fiseg.to_le_bytes());
56         write_bytes!(&self.fioff.to_le_bytes());
57         write_bytes!(&self.foseg.to_le_bytes());
58         write_bytes!(&self.fooff.to_le_bytes());
59         write_bytes!(&self.fop.to_le_bytes());
60     }
61 
gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>62     fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> {
63         if bytes.len() != 0x20 {
64             return Err(());
65         }
66 
67         let mut regs = bytes
68             .chunks_exact(4)
69             .map(|x| u32::from_le_bytes(x.try_into().unwrap()));
70 
71         self.fctrl = regs.next().ok_or(())?;
72         self.fstat = regs.next().ok_or(())?;
73         self.ftag = regs.next().ok_or(())?;
74         self.fiseg = regs.next().ok_or(())?;
75         self.fioff = regs.next().ok_or(())?;
76         self.foseg = regs.next().ok_or(())?;
77         self.fooff = regs.next().ok_or(())?;
78         self.fop = regs.next().ok_or(())?;
79 
80         Ok(())
81     }
82 }
83