Path: blob/main/cranelift/assembler-x64/src/evex.rs
1692 views
//! Encoding logic for EVEX instructions.12use crate::api::CodeSink;34/// EVEX prefix is always 4 bytes, byte 0 is 0x625pub struct EvexPrefix {6byte1: u8,7byte2: u8,8byte3: u8,9}1011/// The EVEX prefix only ever uses the top bit (bit 3--the fourth bit) of any12/// HW-encoded register.13#[inline(always)]14fn invert_top_bit(enc: u8) -> u8 {15(!(enc >> 3)) & 116}1718// ┌───┬───┬───┬───┬───┬───┬───┬───┐19// Byte 1: │ R │ X │ B │ R'│ 0 │ 0 │ m │ m │20// ├───┼───┼───┼───┼───┼───┼───┼───┤21// Byte 2: │ W │ v │ v │ v │ v │ 1 │ p │ p │22// ├───┼───┼───┼───┼───┼───┼───┼───┤23// Byte 3: │ z │ L'│ L │ b │ V'│ a │ a │ a │24// └───┴───┴───┴───┴───┴───┴───┴───┘2526impl EvexPrefix {27/// Construct the [`EvexPrefix`] for an instruction.28pub fn new(29reg: u8,30vvvv: u8,31(b, x): (Option<u8>, Option<u8>),32ll: u8,33pp: u8,34mmm: u8,35w: bool,36broadcast: bool,37) -> Self {38let r = invert_top_bit(reg);39let r_prime = invert_top_bit(reg >> 1);40let b = invert_top_bit(b.unwrap_or(0));41let x = invert_top_bit(x.unwrap_or(0));42let vvvv_value = !vvvv & 0b1111;43let v_prime = !(vvvv >> 4) & 0b1;4445// byte146debug_assert!(mmm <= 0b111);47let byte1 = r << 7 | x << 6 | b << 5 | r_prime << 4 | mmm;4849// byte250debug_assert!(vvvv <= 0b11111);51debug_assert!(pp <= 0b11);52let byte2 = (w as u8) << 7 | vvvv_value << 3 | 0b100 | (pp & 0b11);5354// byte355debug_assert!(ll < 0b11, "bits 11b are reserved (#UD); must fit in 2 bits");56let aaa = 0b000; // Force k0 masking register for now; eventually this should be configurable (TODO).57let z = 0; // Masking kind bit; not used yet (TODO) so we default to merge-masking.58let byte3 = z | ll << 5 | (broadcast as u8) << 4 | v_prime << 3 | aaa;5960Self {61byte1,62byte2,63byte3,64}65}6667/// Construct the [`EvexPrefix`] for an instruction.68pub fn two_op(69reg: u8,70(b, x): (Option<u8>, Option<u8>),71ll: u8,72pp: u8,73mmm: u8,74w: bool,75broadcast: bool,76) -> Self {77EvexPrefix::new(reg, 0, (b, x), ll, pp, mmm, w, broadcast)78}7980/// Construct the [`EvexPrefix`] for an instruction.81pub fn three_op(82reg: u8,83vvvv: u8,84(b, x): (Option<u8>, Option<u8>),85ll: u8,86pp: u8,87mmm: u8,88w: bool,89broadcast: bool,90) -> Self {91EvexPrefix::new(reg, vvvv, (b, x), ll, pp, mmm, w, broadcast)92}9394pub(crate) fn encode(&self, sink: &mut impl CodeSink) {95sink.put1(0x62);96sink.put1(self.byte1);97sink.put1(self.byte2);98sink.put1(self.byte3);99}100}101102103