| //! LoongArch64 CPU feature detection support. |
| //! |
| //! This implementation relies on OS-specific APIs for feature detection. |
| |
| // Evaluate the given `$body` expression any of the supplied target features |
| // are not enabled. Otherwise returns true. |
| #[macro_export] |
| #[doc(hidden)] |
| macro_rules! __unless_target_features { |
| ($($tf:tt),+ => $body:expr ) => { |
| { |
| #[cfg(not(all($(target_feature=$tf,)*)))] |
| $body |
| |
| #[cfg(all($(target_feature=$tf,)*))] |
| true |
| } |
| }; |
| } |
| |
| // Linux runtime detection of target CPU features using `getauxval`. |
| #[cfg(target_os = "linux")] |
| #[macro_export] |
| #[doc(hidden)] |
| macro_rules! __detect_target_features { |
| ($($tf:tt),+) => {{ |
| let hwcaps = $crate::loongarch64::getauxval_hwcap(); |
| $($crate::check!(hwcaps, $tf) & )+ true |
| }}; |
| } |
| |
| /// Linux helper function for calling `getauxval` to get `AT_HWCAP`. |
| #[cfg(target_os = "linux")] |
| pub fn getauxval_hwcap() -> u64 { |
| unsafe { libc::getauxval(libc::AT_HWCAP) } |
| } |
| |
| // Linux `expand_check_macro` |
| #[cfg(target_os = "linux")] |
| macro_rules! __expand_check_macro { |
| ($(($name:tt, $hwcap:ident)),* $(,)?) => { |
| #[macro_export] |
| #[doc(hidden)] |
| macro_rules! check { |
| $( |
| ($hwcaps:expr, $name) => { |
| (($hwcaps & $crate::loongarch64::hwcaps::$hwcap) != 0) |
| }; |
| )* |
| } |
| }; |
| } |
| |
| // Linux `expand_check_macro` |
| #[cfg(target_os = "linux")] |
| __expand_check_macro! { |
| ("cpucfg", CPUCFG), // Enable CPUCFG support. |
| ("lam", LAM), // Enable LAM support. |
| ("ual", UAL), // Enable UAL support. |
| ("fpu", FPU), // Enable FPU support. |
| ("lsx", LSX), // Enable LSX support. |
| ("lasx", LASX), // Enable LASX support. |
| ("crc32", CRC32), // Enable CRC32 support. |
| ("complex", COMPLEX), // Enable COMPLEX support. |
| ("crypto", CRYPTO), // Enable CRYPTO support. |
| ("lvz", LVZ), // Enable LVZ support. |
| ("lbt.x86", LBT_X86), // Enable LBT_X86 support. |
| ("lbt.arm", LBT_ARM), // Enable LBT_ARM support. |
| ("lbt.mips", LBT_MIPS), // Enable LBT_MIPS support. |
| ("ptw", PTW), // Enable PTW support. |
| } |
| |
| /// Linux hardware capabilities mapped to target features. |
| /// |
| /// Note that LLVM target features are coarser grained than what Linux supports |
| /// and imply more capabilities under each feature. This module attempts to |
| /// provide that mapping accordingly. |
| #[cfg(target_os = "linux")] |
| pub mod hwcaps { |
| use libc::c_ulong; |
| |
| pub const CPUCFG: c_ulong = libc::HWCAP_CPUCFG; |
| pub const LAM: c_ulong = libc::HWCAP_LAM; |
| pub const UAL: c_ulong = libc::HWCAP_UAL; |
| pub const FPU: c_ulong = libc::HWCAP_FPU; |
| pub const LSX: c_ulong = libc::HWCAP_LSX; |
| pub const LASX: c_ulong = libc::HWCAP_LASX; |
| pub const CRC32: c_ulong = libc::HWCAP_CRC32; |
| pub const COMPLEX: c_ulong = libc::HWCAP_COMPLEX; |
| pub const CRYPTO: c_ulong = libc::HWCAP_CRYPTO; |
| pub const LVZ: c_ulong = libc::HWCAP_LVZ; |
| pub const LBT_X86: c_ulong = libc::HWCAP_LBT_X86; |
| pub const LBT_ARM: c_ulong = libc::HWCAP_LBT_ARM; |
| pub const LBT_MIPS: c_ulong = libc::HWCAP_LBT_MIPS; |
| pub const PTW: c_ulong = libc::HWCAP_PTW; |
| } |
| |
| // On other targets, runtime CPU feature detection is unavailable |
| #[cfg(not(target_os = "linux"))] |
| #[macro_export] |
| #[doc(hidden)] |
| macro_rules! __detect_target_features { |
| ($($tf:tt),+) => { |
| false |
| }; |
| } |