Skip to content

Commit e07fb5d

Browse files
committed
Add support for feature detection on FreeBSD/aarch64
1 parent 5e628c5 commit e07fb5d

File tree

5 files changed

+118
-0
lines changed

5 files changed

+118
-0
lines changed

crates/stdsimd/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
deny(clippy::missing_inline_in_public_items,)
1212
)]
1313
#![cfg_attr(target_os = "linux", feature(linkage))]
14+
#![cfg_attr(all(target_os = "freebsd", target_arch = "aarch64"), feature(asm))]
1415
#![no_std]
1516
#![unstable(feature = "stdsimd", issue = "27731")]
1617

stdsimd/arch/detect/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ pub use self::arch::Feature;
6363
mod bit;
6464
mod cache;
6565

66+
cfg_if! {
67+
if #[cfg(all(target_arch = "aarch64", any(target_os = "freebsd")))] {
68+
#[path = "os/aarch64.rs"]
69+
mod aarch64;
70+
}
71+
}
72+
6673
cfg_if! {
6774
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
6875
// On x86/x86_64 no OS specific functionality is required.
@@ -71,6 +78,9 @@ cfg_if! {
7178
} else if #[cfg(target_os = "linux")] {
7279
#[path = "os/linux/mod.rs"]
7380
mod os;
81+
} else if #[cfg(target_os = "freebsd")] {
82+
#[path = "os/freebsd/mod.rs"]
83+
mod os;
7484
} else {
7585
#[path = "os/other.rs"]
7686
mod os;

stdsimd/arch/detect/os/aarch64.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//! Run-time feature detection for Aarch64 on any OS that traps the mrs instruction.
2+
3+
use arch::detect::Feature;
4+
use arch::detect::cache;
5+
6+
/// Try to read the features from the system registers.
7+
///
8+
/// This will cause SIGILL when the current OS is not trapping the mrs instruction.
9+
pub(crate) fn detect_features() -> cache::Initializer {
10+
let mut value = cache::Initializer::default();
11+
12+
{
13+
let mut enable_feature = |f, enable| {
14+
if enable {
15+
value.set(f as u32);
16+
}
17+
};
18+
19+
// ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0
20+
let aa64isar0: u64;
21+
unsafe { asm!("mrs $0, S3_0_C0_C6_0" : "=r"(aa64isar0)); }
22+
23+
let aes = bits_shift(aa64isar0, 7, 4) >= 1;
24+
let pmull = bits_shift(aa64isar0, 7, 4) >= 2;
25+
let sha1 = bits_shift(aa64isar0, 11, 8) >= 1;
26+
let sha2 = bits_shift(aa64isar0, 15, 12) >= 1;
27+
enable_feature(Feature::pmull, pmull);
28+
// Crypto is specified as AES + PMULL + SHA1 + SHA2 per LLVM/hosts.cpp
29+
enable_feature(Feature::crypto, aes && pmull && sha1 && sha2);
30+
enable_feature(Feature::lse, bits_shift(aa64isar0, 23, 20) >= 1);
31+
enable_feature(Feature::crc, bits_shift(aa64isar0, 19, 16) >= 1);
32+
33+
// ID_AA64PFR0_EL1 - Processor Feature Register 0
34+
let aa64pfr0: u64;
35+
unsafe { asm!("mrs $0, S3_0_C0_C4_0" : "=r"(aa64pfr0)); }
36+
37+
let fp = bits_shift(aa64pfr0, 19, 16) < 0xF;
38+
let fphp = bits_shift(aa64pfr0, 19, 16) >= 1;
39+
let asimd = bits_shift(aa64pfr0, 23, 20) < 0xF;
40+
let asimdhp = bits_shift(aa64pfr0, 23, 20) >= 1;
41+
enable_feature(Feature::fp, fp);
42+
enable_feature(Feature::fp16, fphp);
43+
// SIMD support requires float support - if half-floats are
44+
// supported, it also requires half-float support:
45+
enable_feature(Feature::asimd, fp && asimd && (!fphp | asimdhp));
46+
// SIMD extensions require SIMD support:
47+
enable_feature(Feature::rdm, asimd && bits_shift(aa64isar0, 31, 28) >= 1);
48+
enable_feature(Feature::dotprod, asimd && bits_shift(aa64isar0, 47, 44) >= 1);
49+
enable_feature(Feature::sve, asimd && bits_shift(aa64pfr0, 35, 32) >= 1);
50+
51+
// ID_AA64ISAR1_EL1 - Instruction Set Attribute Register 1
52+
let aa64isar1: u64;
53+
unsafe { asm!("mrs $0, S3_0_C0_C6_1" : "=r"(aa64isar1)); }
54+
55+
enable_feature(Feature::rcpc, bits_shift(aa64isar1, 23, 20) >= 1);
56+
}
57+
58+
value
59+
}
60+
61+
#[inline]
62+
fn bits_shift(x: u64, high: usize, low: usize) -> u64 {
63+
(x >> low) & ((1 << (high - low + 1)) - 1)
64+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//! Run-time feature detection for Aarch64 on FreeBSD.
2+
3+
use arch::detect::Feature;
4+
use arch::detect::cache;
5+
use super::super::aarch64::detect_features;
6+
7+
/// Performs run-time feature detection.
8+
#[inline]
9+
pub fn check_for(x: Feature) -> bool {
10+
cache::test(x as u32, detect_features)
11+
}
12+
13+
#[cfg(test)]
14+
mod tests {
15+
#[test]
16+
fn dump() {
17+
println!("asimd: {:?}", is_aarch64_feature_detected!("asimd"));
18+
println!("pmull: {:?}", is_aarch64_feature_detected!("pmull"));
19+
println!("fp: {:?}", is_aarch64_feature_detected!("fp"));
20+
println!("fp16: {:?}", is_aarch64_feature_detected!("fp16"));
21+
println!("sve: {:?}", is_aarch64_feature_detected!("sve"));
22+
println!("crc: {:?}", is_aarch64_feature_detected!("crc"));
23+
println!("crypto: {:?}", is_aarch64_feature_detected!("crypto"));
24+
println!("lse: {:?}", is_aarch64_feature_detected!("lse"));
25+
println!("rdm: {:?}", is_aarch64_feature_detected!("rdm"));
26+
println!("rcpc: {:?}", is_aarch64_feature_detected!("rcpc"));
27+
println!("dotprod: {:?}", is_aarch64_feature_detected!("dotprod"));
28+
}
29+
}

stdsimd/arch/detect/os/freebsd/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//! Run-time feature detection on FreeBSD
2+
3+
cfg_if! {
4+
if #[cfg(target_arch = "aarch64")] {
5+
mod aarch64;
6+
pub use self::aarch64::check_for;
7+
} else {
8+
use arch::detect::Feature;
9+
/// Performs run-time feature detection.
10+
pub fn check_for(_x: Feature) -> bool {
11+
false
12+
}
13+
}
14+
}

0 commit comments

Comments
 (0)