Update aarch64 linux feature detection (#1146)

This commit is contained in:
Adam Gemmell 2021-05-28 01:37:20 +01:00 committed by GitHub
parent 3c3db50bbf
commit 1069e66439
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 481 additions and 93 deletions

View file

@ -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)),

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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
}

View file

@ -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,

View file

@ -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"));

View file

@ -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;

View file

@ -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,16 +158,44 @@ 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"),
}
}
}
@ -117,8 +203,8 @@ impl From<super::cpuinfo::CpuInfo> for AtHwcap {
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);
// SIMD support requires float support - if half-floats are
// 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);
// 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::crypto,
self.aes && self.pmull && self.sha1 && self.sha2,
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::sve2_sha3,
self.svesha3 && sve2 && self.sha512 && self.sha3 && self.sha1 && self.sha2,
);
enable_feature(Feature::sve2_bitperm, self.svebitperm && self.sve2);
}
value
}

View file

@ -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

View file

@ -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

View file

@ -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]