|
| 1 | +//! Run-time feature detection on ARM Aarch32. |
| 2 | +
|
| 3 | +use super::{bit, linux}; |
| 4 | + |
| 5 | +#[macro_export] |
| 6 | +#[doc(hidden)] |
| 7 | +macro_rules! __unstable_detect_feature { |
| 8 | + ("neon") => { |
| 9 | + $crate::vendor::__unstable_detect_feature($crate::vendor::__Feature::neon{}) |
| 10 | + }; |
| 11 | + ("pmull") => { |
| 12 | + $crate::vendor::__unstable_detect_feature($crate::vendor::__Feature::pmull{}) |
| 13 | + }; |
| 14 | + ($t:tt) => { compile_error!(concat!("unknown arm target feature: ", $t)) }; |
| 15 | +} |
| 16 | + |
| 17 | +/// ARM CPU Feature enum. Each variant denotes a position in a bitset for a |
| 18 | +/// particular feature. |
| 19 | +/// |
| 20 | +/// PLEASE: do not use this, it is an implementation detail subject to change. |
| 21 | +#[doc(hidden)] |
| 22 | +#[allow(non_camel_case_types)] |
| 23 | +#[repr(u8)] |
| 24 | +pub enum __Feature { |
| 25 | + /// ARM Advanced SIMD (NEON) - Aarch32 |
| 26 | + neon, |
| 27 | + /// Polynomial Multiply |
| 28 | + pmull, |
| 29 | +} |
| 30 | + |
| 31 | +pub fn detect_features<T: linux::FeatureQuery>(mut x: T) -> usize { |
| 32 | + let value: usize = 0; |
| 33 | + { |
| 34 | + let mut enable_feature = |f| { |
| 35 | + if x.has_feature(&f) { |
| 36 | + bit::set(value, f as u32); |
| 37 | + } |
| 38 | + }; |
| 39 | + enable_feature(__Feature::neon); |
| 40 | + enable_feature(__Feature::pmull); |
| 41 | + } |
| 42 | + value |
| 43 | +} |
| 44 | + |
| 45 | +/// Is the CPU known to have a broken NEON unit? |
| 46 | +/// |
| 47 | +/// See https://crbug.com/341598. |
| 48 | +fn has_broken_neon(cpuinfo: &linux::CpuInfo) -> bool { |
| 49 | + cpuinfo.field("CPU implementer") == "0x51" |
| 50 | + && cpuinfo.field("CPU architecture") == "7" |
| 51 | + && cpuinfo.field("CPU variant") == "0x1" |
| 52 | + && cpuinfo.field("CPU part") == "0x04d" |
| 53 | + && cpuinfo.field("CPU revision") == "0" |
| 54 | +} |
| 55 | + |
| 56 | +impl linux::FeatureQuery for linux::CpuInfo { |
| 57 | + fn has_feature(&mut self, x: &__Feature) -> bool { |
| 58 | + use self::__Feature::*; |
| 59 | + match *x { |
| 60 | + neon => { |
| 61 | + self.field("Features").has("neon") && !has_broken_neon(self) |
| 62 | + } |
| 63 | + pmull => self.field("Features").has("pmull"), |
| 64 | + } |
| 65 | + } |
| 66 | +} |
0 commit comments