### Create CPU Feature Detection Module (x86/x86_64) Source: https://docs.rs/cpufeatures/latest/index.html Use the `new!` macro to generate a module for CPU feature detection, specifically for AES and SHA extensions on x86/x86_64. The `init()` function returns a token that guarantees initialization and allows checking feature support. The `get()` function retrieves the cached result, and `init_get()` provides both. ```rust #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub mod x86_backend { // This macro creates `cpuid_aes_sha` module cpufeatures::new!(cpuid_aes_sha, "aes", "sha"); pub fn run() { // `token` is a Zero Sized Type (ZST) value, which guarantees // that underlying static storage got properly initialized, // which allows to omit initialization branch let token: cpuid_aes_sha::InitToken = cpuid_aes_sha::init(); if token.get() { println!("CPU supports both SHA and AES extensions"); } else { println!("SHA and AES extensions are not supported"); } // If stored value needed only once you can get stored value // omitting the token let val = cpuid_aes_sha::get(); assert_eq!(val, token.get()); // Additionally you can get both token and value let (token, val) = cpuid_aes_sha::init_get(); assert_eq!(val, token.get()); } } ``` -------------------------------- ### new! Macro Source: https://docs.rs/cpufeatures/latest/src/cpufeatures/lib.rs.html This macro generates a module for CPU feature detection. It handles initialization and retrieval of feature support status. ```APIDOC ## new! Macro ### Description This macro generates a module for CPU feature detection. It handles initialization and retrieval of feature support status. ### Syntax ```rust macro_rules! new { ($mod_name:ident, $($tf:tt),+ $(,)?) => { ... }; } ``` ### Parameters - `$mod_name`: The name of the module to be generated. - `$($tf:tt),+`: A list of target features to detect. ### Generated Module API #### `InitToken` struct Represents an initialization token for CPU feature detection. ##### `init()` Initializes the token, performing CPU feature detection. Returns: `InitToken` ##### `init_get()` Initializes the token and returns a `bool` indicating if the feature is supported. Returns: `(InitToken, bool)` ##### `get()` Gets the initialized value (feature support status). Returns: `bool` #### `init_get()` function Initializes underlying storage if needed and returns the initialization token and feature support status. Returns: `(InitToken, bool)` #### `init()` function Initializes underlying storage if needed and returns the initialization token. Returns: `InitToken` #### `get()` function Initializes underlying storage if needed and returns the stored value (feature support status). Returns: `bool` ``` -------------------------------- ### Define CPU Feature Detection Module Source: https://docs.rs/cpufeatures/latest/src/cpufeatures/lib.rs.html Use this macro to create a module for CPU feature detection. It handles initialization and retrieval of feature support for specified target features. ```rust #![no_std] #![doc = include_str!("../README.md")] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #[cfg(not(miri))] #[cfg(target_arch = "aarch64")] #[doc(hidden)] pub mod aarch64; #[cfg(not(miri))] #[cfg(target_arch = "loongarch64")] #[doc(hidden)] pub mod loongarch64; #[cfg(not(miri))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod x86; #[cfg(miri)] mod miri; #[cfg(not(any( target_arch = "aarch64", target_arch = "loongarch64", target_arch = "x86", target_arch = "x86_64" )))] compile_error!("This crate works only on `aarch64`, `loongarch64`, `x86`, and `x86-64` targets."); /// Create module with CPU feature detection code. #[macro_export] macro_rules! new { ($mod_name:ident, $($tf:tt),+ $(,)?) => { mod $mod_name { use core::sync::atomic::{AtomicU8, Ordering::Relaxed}; const UNINIT: u8 = u8::max_value(); static STORAGE: AtomicU8 = AtomicU8::new(UNINIT); /// Initialization token #[derive(Copy, Clone, Debug)] pub struct InitToken(()); impl InitToken { /// Initialize token, performing CPU feature detection. pub fn init() -> Self { init() } /// Initialize token and return a `bool` indicating if the feature is supported. pub fn init_get() -> (Self, bool) { init_get() } /// Get initialized value. #[inline(always)] pub fn get(&self) -> bool { $crate::__unless_target_features! { $($tf),+ => { STORAGE.load(Relaxed) == 1 } } } } /// Get stored value and initialization token, /// initializing underlying storage if needed. #[inline] pub fn init_get() -> (InitToken, bool) { let res = $crate::__unless_target_features! { $($tf),+ => { #[cold] fn init_inner() -> bool { let res = $crate::__detect_target_features!($($tf),+); STORAGE.store(res as u8, Relaxed); res } // Relaxed ordering is fine, as we only have a single atomic variable. let val = STORAGE.load(Relaxed); if val == UNINIT { init_inner() } else { val == 1 } } }; (InitToken(()), res) } /// Initialize underlying storage if needed and get initialization token. #[inline] pub fn init() -> InitToken { init_get().0 } /// Initialize underlying storage if needed and get stored value. #[inline] pub fn get() -> bool { init_get().1 } } }; } ``` -------------------------------- ### Macro to Check OS Support for SIMD Registers Source: https://docs.rs/cpufeatures/latest/src/cpufeatures/x86.rs.html Checks if the operating system supports the required SIMD registers using the `_xgetbv` instruction. It verifies that the necessary bits in the XCR0 register are set for features like AVX. ```rust #[macro_export] #[doc(hidden)] macro_rules! __xgetbv { ($cr:expr, $mask:expr) => {{ #[cfg(target_arch = "x86")] use core::arch::x86 as arch; #[cfg(target_arch = "x86_64")] use core::arch::x86_64 as arch; // Check bits 26 and 27 let xmask = 0b11 << 26; let xsave = $cr[0].ecx & xmask == xmask; if xsave { let xcr0 = unsafe { arch::_xgetbv(arch::_XCR_XFEATURE_ENABLED_MASK) }; (xcr0 & $mask) == $mask } else { false } }}; } ``` -------------------------------- ### Define new macro Source: https://docs.rs/cpufeatures/latest/cpufeatures/macro.new.html This macro is used to define a new module for CPU feature detection. It takes a module name and a list of feature flags as arguments. ```rust macro_rules! new { ($mod_name:ident, $($tf:tt),+ $(,)?) => { ... }; } ``` -------------------------------- ### Macro to Detect Target Features using CPUID Source: https://docs.rs/cpufeatures/latest/src/cpufeatures/x86.rs.html Detects the presence of all supplied target features by utilizing the x86 CPUID instruction. It safely calls `__cpuid` and `__cpuid_count` and checks the results against the provided features. ```rust #[macro_export] #[doc(hidden)] macro_rules! __detect_target_features { ($($tf:tt),+) => {{ #[cfg(target_arch = "x86")] use core::arch::x86::{__cpuid, __cpuid_count, CpuidResult}; #[cfg(target_arch = "x86_64")] use core::arch::x86_64::{__cpuid, __cpuid_count, CpuidResult}; unsafe fn cpuid(leaf: u32) -> CpuidResult { __cpuid(leaf) } unsafe fn cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult { __cpuid_count(leaf, sub_leaf) } let cr = unsafe { [cpuid(1), cpuid_count(7, 0), cpuid_count(7, 1)] }; $($crate::check!(cr, $tf) & )+ true }}; } ``` -------------------------------- ### Macro to Evaluate Expression Unless Target Features Are Enabled Source: https://docs.rs/cpufeatures/latest/src/cpufeatures/x86.rs.html Evaluates the provided expression if none of the specified target features are enabled. It returns false on SGX targets unless all features are enabled, and does not evaluate the expression on SGX, freestanding, or UEFI targets. ```rust #[macro_export] #[doc(hidden)] macro_rules! __unless_target_features { ($($tf:tt),+ => $body:expr ) => {{ #[cfg(not(all($(target_feature=$tf,)*)))] { #[cfg(not(any(target_env = "sgx", target_os = "none", target_os = "uefi")))] $body // CPUID is not available on SGX. Freestanding and UEFI targets // do not support SIMD features with default compilation flags. #[cfg(any(target_env = "sgx", target_os = "none", target_os = "uefi"))] false } #[cfg(all($(target_feature=$tf,)*))] true }}; } ``` -------------------------------- ### Macro to Expand CPU Feature Check Logic Source: https://docs.rs/cpufeatures/latest/src/cpufeatures/x86.rs.html Expands the `check` macro based on provided CPU feature names and their corresponding CPUID register bits. This macro is used internally to define how each feature is checked. ```rust macro_rules! __expand_check_macro { ($(($name:tt, $reg_cap:tt $(, $i:expr, $reg:ident, $offset:expr)*)),* $(,)?) => { #[macro_export] #[doc(hidden)] macro_rules! check { $( ($cr:expr, $name) => {{ // Register bits are listed here: // https://wiki.osdev.org/CPU_Registers_x86#Extended_Control_Registers let reg_cap = match $reg_cap { // Bit 1 "xmm" => $crate::__xgetbv!($cr, 0b10), // Bits 1 and 2 "ymm" => $crate::__xgetbv!($cr, 0b110), // Bits 1, 2, 5, 6, and 7 "zmm" => $crate::__xgetbv!($cr, 0b1110_0110), _ => true, }; reg_cap $( & ($cr[$i].$reg & (1 << $offset) != 0) )* }}; )* } }; } __expand_check_macro! { ("sse3", "", 0, ecx, 0), ("pclmulqdq", "", 0, ecx, 1), ("ssse3", "", 0, ecx, 9), ("fma", "ymm", 0, ecx, 12, 0, ecx, 28), ("sse4.1", "", 0, ecx, 19), ("sse4.2", "", 0, ecx, 20), ("popcnt", "", 0, ecx, 23), ("aes", "", 0, ecx, 25), ("avx", "xmm", 0, ecx, 28), ("rdrand", "", 0, ecx, 30), ("mmx", "", 0, edx, 23), ("sse", "", 0, edx, 25), ("sse2", "", 0, edx, 26), ("sgx", "", 1, ebx, 2), ("bmi1", "", 1, ebx, 3), ("bmi2", "", 1, ebx, 8), ("avx2", "ymm", 1, ebx, 5, 0, ecx, 28), ("avx512f", "zmm", 1, ebx, 16), ("avx512dq", "zmm", 1, ebx, 17), ("rdseed", "", 1, ebx, 18), ("adx", "", 1, ebx, 19), ("avx512ifma", "zmm", 1, ebx, 21), ("avx512pf", "zmm", 1, ebx, 26), ("avx512er", "zmm", 1, ebx, 27), ("avx512cd", "zmm", 1, ebx, 28), ("sha", "", 1, ebx, 29), ("avx512bw", "zmm", 1, ebx, 30), ("avx512vl", "zmm", 1, ebx, 31), ("avx512vbmi", "zmm", 1, ecx, 1), ("avx512vbmi2", "zmm", 1, ecx, 6), ("gfni", "zmm", 1, ecx, 8), ("vaes", "zmm", 1, ecx, 9), ("vpclmulqdq", "zmm", 1, ecx, 10), ("avx512bitalg", "zmm", 1, ecx, 12), } ``` -------------------------------- ### X86 CPU Feature Definitions Source: https://docs.rs/cpufeatures/latest/src/cpufeatures/x86.rs.html Defines specific X86 CPU features like AVX512VPOPCNTDQ, SHA512, SM3, and SM4, including their register types, operand sizes, and CPUID leaf/subleaf values. ```rust ("avx512vpopcntdq", "zmm", 1, ecx, 14), ("sha512", "ymm", 2, eax, 0), ("sm3", "xmm", 2, eax, 1), ("sm4", "ymm", 2, eax, 2) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.