use crate::detect::{Feature, cache, bit};
use super::{auxvec, cpuinfo};
#[inline]
pub fn check_for(x: Feature) -> bool {
cache::test(x as u32, detect_features)
}
fn detect_features() -> cache::Initializer {
if let Ok(auxv) = auxvec::auxv() {
let hwcap: AtHwcap = auxv.into();
return hwcap.cache();
}
if let Ok(c) = cpuinfo::CpuInfo::new() {
let hwcap: AtHwcap = c.into();
return hwcap.cache();
}
cache::Initializer::default()
}
struct AtHwcap {
fp: bool, asimd: bool, aes: bool, pmull: bool, sha1: bool, sha2: bool, crc32: bool, atomics: bool, fphp: bool, asimdhp: bool, asimdrdm: bool, lrcpc: bool, asimddp: bool, sve: bool, }
impl From<auxvec::AuxVec> for AtHwcap {
fn from(auxv: auxvec::AuxVec) -> Self {
AtHwcap {
fp: bit::test(auxv.hwcap, 0),
asimd: bit::test(auxv.hwcap, 1),
aes: bit::test(auxv.hwcap, 3),
pmull: bit::test(auxv.hwcap, 4),
sha1: bit::test(auxv.hwcap, 5),
sha2: bit::test(auxv.hwcap, 6),
crc32: bit::test(auxv.hwcap, 7),
atomics: bit::test(auxv.hwcap, 8),
fphp: bit::test(auxv.hwcap, 9),
asimdhp: bit::test(auxv.hwcap, 10),
asimdrdm: bit::test(auxv.hwcap, 12),
lrcpc: bit::test(auxv.hwcap, 15),
asimddp: bit::test(auxv.hwcap, 20),
sve: bit::test(auxv.hwcap, 22),
}
}
}
impl From<cpuinfo::CpuInfo> for AtHwcap {
fn from(c: cpuinfo::CpuInfo) -> Self {
let f = &c.field("Features");
AtHwcap {
fp: f.has("fp"),
asimd: f.has("asimd"),
aes: f.has("aes"),
pmull: f.has("pmull"),
sha1: f.has("sha1"),
sha2: f.has("sha2"),
crc32: f.has("crc32"),
atomics: f.has("atomics"),
fphp: f.has("fphp"),
asimdhp: f.has("asimdhp"),
asimdrdm: f.has("asimdrdm"),
lrcpc: f.has("lrcpc"),
asimddp: f.has("asimddp"),
sve: f.has("sve"),
}
}
}
impl AtHwcap {
fn cache(self) -> cache::Initializer {
let mut value = cache::Initializer::default();
{
let mut enable_feature = |f, enable| {
if enable {
value.set(f as u32);
}
};
enable_feature(Feature::fp, self.fp);
enable_feature(Feature::fp16, self.fp && self.fphp);
enable_feature(Feature::pmull, self.pmull);
enable_feature(Feature::crc, self.crc32);
enable_feature(Feature::lse, self.atomics);
enable_feature(Feature::rcpc, self.lrcpc);
let asimd = self.fp && self.asimd && (!self.fphp | self.asimdhp);
enable_feature(Feature::asimd, asimd);
enable_feature(Feature::rdm, self.asimdrdm && asimd);
enable_feature(Feature::dotprod, self.asimddp && asimd);
enable_feature(Feature::sve, self.sve && asimd);
enable_feature(Feature::crypto, self.aes && self.pmull && self.sha1 && self.sha2);
}
value
}
}