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