Skip to content

Update aarch64 linux feature detection #1146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 28, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 113 additions & 28 deletions crates/core_arch/src/arm_shared/crypto.rs
Original file line number Diff line number Diff line change
@@ -51,9 +51,16 @@ extern "C" {
#[cfg(test)]
use stdarch_test::assert_instr;

// Rust compilers without 8a57820bca64a252489790a57cb5ea23db6f9198 need crypto (hence the bootstrap check)
// LLVM builds without b8baa2a9132498ea286dbb0d03f005760ecc6fdb need crypto for arm (hence the target_arch check)

/// AES single round encryption.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "aes")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(aese))]
pub unsafe fn vaeseq_u8(data: uint8x16_t, key: uint8x16_t) -> uint8x16_t {
@@ -62,7 +69,11 @@ pub unsafe fn vaeseq_u8(data: uint8x16_t, key: uint8x16_t) -> uint8x16_t {

/// AES single round decryption.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "aes")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(aesd))]
pub unsafe fn vaesdq_u8(data: uint8x16_t, key: uint8x16_t) -> uint8x16_t {
@@ -71,7 +82,11 @@ pub unsafe fn vaesdq_u8(data: uint8x16_t, key: uint8x16_t) -> uint8x16_t {

/// AES mix columns.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "aes")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(aesmc))]
pub unsafe fn vaesmcq_u8(data: uint8x16_t) -> uint8x16_t {
@@ -80,7 +95,11 @@ pub unsafe fn vaesmcq_u8(data: uint8x16_t) -> uint8x16_t {

/// AES inverse mix columns.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "aes")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(aesimc))]
pub unsafe fn vaesimcq_u8(data: uint8x16_t) -> uint8x16_t {
@@ -89,7 +108,11 @@ pub unsafe fn vaesimcq_u8(data: uint8x16_t) -> uint8x16_t {

/// SHA1 fixed rotate.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha1h))]
pub unsafe fn vsha1h_u32(hash_e: u32) -> u32 {
@@ -98,7 +121,11 @@ pub unsafe fn vsha1h_u32(hash_e: u32) -> u32 {

/// SHA1 hash update accelerator, choose.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha1c))]
pub unsafe fn vsha1cq_u32(hash_abcd: uint32x4_t, hash_e: u32, wk: uint32x4_t) -> uint32x4_t {
@@ -107,7 +134,11 @@ pub unsafe fn vsha1cq_u32(hash_abcd: uint32x4_t, hash_e: u32, wk: uint32x4_t) ->

/// SHA1 hash update accelerator, majority.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha1m))]
pub unsafe fn vsha1mq_u32(hash_abcd: uint32x4_t, hash_e: u32, wk: uint32x4_t) -> uint32x4_t {
@@ -116,7 +147,11 @@ pub unsafe fn vsha1mq_u32(hash_abcd: uint32x4_t, hash_e: u32, wk: uint32x4_t) ->

/// SHA1 hash update accelerator, parity.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha1p))]
pub unsafe fn vsha1pq_u32(hash_abcd: uint32x4_t, hash_e: u32, wk: uint32x4_t) -> uint32x4_t {
@@ -125,7 +160,11 @@ pub unsafe fn vsha1pq_u32(hash_abcd: uint32x4_t, hash_e: u32, wk: uint32x4_t) ->

/// SHA1 schedule update accelerator, first part.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha1su0))]
pub unsafe fn vsha1su0q_u32(w0_3: uint32x4_t, w4_7: uint32x4_t, w8_11: uint32x4_t) -> uint32x4_t {
@@ -134,7 +173,11 @@ pub unsafe fn vsha1su0q_u32(w0_3: uint32x4_t, w4_7: uint32x4_t, w8_11: uint32x4_

/// SHA1 schedule update accelerator, second part.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha1su1))]
pub unsafe fn vsha1su1q_u32(tw0_3: uint32x4_t, w12_15: uint32x4_t) -> uint32x4_t {
@@ -143,7 +186,11 @@ pub unsafe fn vsha1su1q_u32(tw0_3: uint32x4_t, w12_15: uint32x4_t) -> uint32x4_t

/// SHA256 hash update accelerator.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha256h))]
pub unsafe fn vsha256hq_u32(
@@ -156,7 +203,11 @@ pub unsafe fn vsha256hq_u32(

/// SHA256 hash update accelerator, upper part.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha256h2))]
pub unsafe fn vsha256h2q_u32(
@@ -169,7 +220,11 @@ pub unsafe fn vsha256h2q_u32(

/// SHA256 schedule update accelerator, first part.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha256su0))]
pub unsafe fn vsha256su0q_u32(w0_3: uint32x4_t, w4_7: uint32x4_t) -> uint32x4_t {
@@ -178,7 +233,11 @@ pub unsafe fn vsha256su0q_u32(w0_3: uint32x4_t, w4_7: uint32x4_t) -> uint32x4_t

/// SHA256 schedule update accelerator, second part.
#[inline]
#[target_feature(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), target_feature(enable = "crypto"))]
#[cfg_attr(
not(any(bootstrap, target_arch = "arm")),
target_feature(enable = "sha2")
)]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
#[cfg_attr(test, assert_instr(sha256su1))]
pub unsafe fn vsha256su1q_u32(
@@ -196,7 +255,11 @@ mod tests {
use std::mem;
use stdarch_test::simd_test;

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(
all(not(bootstrap), target_arch = "aarch64"),
simd_test(enable = "aes")
)]
unsafe fn test_vaeseq_u8() {
let data = mem::transmute(u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8));
let key = mem::transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7));
@@ -209,7 +272,11 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(
all(not(bootstrap), target_arch = "aarch64"),
simd_test(enable = "aes")
)]
unsafe fn test_vaesdq_u8() {
let data = mem::transmute(u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8));
let key = mem::transmute(u8x16::new(0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7));
@@ -220,7 +287,11 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(
all(not(bootstrap), target_arch = "aarch64"),
simd_test(enable = "aes")
)]
unsafe fn test_vaesmcq_u8() {
let data = mem::transmute(u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8));
let r: u8x16 = mem::transmute(vaesmcq_u8(data));
@@ -230,7 +301,11 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(
all(not(bootstrap), target_arch = "aarch64"),
simd_test(enable = "aes")
)]
unsafe fn test_vaesimcq_u8() {
let data = mem::transmute(u8x16::new(1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8));
let r: u8x16 = mem::transmute(vaesimcq_u8(data));
@@ -240,13 +315,15 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha1h_u32() {
assert_eq!(vsha1h_u32(0x1234), 0x048d);
assert_eq!(vsha1h_u32(0x5678), 0x159e);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha1su0q_u32() {
let r: u32x4 = mem::transmute(vsha1su0q_u32(
mem::transmute(u32x4::new(0x1234_u32, 0x5678_u32, 0x9abc_u32, 0xdef0_u32)),
@@ -256,7 +333,8 @@ mod tests {
assert_eq!(r, u32x4::new(0x9abc, 0xdef0, 0x1234, 0x5678));
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha1su1q_u32() {
let r: u32x4 = mem::transmute(vsha1su1q_u32(
mem::transmute(u32x4::new(0x1234, 0x5678, 0x9abc, 0xdef0)),
@@ -268,7 +346,8 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha1cq_u32() {
let r: u32x4 = mem::transmute(vsha1cq_u32(
mem::transmute(u32x4::new(0x1234, 0x5678, 0x9abc, 0xdef0)),
@@ -281,7 +360,8 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha1pq_u32() {
let r: u32x4 = mem::transmute(vsha1pq_u32(
mem::transmute(u32x4::new(0x1234, 0x5678, 0x9abc, 0xdef0)),
@@ -294,7 +374,8 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha1mq_u32() {
let r: u32x4 = mem::transmute(vsha1mq_u32(
mem::transmute(u32x4::new(0x1234, 0x5678, 0x9abc, 0xdef0)),
@@ -307,7 +388,8 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha256hq_u32() {
let r: u32x4 = mem::transmute(vsha256hq_u32(
mem::transmute(u32x4::new(0x1234, 0x5678, 0x9abc, 0xdef0)),
@@ -320,7 +402,8 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha256h2q_u32() {
let r: u32x4 = mem::transmute(vsha256h2q_u32(
mem::transmute(u32x4::new(0x1234, 0x5678, 0x9abc, 0xdef0)),
@@ -333,7 +416,8 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha256su0q_u32() {
let r: u32x4 = mem::transmute(vsha256su0q_u32(
mem::transmute(u32x4::new(0x1234, 0x5678, 0x9abc, 0xdef0)),
@@ -345,7 +429,8 @@ mod tests {
);
}

#[simd_test(enable = "crypto")]
#[cfg_attr(any(bootstrap, target_arch = "arm"), simd_test(enable = "crypto"))]
#[cfg_attr(not(any(bootstrap, target_arch = "arm")), simd_test(enable = "sha2"))]
unsafe fn test_vsha256su1q_u32() {
let r: u32x4 = mem::transmute(vsha256su1q_u32(
mem::transmute(u32x4::new(0x1234, 0x5678, 0x9abc, 0xdef0)),
138 changes: 124 additions & 14 deletions crates/std_detect/src/detect/arch/aarch64.rs
Original file line number Diff line number Diff line change
@@ -4,35 +4,145 @@ features! {
@TARGET: aarch64;
@MACRO_NAME: is_aarch64_feature_detected;
@MACRO_ATTRS:
/// Checks if `aarch64` feature is enabled.
/// This macro tests, at runtime, whether an `aarch64` feature is enabled on aarch64 platforms.
/// Currently most features are only supported on linux-based platforms.
///
/// This macro takes one argument which is a string literal of the feature being tested for.
/// The feature names are mostly taken from their FEAT_* definitiions in the [ARM Architecture
/// Reference Manual][docs].
///
/// ## Supported arguments
///
/// * `"asimd"` or "neon" - FEAT_AdvSIMD
/// * `"pmull"` - FEAT_PMULL
/// * `"fp"` - FEAT_FP
/// * `"fp16"` - FEAT_FP16
/// * `"sve"` - FEAT_SVE
/// * `"crc"` - FEAT_CRC
/// * `"lse"` - FEAT_LSE
/// * `"lse2"` - FEAT_LSE2
/// * `"rdm"` - FEAT_RDM
/// * `"rcpc"` - FEAT_LRCPC
/// * `"rcpc2"` - FEAT_LRCPC2
/// * `"dotprod"` - FEAT_DotProd
/// * `"tme"` - FEAT_TME
/// * `"fhm"` - FEAT_FHM
/// * `"dit"` - FEAT_DIT
/// * `"flagm"` - FEAT_FLAGM
/// * `"ssbs"` - FEAT_SSBS
/// * `"sb"` - FEAT_SB
/// * `"pauth"` - FEAT_PAuth
/// * `"dpb"` - FEAT_DPB
/// * `"dpb2"` - FEAT_DPB2
/// * `"sve2"` - FEAT_SVE2
/// * `"sve2-aes"` - FEAT_SVE2_AES
/// * `"sve2-sm4"` - FEAT_SVE2_SM4
/// * `"sve2-sha3"` - FEAT_SVE2_SHA3
/// * `"sve2-bitperm"` - FEAT_SVE2_BitPerm
/// * `"frintts"` - FEAT_FRINTTS
/// * `"i8mm"` - FEAT_I8MM
/// * `"f32mm"` - FEAT_F32MM
/// * `"f64mm"` - FEAT_F64MM
/// * `"bf16"` - FEAT_BF16
/// * `"rand"` - FEAT_RNG
/// * `"bti"` - FEAT_BTI
/// * `"mte"` - FEAT_MTE
/// * `"jsconv"` - FEAT_JSCVT
/// * `"fcma"` - FEAT_FCMA
/// * `"aes"` - FEAT_AES
/// * `"sha2"` - FEAT_SHA1 & FEAT_SHA256
/// * `"sha3"` - FEAT_SHA512 & FEAT_SHA3
/// * `"sm4"` - FEAT_SM3 & FEAT_SM4
///
/// [docs]: https://developer.arm.com/documentation/ddi0487/latest
#[unstable(feature = "stdsimd", issue = "27731")]
@BIND_FEATURE_NAME: "asimd"; "neon";
@NO_RUNTIME_DETECTION: "ras";
@NO_RUNTIME_DETECTION: "v8.1a";
@NO_RUNTIME_DETECTION: "v8.2a";
@NO_RUNTIME_DETECTION: "v8.3a";
@NO_RUNTIME_DETECTION: "v8.4a";
@NO_RUNTIME_DETECTION: "v8.5a";
@NO_RUNTIME_DETECTION: "v8.6a";
@NO_RUNTIME_DETECTION: "v8.7a";
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] asimd: "neon";
/// ARM Advanced SIMD (ASIMD)
/// FEAT_AdvSIMD (Advanced SIMD/NEON)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] pmull: "pmull";
/// Polynomial Multiply
/// FEAT_PMULL (Polynomial Multiply)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] fp: "fp";
/// Floating point support
/// FEAT_FP (Floating point support)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] fp16: "fp16";
/// Half-float support.
/// FEAT_FP16 (Half-float support)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sve: "sve";
/// Scalable Vector Extension (SVE)
/// FEAT_SVE (Scalable Vector Extension)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] crc: "crc";
/// CRC32 (Cyclic Redundancy Check)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] crypto: "crypto";
/// Crypto: AES + PMULL + SHA1 + SHA2
/// FEAT_CRC32 (Cyclic Redundancy Check)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] lse: "lse";
/// Atomics (Large System Extension)
/// FEAT_LSE (Large System Extension - atomics)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] lse2: "lse2";
/// FEAT_LSE2 (unaligned and register-pair atomics)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rdm: "rdm";
/// Rounding Double Multiply (ASIMDRDM)
/// FEAT_RDM (Rounding Doubling Multiply - ASIMDRDM)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rcpc: "rcpc";
/// Release consistent Processor consistent (RcPc)
/// FEAT_LRCPC (Release consistent Processor consistent)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rcpc2: "rcpc2";
/// FEAT_LRCPC2 (RCPC with immediate offsets)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] dotprod: "dotprod";
/// Vector Dot-Product (ASIMDDP)
/// FEAT_DotProd (Vector Dot-Product - ASIMDDP)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] tme: "tme";
/// Transactional Memory Extensions (TME)
/// FEAT_TME (Transactional Memory Extensions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] fhm: "fhm";
/// FEAT_FHM (fp16 multiplication instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] dit: "dit";
/// FEAT_DIT (Data Independent Timing instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] flagm: "flagm";
/// FEAT_FLAGM (flag manipulation instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] ssbs: "ssbs";
/// FEAT_SSBS (speculative store bypass safe)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sb: "sb";
/// FEAT_SB (speculation barrier)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] pauth: "pauth";
/// FEAT_PAuth (pointer authentication)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] dpb: "dpb";
/// FEAT_DPB (aka dcpop - data cache clean to point of persistance)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] dpb2: "dpb2";
/// FEAT_DPB2 (aka dcpodp - data cache clean to point of deep persistance)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sve2: "sve2";
/// FEAT_SVE2 (Scalable Vector Extension 2)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sve2_aes: "sve2-aes";
/// FEAT_SVE_AES (SVE2 AES crypto)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sve2_sm4: "sve2-sm4";
/// FEAT_SVE_SM4 (SVE2 SM4 crypto)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sve2_sha3: "sve2-sha3";
/// FEAT_SVE_SHA3 (SVE2 SHA3 crypto)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sve2_bitperm: "sve2-bitperm";
/// FEAT_SVE_BitPerm (SVE2 bit permutation instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] frintts: "frintts";
/// FEAT_FRINTTS (float to integer rounding instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] i8mm: "i8mm";
/// FEAT_I8MM (integer matrix multiplication, plus ASIMD support)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] f32mm: "f32mm";
/// FEAT_F32MM (single-precision matrix multiplication)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] f64mm: "f64mm";
/// FEAT_F64MM (double-precision matrix multiplication)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] bf16: "bf16";
/// FEAT_BF16 (BFloat16 type, plus MM instructions, plus ASIMD support)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] rand: "rand";
/// FEAT_RNG (Random Number Generator)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] bti: "bti";
/// FEAT_BTI (Branch Target Identification)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] mte: "mte";
/// FEAT_MTE (Memory Tagging Extension)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] jsconv: "jsconv";
/// FEAT_JSCVT (JavaScript float conversion instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] fcma: "fcma";
/// FEAT_FCMA (float complex number operations)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] aes: "aes";
/// FEAT_AES (AES instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sha2: "sha2";
/// FEAT_SHA1 & FEAT_SHA256 (SHA1 & SHA2-256 instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sha3: "sha3";
/// FEAT_SHA512 & FEAT_SHA3 (SHA2-512 & SHA3 instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sm4: "sm4";
/// FEAT_SM3 & FEAT_SM4 (SM3 & SM4 instructions)
}
6 changes: 5 additions & 1 deletion crates/std_detect/src/detect/arch/arm.rs
Original file line number Diff line number Diff line change
@@ -17,5 +17,9 @@ features! {
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] crc: "crc";
/// CRC32 (Cyclic Redundancy Check)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] crypto: "crypto";
/// Crypto: AES + PMULL + SHA1 + SHA2
/// Crypto: AES + PMULL + SHA1 + SHA256. Prefer using the individual features where possible.
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] aes: "aes";
/// FEAT_AES (AES instructions)
@FEATURE: #[unstable(feature = "stdsimd", issue = "27731")] sha2: "sha2";
/// FEAT_SHA1 & FEAT_SHA256 (SHA1 & SHA2-256 instructions)
}
2 changes: 1 addition & 1 deletion crates/std_detect/src/detect/bit.rs
Original file line number Diff line number Diff line change
@@ -4,6 +4,6 @@
#[allow(dead_code)]
#[inline]
pub(crate) fn test(x: usize, bit: u32) -> bool {
debug_assert!(bit < 32, "bit index out-of-bounds");
debug_assert!(bit < usize::BITS, "bit index out-of-bounds");
x & (1 << bit) != 0
}
12 changes: 5 additions & 7 deletions crates/std_detect/src/detect/os/aarch64.rs
Original file line number Diff line number Diff line change
@@ -41,13 +41,7 @@ pub(crate) fn detect_features() -> cache::Initializer {
);
}

let aes = bits_shift(aa64isar0, 7, 4) >= 1;
let pmull = bits_shift(aa64isar0, 7, 4) >= 2;
let sha1 = bits_shift(aa64isar0, 11, 8) >= 1;
let sha2 = bits_shift(aa64isar0, 15, 12) >= 1;
enable_feature(Feature::pmull, pmull);
// Crypto is specified as AES + PMULL + SHA1 + SHA2 per LLVM/hosts.cpp
enable_feature(Feature::crypto, aes && pmull && sha1 && sha2);
enable_feature(Feature::pmull, bits_shift(aa64isar0, 7, 4) >= 2);
enable_feature(Feature::tme, bits_shift(aa64isar0, 27, 24) == 1);
enable_feature(Feature::lse, bits_shift(aa64isar0, 23, 20) >= 1);
enable_feature(Feature::crc, bits_shift(aa64isar0, 19, 16) >= 1);
@@ -72,6 +66,10 @@ pub(crate) fn detect_features() -> cache::Initializer {
// supported, it also requires half-float support:
enable_feature(Feature::asimd, fp && asimd && (!fphp | asimdhp));
// SIMD extensions require SIMD support:
enable_feature(Feature::aes, asimd && bits_shift(aa64isar0, 7, 4) >= 1);
let sha1 = bits_shift(aa64isar0, 11, 8) >= 1;
let sha2 = bits_shift(aa64isar0, 15, 12) >= 1;
enable_feature(Feature::sha2, asimd && sha1 && sha2);
enable_feature(Feature::rdm, asimd && bits_shift(aa64isar0, 31, 28) >= 1);
enable_feature(
Feature::dotprod,
3 changes: 1 addition & 2 deletions crates/std_detect/src/detect/os/freebsd/aarch64.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Run-time feature detection for Aarch64 on FreeBSD.
pub use super::super::aarch64::detect_features;
pub(crate) use super::super::aarch64::detect_features;

#[cfg(test)]
mod tests {
@@ -12,7 +12,6 @@ mod tests {
println!("fp16: {:?}", is_aarch64_feature_detected!("fp16"));
println!("sve: {:?}", is_aarch64_feature_detected!("sve"));
println!("crc: {:?}", is_aarch64_feature_detected!("crc"));
println!("crypto: {:?}", is_aarch64_feature_detected!("crypto"));
println!("lse: {:?}", is_aarch64_feature_detected!("lse"));
println!("rdm: {:?}", is_aarch64_feature_detected!("rdm"));
println!("rcpc: {:?}", is_aarch64_feature_detected!("rcpc"));
9 changes: 8 additions & 1 deletion crates/std_detect/src/detect/os/freebsd/auxvec.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
//! Parses ELF auxiliary vectors.
#![cfg_attr(any(target_arch = "arm", target_arch = "powerpc64"), allow(dead_code))]
#![cfg_attr(
any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc64"
),
allow(dead_code)
)]

/// Key to access the CPU Hardware capabilities bitfield.
pub(crate) const AT_HWCAP: usize = 25;
204 changes: 169 additions & 35 deletions crates/std_detect/src/detect/os/linux/aarch64.rs
Original file line number Diff line number Diff line change
@@ -20,11 +20,13 @@ pub(crate) fn detect_features() -> cache::Initializer {

/// These values are part of the platform-specific [asm/hwcap.h][hwcap] .
///
/// The names match those used for cpuinfo.
///
/// [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
struct AtHwcap {
fp: bool, // 0
asimd: bool, // 1
// evtstrm: bool, // 2
// evtstrm: bool, // 2 No LLVM support
aes: bool, // 3
pmull: bool, // 4
sha1: bool, // 5
@@ -33,18 +35,46 @@ struct AtHwcap {
atomics: bool, // 8
fphp: bool, // 9
asimdhp: bool, // 10
// cpuid: bool, // 11
// cpuid: bool, // 11 No LLVM support
asimdrdm: bool, // 12
// jscvt: bool, // 13
// fcma: bool, // 14
lrcpc: bool, // 15
// dcpop: bool, // 16
// sha3: bool, // 17
// sm3: bool, // 18
// sm4: bool, // 19
asimddp: bool, // 20
// sha512: bool, // 21
sve: bool, // 22
jscvt: bool, // 13
fcma: bool, // 14
lrcpc: bool, // 15
dcpop: bool, // 16
sha3: bool, // 17
sm3: bool, // 18
sm4: bool, // 19
asimddp: bool, // 20
sha512: bool, // 21
sve: bool, // 22
fhm: bool, // 23
dit: bool, // 24
uscat: bool, // 25
ilrcpc: bool, // 26
flagm: bool, // 27
ssbs: bool, // 28
sb: bool, // 29
paca: bool, // 30
pacg: bool, // 31
dcpodp: bool, // 32
sve2: bool, // 33
sveaes: bool, // 34
// svepmull: bool, // 35 No LLVM support
svebitperm: bool, // 36
svesha3: bool, // 37
svesm4: bool, // 38
// flagm2: bool, // 39 No LLVM support
frint: bool, // 40
// svei8mm: bool, // 41 See i8mm feature
svef32mm: bool, // 42
svef64mm: bool, // 43
// svebf16: bool, // 44 See bf16 feature
i8mm: bool, // 45
bf16: bool, // 46
// dgh: bool, // 47 No LLVM support
rng: bool, // 48
bti: bool, // 49
mte: bool, // 50
}

impl From<auxvec::AuxVec> for AtHwcap {
@@ -64,16 +94,44 @@ impl From<auxvec::AuxVec> for AtHwcap {
asimdhp: bit::test(auxv.hwcap, 10),
// cpuid: bit::test(auxv.hwcap, 11),
asimdrdm: bit::test(auxv.hwcap, 12),
// jscvt: bit::test(auxv.hwcap, 13),
// fcma: bit::test(auxv.hwcap, 14),
jscvt: bit::test(auxv.hwcap, 13),
fcma: bit::test(auxv.hwcap, 14),
lrcpc: bit::test(auxv.hwcap, 15),
// dcpop: bit::test(auxv.hwcap, 16),
// sha3: bit::test(auxv.hwcap, 17),
// sm3: bit::test(auxv.hwcap, 18),
// sm4: bit::test(auxv.hwcap, 19),
dcpop: bit::test(auxv.hwcap, 16),
sha3: bit::test(auxv.hwcap, 17),
sm3: bit::test(auxv.hwcap, 18),
sm4: bit::test(auxv.hwcap, 19),
asimddp: bit::test(auxv.hwcap, 20),
// sha512: bit::test(auxv.hwcap, 21),
sha512: bit::test(auxv.hwcap, 21),
sve: bit::test(auxv.hwcap, 22),
fhm: bit::test(auxv.hwcap, 23),
dit: bit::test(auxv.hwcap, 24),
uscat: bit::test(auxv.hwcap, 25),
ilrcpc: bit::test(auxv.hwcap, 26),
flagm: bit::test(auxv.hwcap, 27),
ssbs: bit::test(auxv.hwcap, 28),
sb: bit::test(auxv.hwcap, 29),
paca: bit::test(auxv.hwcap, 30),
pacg: bit::test(auxv.hwcap, 31),
dcpodp: bit::test(auxv.hwcap, 32),
sve2: bit::test(auxv.hwcap, 33),
sveaes: bit::test(auxv.hwcap, 34),
// svepmull: bit::test(auxv.hwcap, 35),
svebitperm: bit::test(auxv.hwcap, 36),
svesha3: bit::test(auxv.hwcap, 37),
svesm4: bit::test(auxv.hwcap, 38),
// flagm2: bit::test(auxv.hwcap, 39),
frint: bit::test(auxv.hwcap, 40),
// svei8mm: bit::test(auxv.hwcap, 41),
svef32mm: bit::test(auxv.hwcap, 42),
svef64mm: bit::test(auxv.hwcap, 43),
// svebf16: bit::test(auxv.hwcap, 44),
i8mm: bit::test(auxv.hwcap, 45),
bf16: bit::test(auxv.hwcap, 46),
// dgh: bit::test(auxv.hwcap, 47),
rng: bit::test(auxv.hwcap, 48),
bti: bit::test(auxv.hwcap, 49),
mte: bit::test(auxv.hwcap, 50),
}
}
}
@@ -100,25 +158,53 @@ impl From<super::cpuinfo::CpuInfo> for AtHwcap {
asimdhp: f.has("asimdhp"),
// cpuid: f.has("cpuid"),
asimdrdm: f.has("asimdrdm"),
// jscvt: f.has("jscvt"),
// fcma: f.has("fcma"),
jscvt: f.has("jscvt"),
fcma: f.has("fcma"),
lrcpc: f.has("lrcpc"),
// dcpop: f.has("dcpop"),
// sha3: f.has("sha3"),
// sm3: f.has("sm3"),
// sm4: f.has("sm4"),
dcpop: f.has("dcpop"),
sha3: f.has("sha3"),
sm3: f.has("sm3"),
sm4: f.has("sm4"),
asimddp: f.has("asimddp"),
// sha512: f.has("sha512"),
sha512: f.has("sha512"),
sve: f.has("sve"),
fhm: f.has("asimdfhm"),
dit: f.has("dit"),
uscat: f.has("uscat"),
ilrcpc: f.has("ilrcpc"),
flagm: f.has("flagm"),
ssbs: f.has("ssbs"),
sb: f.has("sb"),
paca: f.has("paca"),
pacg: f.has("pacg"),
dcpodp: f.has("dcpodp"),
sve2: f.has("sve2"),
sveaes: f.has("sveaes"),
// svepmull: f.has("svepmull"),
svebitperm: f.has("svebitperm"),
svesha3: f.has("svesha3"),
svesm4: f.has("svesm4"),
// flagm2: f.has("flagm2"),
frint: f.has("frint"),
// svei8mm: f.has("svei8mm"),
svef32mm: f.has("svef32mm"),
svef64mm: f.has("svef64mm"),
// svebf16: f.has("svebf16"),
i8mm: f.has("i8mm"),
bf16: f.has("bf16"),
// dgh: f.has("dgh"),
rng: f.has("rng"),
bti: f.has("bti"),
mte: f.has("mte"),
}
}
}

impl AtHwcap {
/// Initializes the cache from the feature -bits.
///
/// The features are enabled approximately like in LLVM host feature detection:
/// https://github.com/llvm-mirror/llvm/blob/master/lib/Support/Host.cpp#L1273
/// The feature dependencies here come directly from LLVM's feature definintions:
/// https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/AArch64/AArch64.td
fn cache(self) -> cache::Initializer {
let mut value = cache::Initializer::default();
{
@@ -131,25 +217,73 @@ impl AtHwcap {
enable_feature(Feature::fp, self.fp);
// Half-float support requires float support
enable_feature(Feature::fp16, self.fp && self.fphp);
// FHM (fp16fml in LLVM) requires half float support
enable_feature(Feature::fhm, self.fphp && self.fhm);
enable_feature(Feature::pmull, self.pmull);
enable_feature(Feature::crc, self.crc32);
enable_feature(Feature::lse, self.atomics);
enable_feature(Feature::lse2, self.uscat);
enable_feature(Feature::rcpc, self.lrcpc);
// RCPC2 (rcpc-immo in LLVM) requires RCPC support
enable_feature(Feature::rcpc2, self.ilrcpc && self.lrcpc);
enable_feature(Feature::dit, self.dit);
enable_feature(Feature::flagm, self.flagm);
enable_feature(Feature::ssbs, self.ssbs);
enable_feature(Feature::sb, self.sb);
// FEAT_PAuth provides both paca & pacg
enable_feature(Feature::pauth, self.paca && self.pacg);
enable_feature(Feature::dpb, self.dcpop);
enable_feature(Feature::dpb2, self.dcpodp);
enable_feature(Feature::rand, self.rng);
enable_feature(Feature::bti, self.bti);
enable_feature(Feature::mte, self.mte);
// jsconv requires float support
enable_feature(Feature::jsconv, self.jscvt && self.fp);
enable_feature(Feature::rdm, self.asimdrdm);
enable_feature(Feature::dotprod, self.asimddp);
enable_feature(Feature::frintts, self.frint);

// FEAT_I8MM & FEAT_BF16 also include optional SVE components which linux exposes
// separately. We ignore that distinction here.
enable_feature(Feature::i8mm, self.i8mm);
enable_feature(Feature::bf16, self.bf16);

// SIMD support requires float support - if half-floats are
// ASIMD support requires float support - if half-floats are
// supported, it also requires half-float support:
let asimd = self.fp && self.asimd && (!self.fphp | self.asimdhp);
enable_feature(Feature::asimd, asimd);
// SIMD extensions require SIMD support:
enable_feature(Feature::rdm, self.asimdrdm && asimd);
enable_feature(Feature::dotprod, self.asimddp && asimd);
// ASIMD extensions require ASIMD support:
enable_feature(Feature::fcma, self.fcma && asimd);
enable_feature(Feature::sve, self.sve && asimd);

// Crypto is specified as AES + PMULL + SHA1 + SHA2 per LLVM/hosts.cpp
// SVE extensions require SVE & ASIMD
enable_feature(Feature::f32mm, self.svef32mm && self.sve && asimd);
enable_feature(Feature::f64mm, self.svef64mm && self.sve && asimd);

// Cryptographic extensions require ASIMD
enable_feature(Feature::aes, self.aes && asimd);
enable_feature(Feature::sha2, self.sha1 && self.sha2 && asimd);
// SHA512/SHA3 require SHA1 & SHA256
enable_feature(
Feature::sha3,
self.sha512 && self.sha3 && self.sha1 && self.sha2 && asimd,
);
enable_feature(Feature::sm4, self.sm3 && self.sm4 && asimd);

// SVE2 requires SVE
let sve2 = self.sve2 && self.sve && asimd;
enable_feature(Feature::sve2, sve2);
// SVE2 extensions require SVE2 and crypto features
enable_feature(Feature::sve2_aes, self.sveaes && sve2 && self.aes);
enable_feature(
Feature::sve2_sm4,
self.svesm4 && sve2 && self.sm3 && self.sm4,
);
enable_feature(
Feature::crypto,
self.aes && self.pmull && self.sha1 && self.sha2,
Feature::sve2_sha3,
self.svesha3 && sve2 && self.sha512 && self.sha3 && self.sha1 && self.sha2,
);
enable_feature(Feature::sve2_bitperm, self.svebitperm && self.sve2);
}
value
}
13 changes: 13 additions & 0 deletions crates/std_detect/src/detect/os/linux/arm.rs
Original file line number Diff line number Diff line change
@@ -28,6 +28,13 @@ pub(crate) fn detect_features() -> cache::Initializer {
&& bit::test(auxv.hwcap2, 2)
&& bit::test(auxv.hwcap2, 3),
);
enable_feature(&mut value, Feature::aes, bit::test(auxv.hwcap2, 0));
// SHA2 requires SHA1 & SHA2 features
enable_feature(
&mut value,
Feature::sha2,
bit::test(auxv.hwcap2, 2) && bit::test(auxv.hwcap2, 3),
);
return value;
}

@@ -48,6 +55,12 @@ pub(crate) fn detect_features() -> cache::Initializer {
&& c.field("Features").has("sha1")
&& c.field("Features").has("sha2"),
);
enable_feature(&mut value, Feature::aes, c.field("Features").has("aes"));
enable_feature(
&mut value,
Feature::sha2,
c.field("Features").has("sha1") && c.field("Features").has("sha2"),
);
return value;
}
value
6 changes: 5 additions & 1 deletion crates/std_detect/src/detect/os/windows/aarch64.rs
Original file line number Diff line number Diff line change
@@ -42,13 +42,17 @@ pub(crate) fn detect_features() -> cache::Initializer {
// PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE means aes, sha1, sha2 and
// pmull support
enable_feature(
Feature::crypto,
Feature::aes,
IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != FALSE,
);
enable_feature(
Feature::pmull,
IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != FALSE,
);
enable_feature(
Feature::sha2,
IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != FALSE,
);
}
}
value
40 changes: 37 additions & 3 deletions crates/std_detect/tests/cpu-detection.rs
Original file line number Diff line number Diff line change
@@ -26,6 +26,8 @@ fn arm_linux() {
println!("pmull: {}", is_arm_feature_detected!("pmull"));
println!("crc: {}", is_arm_feature_detected!("crc"));
println!("crypto: {}", is_arm_feature_detected!("crypto"));
println!("aes: {}", is_arm_feature_detected!("aes"));
println!("sha2: {}", is_arm_feature_detected!("sha2"));
}

#[test]
@@ -34,18 +36,50 @@ fn arm_linux() {
any(target_os = "linux", target_os = "android")
))]
fn aarch64_linux() {
println!("asimd: {}", is_aarch64_feature_detected!("asimd"));
println!("neon: {}", is_aarch64_feature_detected!("neon"));
println!("pmull: {}", is_aarch64_feature_detected!("pmull"));
println!("fp: {}", is_aarch64_feature_detected!("fp"));
println!("fp16: {}", is_aarch64_feature_detected!("fp16"));
println!("neon: {}", is_aarch64_feature_detected!("neon"));
println!("asimd: {}", is_aarch64_feature_detected!("asimd"));
println!("sve: {}", is_aarch64_feature_detected!("sve"));
println!("crc: {}", is_aarch64_feature_detected!("crc"));
println!("crypto: {}", is_aarch64_feature_detected!("crypto"));
println!("lse: {}", is_aarch64_feature_detected!("lse"));
println!("lse2: {}", is_aarch64_feature_detected!("lse2"));
println!("rdm: {}", is_aarch64_feature_detected!("rdm"));
println!("rcpc: {}", is_aarch64_feature_detected!("rcpc"));
println!("rcpc2: {}", is_aarch64_feature_detected!("rcpc2"));
println!("dotprod: {}", is_aarch64_feature_detected!("dotprod"));
println!("tme: {}", is_aarch64_feature_detected!("tme"));
println!("fhm: {}", is_aarch64_feature_detected!("fhm"));
println!("dit: {}", is_aarch64_feature_detected!("dit"));
println!("flagm: {}", is_aarch64_feature_detected!("flagm"));
println!("ssbs: {}", is_aarch64_feature_detected!("ssbs"));
println!("sb: {}", is_aarch64_feature_detected!("sb"));
println!("pauth: {}", is_aarch64_feature_detected!("pauth"));
println!("dpb: {}", is_aarch64_feature_detected!("dpb"));
println!("dpb2: {}", is_aarch64_feature_detected!("dpb2"));
println!("sve2: {}", is_aarch64_feature_detected!("sve2"));
println!("sve2-aes: {}", is_aarch64_feature_detected!("sve2-aes"));
println!("sve2-sm4: {}", is_aarch64_feature_detected!("sve2-sm4"));
println!("sve2-sha3: {}", is_aarch64_feature_detected!("sve2-sha3"));
println!(
"sve2-bitperm: {}",
is_aarch64_feature_detected!("sve2-bitperm")
);
println!("frintts: {}", is_aarch64_feature_detected!("frintts"));
println!("i8mm: {}", is_aarch64_feature_detected!("i8mm"));
println!("f32mm: {}", is_aarch64_feature_detected!("f32mm"));
println!("f64mm: {}", is_aarch64_feature_detected!("f64mm"));
println!("bf16: {}", is_aarch64_feature_detected!("bf16"));
println!("rand: {}", is_aarch64_feature_detected!("rand"));
println!("bti: {}", is_aarch64_feature_detected!("bti"));
println!("mte: {}", is_aarch64_feature_detected!("mte"));
println!("jsconv: {}", is_aarch64_feature_detected!("jsconv"));
println!("fcma: {}", is_aarch64_feature_detected!("fcma"));
println!("aes: {}", is_aarch64_feature_detected!("aes"));
println!("sha2: {}", is_aarch64_feature_detected!("sha2"));
println!("sha3: {}", is_aarch64_feature_detected!("sha3"));
println!("sm4: {}", is_aarch64_feature_detected!("sm4"));
}

#[test]