#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
#[no_mangle]
pub static mut OPENSSL_armcap_P: u32 = 0;
pub static INITIALIZED: AtomicBool = AtomicBool::new(false);
#[inline(never)]
pub fn init() {
if INITIALIZED.swap(true, Ordering::Relaxed) {
return;
}
#[cfg(all(target_arch = "aarch64", target_vendor = "apple"))]
unsafe {
super::OPENSSL_armcap_P = (1 << 0) | (1 << 3) | (1 << 4);
}
#[cfg(all(target_arch = "aarch64", not(target_vendor = "apple")))]
aarch64::init();
#[cfg(all(target_arch = "arm", target_os = "linux"))]
arm::init();
#[cfg(not(any(
all(target_arch = "aarch64", target_vendor = "apple"),
all(target_arch = "aarch64", not(target_vendor = "apple")),
all(target_arch = "arm", target_os = "linux")
)))]
unsafe {
OPENSSL_armcap_P = 0;
}
INITIALIZED.store(true, Ordering::Release);
}
#[cfg(all(target_arch = "aarch64", not(target_vendor = "apple")))]
mod aarch64 {
use super::OPENSSL_armcap_P;
#[inline(always)]
unsafe fn read_isar0() -> u64 {
let v: u64;
core::arch::asm!(
"mrs {v}, ID_AA64ISAR0_EL1",
v = out(reg) v,
options(nomem, nostack, preserves_flags)
);
v
}
pub(super) fn init() {
let isar0 = unsafe { read_isar0() };
let mut cap: u32 = 1; if ((isar0 >> 4) & 0xF) >= 2 {
cap |= 1 << 3;
}
if ((isar0 >> 8) & 0xF) >= 1 {
cap |= 1 << 4;
}
unsafe {
OPENSSL_armcap_P = cap;
}
}
}
#[cfg(all(target_arch = "arm", target_os = "linux"))]
mod arm {
use super::OPENSSL_armcap_P;
const AT_HWCAP: usize = 16;
const HWCAP_AES: usize = 1 << 0;
const HWCAP_PMULL: usize = 1 << 1;
extern "C" {
fn getauxval(type_: usize) -> usize;
}
pub(super) fn init() {
let mut cap: u32 = 1; let hw = unsafe { getauxval(AT_HWCAP) };
if hw & HWCAP_AES != 0 {
cap |= 1 << 3;
}
if hw & HWCAP_PMULL != 0 {
cap |= 1 << 4;
}
unsafe {
OPENSSL_armcap_P = cap;
}
}
}