1#[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 #[cfg(target_env = "sgx")]
22 false
23 }
24
25 #[cfg(all($(target_feature=$tf,)*))]
26 true
27 }};
28}
29
30#[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, CpuidResult};
37 #[cfg(target_arch = "x86_64")]
38 use core::arch::x86_64::{__cpuid, __cpuid_count, CpuidResult};
39
40 #[inline(never)]
46 unsafe fn cpuid(leaf: u32) -> CpuidResult {
47 __cpuid(leaf)
48 }
49
50 #[inline(never)]
51 unsafe fn cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
52 __cpuid_count(leaf, sub_leaf)
53 }
54
55 let cr = unsafe {
56 [cpuid(1), cpuid_count(7, 0)]
57 };
58
59 $($crate::check!(cr, $tf) & )+ true
60 }};
61}
62
63macro_rules! __expand_check_macro {
64 ($(($name:tt $(, $i:expr, $reg:ident, $offset:expr)*)),* $(,)?) => {
65 #[macro_export]
66 #[doc(hidden)]
67 macro_rules! check {
68 $(
69 ($cr:expr, $name) => {
70 true
71 $(
72 & ($cr[$i].$reg & (1 << $offset) != 0)
73 )*
74 };
75 )*
76 }
77 };
78}
79
80__expand_check_macro! {
85 ("mmx", 0, edx, 23),
86 ("sse", 0, edx, 25),
87 ("sse2", 0, edx, 26),
88 ("sse3", 0, ecx, 0),
89 ("pclmulqdq", 0, ecx, 1),
90 ("ssse3", 0, ecx, 9),
91 ("fma", 0, ecx, 28, 0, ecx, 12),
92 ("sse4.1", 0, ecx, 19),
93 ("sse4.2", 0, ecx, 20),
94 ("popcnt", 0, ecx, 23),
95 ("aes", 0, ecx, 25),
96 ("avx", 0, ecx, 28),
97 ("rdrand", 0, ecx, 30),
98 ("sgx", 1, ebx, 2),
99 ("bmi1", 1, ebx, 3),
100 ("avx2", 0, ecx, 28, 1, ebx, 5),
101 ("bmi2", 1, ebx, 8),
102 ("rdseed", 1, ebx, 18),
103 ("adx", 1, ebx, 19),
104 ("sha", 1, ebx, 29),
105}