From 5625c8bf49dfd5fb8d6a58143aa435085872f52f Mon Sep 17 00:00:00 2001 From: ZHAI Xiang Date: Wed, 25 Oct 2023 15:09:45 +0800 Subject: [PATCH] std_detect: Add support for LoongArch Co-authored-by: WANG Rui --- library/stdarch/crates/std_detect/README.md | 2 +- .../std_detect/src/detect/arch/loongarch.rs | 48 +++++++++++++++++++ .../crates/std_detect/src/detect/arch/mod.rs | 5 ++ .../crates/std_detect/src/detect/mod.rs | 1 + .../std_detect/src/detect/os/linux/auxvec.rs | 4 +- .../src/detect/os/linux/loongarch.rs | 34 +++++++++++++ .../std_detect/src/detect/os/linux/mod.rs | 3 ++ library/stdarch/crates/std_detect/src/lib.rs | 1 + 8 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 library/stdarch/crates/std_detect/src/detect/arch/loongarch.rs create mode 100644 library/stdarch/crates/std_detect/src/detect/os/linux/loongarch.rs diff --git a/library/stdarch/crates/std_detect/README.md b/library/stdarch/crates/std_detect/README.md index 3611daaf40fe..04bc6a665e7e 100644 --- a/library/stdarch/crates/std_detect/README.md +++ b/library/stdarch/crates/std_detect/README.md @@ -53,7 +53,7 @@ crate from working on applications in which `std` is not available. [`cupid`](https://crates.io/crates/cupid) crate. * Linux/Android: - * `arm{32, 64}`, `mips{32,64}{,el}`, `powerpc{32,64}{,le}`, `riscv{32,64}`: `std_detect` + * `arm{32, 64}`, `mips{32,64}{,el}`, `powerpc{32,64}{,le}`, `riscv{32,64}`, `loongarch64`: `std_detect` supports these on Linux by querying ELF auxiliary vectors (using `getauxval` when available), and if that fails, by querying `/proc/cpuinfo`. * `arm64`: partial support for doing run-time feature detection by directly diff --git a/library/stdarch/crates/std_detect/src/detect/arch/loongarch.rs b/library/stdarch/crates/std_detect/src/detect/arch/loongarch.rs new file mode 100644 index 000000000000..049cb73224a3 --- /dev/null +++ b/library/stdarch/crates/std_detect/src/detect/arch/loongarch.rs @@ -0,0 +1,48 @@ +//! Run-time feature detection on LoongArch. + +features! { + @TARGET: loongarch; + @CFG: target_arch = "loongarch64"; + @MACRO_NAME: is_loongarch_feature_detected; + @MACRO_ATTRS: + /// Checks if `loongarch` feature is enabled. + /// Supported arguments are: + /// + /// * `"lam"` + /// * `"ual"` + /// * `"fpu"` + /// * `"lsx"` + /// * `"lasx"` + /// * `"crc32"` + /// * `"complex"` + /// * `"crypto"` + /// * `"lvz"` + /// * `"lbtx86"` + /// * `"lbtarm"` + /// * `"lbtmips"` + #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] lam: "lam"; + /// LAM + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] ual: "ual"; + /// UAL + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] fpu: "fpu"; + /// FPU + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] lsx: "lsx"; + /// LSX + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] lasx: "lasx"; + /// LASX + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] crc32: "crc32"; + /// FPU + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] complex: "complex"; + /// Complex + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] crypto: "crypto"; + /// Crypto + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] lvz: "lvz"; + /// LVZ + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] lbtx86: "lbtx86"; + /// LBT.X86 + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] lbtarm: "lbtarm"; + /// LBT.ARM + @FEATURE: #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] lbtmips: "lbtmips"; + /// LBT.MIPS +} diff --git a/library/stdarch/crates/std_detect/src/detect/arch/mod.rs b/library/stdarch/crates/std_detect/src/detect/arch/mod.rs index af8222dc2b2a..2123fec8bff4 100644 --- a/library/stdarch/crates/std_detect/src/detect/arch/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/arch/mod.rs @@ -19,6 +19,8 @@ mod powerpc64; mod mips; #[macro_use] mod mips64; +#[macro_use] +mod loongarch; cfg_if! { if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { @@ -45,6 +47,9 @@ cfg_if! { } else if #[cfg(target_arch = "mips64")] { #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] pub use mips64::*; + } else if #[cfg(target_arch = "loongarch64")] { + #[unstable(feature = "stdarch_loongarch_feature_detection", issue = "117425")] + pub use loongarch::*; } else { // Unimplemented architecture: #[doc(hidden)] diff --git a/library/stdarch/crates/std_detect/src/detect/mod.rs b/library/stdarch/crates/std_detect/src/detect/mod.rs index 75a2f70db8ee..5ce4e54e23be 100644 --- a/library/stdarch/crates/std_detect/src/detect/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/mod.rs @@ -96,6 +96,7 @@ pub fn features() -> impl Iterator { target_arch = "powerpc64", target_arch = "mips", target_arch = "mips64", + target_arch = "loongarch64", ))] { (0_u8..Feature::_last as u8).map(|discriminant: u8| { #[allow(bindings_with_variant_name)] // RISC-V has Feature::f diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs index ee46aa1ac736..a04ea7b147ec 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs @@ -129,7 +129,8 @@ pub(crate) fn auxv() -> Result { target_arch = "riscv32", target_arch = "riscv64", target_arch = "mips", - target_arch = "mips64" + target_arch = "mips64", + target_arch = "loongarch64", ))] { let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize }; @@ -225,6 +226,7 @@ fn auxv_from_buf(buf: &[usize]) -> Result { target_arch = "riscv64", target_arch = "mips", target_arch = "mips64", + target_arch = "loongarch64", ))] { for el in buf.chunks(2) { diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/loongarch.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/loongarch.rs new file mode 100644 index 000000000000..a2c6d308e6ae --- /dev/null +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/loongarch.rs @@ -0,0 +1,34 @@ +//! Run-time feature detection for LoongArch on Linux. + +use super::auxvec; +use crate::detect::{bit, cache, Feature}; + +/// Try to read the features from the auxiliary vector. +pub(crate) fn detect_features() -> cache::Initializer { + let mut value = cache::Initializer::default(); + let enable_feature = |value: &mut cache::Initializer, feature, enable| { + if enable { + value.set(feature as u32); + } + }; + + // The values are part of the platform-specific [asm/hwcap.h][hwcap] + // + // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/loongarch/include/uapi/asm/hwcap.h + if let Ok(auxv) = auxvec::auxv() { + enable_feature(&mut value, Feature::lam, bit::test(auxv.hwcap, 1)); + enable_feature(&mut value, Feature::ual, bit::test(auxv.hwcap, 2)); + enable_feature(&mut value, Feature::fpu, bit::test(auxv.hwcap, 3)); + enable_feature(&mut value, Feature::lsx, bit::test(auxv.hwcap, 4)); + enable_feature(&mut value, Feature::lasx, bit::test(auxv.hwcap, 5)); + enable_feature(&mut value, Feature::crc32, bit::test(auxv.hwcap, 6)); + enable_feature(&mut value, Feature::complex, bit::test(auxv.hwcap, 7)); + enable_feature(&mut value, Feature::crypto, bit::test(auxv.hwcap, 8)); + enable_feature(&mut value, Feature::lvz, bit::test(auxv.hwcap, 9)); + enable_feature(&mut value, Feature::lbtx86, bit::test(auxv.hwcap, 10)); + enable_feature(&mut value, Feature::lbtarm, bit::test(auxv.hwcap, 11)); + enable_feature(&mut value, Feature::lbtmips, bit::test(auxv.hwcap, 12)); + return value; + } + value +} diff --git a/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs b/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs index a49a72783d91..305773852007 100644 --- a/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs +++ b/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs @@ -54,6 +54,9 @@ cfg_if::cfg_if! { } else if #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] { mod powerpc; pub(crate) use self::powerpc::detect_features; + } else if #[cfg(target_arch = "loongarch64")] { + mod loongarch; + pub(crate) use self::loongarch::detect_features; } else { use crate::detect::cache; /// Performs run-time feature detection. diff --git a/library/stdarch/crates/std_detect/src/lib.rs b/library/stdarch/crates/std_detect/src/lib.rs index ac9074eaea75..9bdd64731335 100644 --- a/library/stdarch/crates/std_detect/src/lib.rs +++ b/library/stdarch/crates/std_detect/src/lib.rs @@ -11,6 +11,7 @@ //! * `mips64`: [`is_mips64_feature_detected`] //! * `powerpc`: [`is_powerpc_feature_detected`] //! * `powerpc64`: [`is_powerpc64_feature_detected`] +//! * `loongarch`: [`is_loongarch_feature_detected`] #![stable(feature = "stdsimd", since = "1.27.0")] #![feature(staged_api, doc_cfg, allow_internal_unstable)]