]> git.proxmox.com Git - rustc.git/blob - src/stdsimd/stdsimd/arch/detect/os/linux/arm.rs
New upstream version 1.33.0+dfsg1
[rustc.git] / src / stdsimd / stdsimd / arch / detect / os / linux / arm.rs
1 //! Run-time feature detection for ARM on Linux.
2
3 use arch::detect::Feature;
4 use arch::detect::cache;
5 use arch::detect::bit;
6 use super::auxvec;
7 use super::cpuinfo;
8
9 /// Performs run-time feature detection.
10 #[inline]
11 pub fn check_for(x: Feature) -> bool {
12 cache::test(x as u32, detect_features)
13 }
14
15 /// Try to read the features from the auxiliary vector, and if that fails, try
16 /// to read them from /proc/cpuinfo.
17 fn detect_features() -> cache::Initializer {
18 let mut value = cache::Initializer::default();
19 let enable_feature = |value: &mut cache::Initializer, f, enable| {
20 if enable {
21 value.set(f as u32);
22 }
23 };
24
25 // The values are part of the platform-specific [asm/hwcap.h][hwcap]
26 //
27 // [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
28 if let Ok(auxv) = auxvec::auxv() {
29 enable_feature(&mut value, Feature::neon, bit::test(auxv.hwcap, 12));
30 enable_feature(&mut value, Feature::pmull, bit::test(auxv.hwcap2, 1));
31 return value;
32 }
33
34 if let Ok(c) = cpuinfo::CpuInfo::new() {
35 enable_feature(&mut value, Feature::neon, c.field("Features").has("neon") &&
36 !has_broken_neon(&c));
37 enable_feature(&mut value, Feature::pmull, c.field("Features").has("pmull"));
38 return value;
39 }
40 value
41 }
42
43 /// Is the CPU known to have a broken NEON unit?
44 ///
45 /// See https://crbug.com/341598.
46 fn has_broken_neon(cpuinfo: &cpuinfo::CpuInfo) -> bool {
47 cpuinfo.field("CPU implementer") == "0x51"
48 && cpuinfo.field("CPU architecture") == "7"
49 && cpuinfo.field("CPU variant") == "0x1"
50 && cpuinfo.field("CPU part") == "0x04d"
51 && cpuinfo.field("CPU revision") == "0"
52 }