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