cpufeatures/
x86.rs

1//! x86/x86-64 CPU feature detection support.
2//!
3//! Portable, `no_std`-friendly implementation that relies on the x86 `CPUID`
4//! instruction for feature detection.
5
6// Evaluate the given `$body` expression any of the supplied target features
7// are not enabled. Otherwise returns true.
8//
9// The `$body` expression is not evaluated on SGX targets, and returns false
10// on these targets unless *all* supplied target features are enabled.
11#[macro_export]
12#[doc(hidden)]
13macro_rules! __unless_target_features {
14    ($($tf:tt),+ => $body:expr ) => {{
15        #[cfg(not(all($(target_feature=$tf,)*)))]
16        {
17            #[cfg(not(target_env = "sgx"))]
18            $body
19
20            // CPUID is not available on SGX targets
21            #[cfg(target_env = "sgx")]
22            false
23        }
24
25        #[cfg(all($(target_feature=$tf,)*))]
26        true
27    }};
28}
29
30// Use CPUID to detect the presence of all supplied target features.
31#[macro_export]
32#[doc(hidden)]
33macro_rules! __detect_target_features {
34    ($($tf:tt),+) => {{
35        #[cfg(target_arch = "x86")]
36        use core::arch::x86::{__cpuid, __cpuid_count};
37        #[cfg(target_arch = "x86_64")]
38        use core::arch::x86_64::{__cpuid, __cpuid_count};
39
40        let cr = unsafe {
41            [__cpuid(1), __cpuid_count(7, 0)]
42        };
43
44        $($crate::check!(cr, $tf) & )+ true
45    }};
46}
47
48macro_rules! __expand_check_macro {
49    ($(($name:tt, $i:expr, $reg:ident, $offset:expr)),* $(,)?) => {
50        #[macro_export]
51        #[doc(hidden)]
52        macro_rules! check {
53            $(
54                ($cr:expr, $name) => { ($cr[$i].$reg & (1 << $offset) != 0) };
55            )*
56        }
57    };
58}
59
60__expand_check_macro! {
61    ("mmx", 0, edx, 23),
62    ("sse", 0, edx, 25),
63    ("sse2", 0, edx, 26),
64    ("sse3", 0, ecx, 0),
65    ("pclmulqdq", 0, ecx, 1),
66    ("ssse3", 0, ecx, 9),
67    ("fma", 0, ecx, 12),
68    ("sse4.1", 0, ecx, 19),
69    ("sse4.2", 0, ecx, 20),
70    ("popcnt", 0, ecx, 23),
71    ("aes", 0, ecx, 25),
72    ("avx", 0, ecx, 28),
73    ("rdrand", 0, ecx, 30),
74    ("sgx", 1, ebx, 2),
75    ("bmi1", 1, ebx, 3),
76    ("avx2", 1, ebx, 5),
77    ("bmi2", 1, ebx, 8),
78    ("rdseed", 1, ebx, 18),
79    ("adx", 1, ebx, 19),
80    ("sha", 1, ebx, 29),
81}