Skip to main content

cranelift_assembler_x64/
xmm.rs

1//! Xmm register operands; see [`Xmm`].
2
3use crate::{AsReg, CodeSink, rex::encode_modrm};
4
5use alloc::string::String;
6
7/// An x64 SSE register (e.g., `%xmm0`).
8#[derive(Clone, Copy, Debug)]
9pub struct Xmm<R: AsReg = u8>(pub(crate) R);
10
11impl<R: AsReg> Xmm<R> {
12    /// Create a new [`Xmm`] register.
13    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.
23    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.
30    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.
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.
46    pub(crate) fn encode_bx_regs(&self) -> (Option<u8>, Option<u8>) {
47        (Some(self.enc()), None)
48    }
49}
50
51impl<R: AsReg> AsRef<R> for Xmm<R> {
52    fn as_ref(&self) -> &R {
53        &self.0
54    }
55}
56
57impl<R: AsReg> AsMut<R> for Xmm<R> {
58    fn as_mut(&mut self) -> &mut R {
59        &mut self.0
60    }
61}
62
63impl<R: AsReg> From<R> for Xmm<R> {
64    fn from(reg: R) -> Xmm<R> {
65        Xmm(reg)
66    }
67}
68
69/// Encode xmm registers.
70pub 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.
93    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}