1 //! Xmm register operands; see [`Xmm`].
2 
3 use crate::{AsReg, CodeSink, rex::encode_modrm};
4 
5 use alloc::string::String;
6 
7 /// An x64 SSE register (e.g., `%xmm0`).
8 #[derive(Clone, Copy, Debug)]
9 pub struct Xmm<R: AsReg = u8>(pub(crate) R);
10 
11 impl<R: AsReg> Xmm<R> {
12     /// Create a new [`Xmm`] register.
new(reg: R) -> Self13     pub fn new(reg: R) -> Self {
14         Self(reg)
15     }
16 
17     /// Return the register's hardware encoding; the underlying type `R` _must_
18     /// be a real register at this point.
19     ///
20     /// # Panics
21     ///
22     /// Panics if the register is not a valid Xmm register.
enc(&self) -> u823     pub fn enc(&self) -> u8 {
24         let enc = self.0.enc();
25         assert!(enc < 16, "invalid register: {enc}");
26         enc
27     }
28 
29     /// Return the register name.
to_string(&self) -> String30     pub fn to_string(&self) -> String {
31         self.0.to_string(None)
32     }
33 
34     /// Emit this register as the `r/m` field of a ModR/M byte.
encode_modrm(&self, sink: &mut impl CodeSink, enc_reg: u8)35     pub(crate) fn encode_modrm(&self, sink: &mut impl CodeSink, enc_reg: u8) {
36         sink.put1(encode_modrm(0b11, enc_reg & 0b111, self.enc() & 0b111));
37     }
38 
39     /// Return the registers for encoding the `b` and `x` bits (e.g., in a VEX
40     /// prefix).
41     ///
42     /// This is primarily used for `*Mem` variants (see
43     /// `XmmMem::encode_bx_regs`), but when used on a single `Xmm` register,
44     /// only the `b` bit is set by the topmost bit (the fourth bit) of this
45     /// register. We expect this register to be in the `rm` slot.
encode_bx_regs(&self) -> (Option<u8>, Option<u8>)46     pub(crate) fn encode_bx_regs(&self) -> (Option<u8>, Option<u8>) {
47         (Some(self.enc()), None)
48     }
49 }
50 
51 impl<R: AsReg> AsRef<R> for Xmm<R> {
as_ref(&self) -> &R52     fn as_ref(&self) -> &R {
53         &self.0
54     }
55 }
56 
57 impl<R: AsReg> AsMut<R> for Xmm<R> {
as_mut(&mut self) -> &mut R58     fn as_mut(&mut self) -> &mut R {
59         &mut self.0
60     }
61 }
62 
63 impl<R: AsReg> From<R> for Xmm<R> {
from(reg: R) -> Xmm<R>64     fn from(reg: R) -> Xmm<R> {
65         Xmm(reg)
66     }
67 }
68 
69 /// Encode xmm registers.
70 pub mod enc {
71     pub const XMM0: u8 = 0;
72     pub const XMM1: u8 = 1;
73     pub const XMM2: u8 = 2;
74     pub const XMM3: u8 = 3;
75     pub const XMM4: u8 = 4;
76     pub const XMM5: u8 = 5;
77     pub const XMM6: u8 = 6;
78     pub const XMM7: u8 = 7;
79     pub const XMM8: u8 = 8;
80     pub const XMM9: u8 = 9;
81     pub const XMM10: u8 = 10;
82     pub const XMM11: u8 = 11;
83     pub const XMM12: u8 = 12;
84     pub const XMM13: u8 = 13;
85     pub const XMM14: u8 = 14;
86     pub const XMM15: u8 = 15;
87 
88     /// Return the name of a XMM encoding (`enc`).
89     ///
90     /// # Panics
91     ///
92     /// This function will panic if the encoding is not a valid x64 register.
to_string(enc: u8) -> &'static str93     pub fn to_string(enc: u8) -> &'static str {
94         match enc {
95             XMM0 => "%xmm0",
96             XMM1 => "%xmm1",
97             XMM2 => "%xmm2",
98             XMM3 => "%xmm3",
99             XMM4 => "%xmm4",
100             XMM5 => "%xmm5",
101             XMM6 => "%xmm6",
102             XMM7 => "%xmm7",
103             XMM8 => "%xmm8",
104             XMM9 => "%xmm9",
105             XMM10 => "%xmm10",
106             XMM11 => "%xmm11",
107             XMM12 => "%xmm12",
108             XMM13 => "%xmm13",
109             XMM14 => "%xmm14",
110             XMM15 => "%xmm15",
111             _ => panic!("%invalid{enc}"),
112         }
113     }
114 }
115