Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/assembler-x64/meta/src/dsl/features.rs
1693 views
1
//! A DSL for describing x64 CPU features.
2
3
use core::fmt;
4
use std::ops::{BitAnd, BitOr};
5
6
/// A boolean term of CPU features.
7
///
8
/// An instruction is valid when the boolean term (a recursive tree of `AND` and
9
/// `OR` terms) is satisfied.
10
///
11
/// ```
12
/// # use cranelift_assembler_x64_meta::dsl::{Features, Feature};
13
/// let fs = Feature::_64b | Feature::compat;
14
/// assert_eq!(fs.to_string(), "(_64b | compat)");
15
/// ```
16
#[derive(PartialEq)]
17
pub enum Features {
18
And(Box<Features>, Box<Features>),
19
Or(Box<Features>, Box<Features>),
20
Feature(Feature),
21
}
22
23
impl Features {
24
pub(crate) fn is_sse(&self) -> bool {
25
use Feature::*;
26
match self {
27
Features::And(lhs, rhs) => lhs.is_sse() || rhs.is_sse(),
28
Features::Or(lhs, rhs) => lhs.is_sse() || rhs.is_sse(),
29
Features::Feature(feature) => {
30
matches!(feature, sse | sse2 | sse3 | ssse3 | sse41 | sse42)
31
}
32
}
33
}
34
}
35
36
impl fmt::Display for Features {
37
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38
match self {
39
Features::And(lhs, rhs) => write!(f, "({lhs} & {rhs})"),
40
Features::Or(lhs, rhs) => write!(f, "({lhs} | {rhs})"),
41
Features::Feature(feature) => write!(f, "{feature:#?}"),
42
}
43
}
44
}
45
46
impl<T> BitOr<T> for Features
47
where
48
T: Into<Features>,
49
{
50
type Output = Features;
51
fn bitor(self, rhs: T) -> Self::Output {
52
Features::Or(Box::new(self), Box::new(rhs.into()))
53
}
54
}
55
56
impl<T> BitAnd<T> for Features
57
where
58
T: Into<Features>,
59
{
60
type Output = Features;
61
fn bitand(self, rhs: T) -> Self::Output {
62
Features::And(Box::new(self), Box::new(rhs.into()))
63
}
64
}
65
66
/// A CPU feature.
67
///
68
/// IA-32e mode is the typical mode of operation for modern 64-bit x86
69
/// processors. It consists of two sub-modes:
70
/// - __64-bit mode__: uses the full 64-bit address space
71
/// - __compatibility mode__: allows use of legacy 32-bit code
72
///
73
/// Other features listed here should match the __CPUID Feature Flags__ column
74
/// of the instruction tables of the x64 reference manual.
75
#[derive(Clone, Copy, Debug, PartialEq)]
76
#[allow(non_camel_case_types, reason = "makes DSL definitions easier to read")]
77
pub enum Feature {
78
_64b,
79
compat,
80
sse,
81
sse2,
82
sse3,
83
ssse3,
84
sse41,
85
sse42,
86
bmi1,
87
bmi2,
88
lzcnt,
89
popcnt,
90
avx,
91
avx2,
92
avx512f,
93
avx512vl,
94
avx512dq,
95
avx512bitalg,
96
avx512vbmi,
97
cmpxchg16b,
98
fma,
99
}
100
101
/// List all CPU features.
102
///
103
/// It is critical that this list contains _all_ variants of the [`Feature`]
104
/// `enum`. We use this list here in the `meta` level so that we can accurately
105
/// transcribe each variant to an `enum` available in the generated layer above.
106
/// If this list is incomplete, we will (fortunately) see compile errors for
107
/// generated functions that use the missing variants.
108
pub const ALL_FEATURES: &[Feature] = &[
109
Feature::_64b,
110
Feature::compat,
111
Feature::sse,
112
Feature::sse2,
113
Feature::sse3,
114
Feature::ssse3,
115
Feature::sse41,
116
Feature::sse42,
117
Feature::bmi1,
118
Feature::bmi2,
119
Feature::lzcnt,
120
Feature::popcnt,
121
Feature::avx,
122
Feature::avx2,
123
Feature::avx512f,
124
Feature::avx512vl,
125
Feature::avx512dq,
126
Feature::avx512bitalg,
127
Feature::avx512vbmi,
128
Feature::cmpxchg16b,
129
Feature::fma,
130
];
131
132
impl fmt::Display for Feature {
133
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134
fmt::Debug::fmt(self, f)
135
}
136
}
137
138
impl From<Feature> for Features {
139
fn from(f: Feature) -> Self {
140
Features::Feature(f)
141
}
142
}
143
144
impl<T> BitAnd<T> for Feature
145
where
146
T: Into<Features>,
147
{
148
type Output = Features;
149
fn bitand(self, rhs: T) -> Self::Output {
150
Features::from(self) & rhs.into()
151
}
152
}
153
154
impl<T> BitOr<T> for Feature
155
where
156
T: Into<Features>,
157
{
158
type Output = Features;
159
fn bitor(self, rhs: T) -> Self::Output {
160
Features::from(self) | rhs.into()
161
}
162
}
163
164