#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
#[cfg(any(target_os = "linux", target_os = "android"))]
use super::get_auxv;
#[no_mangle]
pub static mut OPENSSL_armcap_P: u32 = 0;
pub static INITIALIZED: AtomicBool = AtomicBool::new(false);
#[cfg(any(target_os = "linux", target_os = "android"))]
fn detect_arm_capabilities(hwcap: usize, hwcap2: Option<usize>) -> u32 {
let mut caps = 0u32;
#[cfg(target_arch = "aarch64")]
{
const HWCAP_ASIMD: usize = 1 << 1;
const HWCAP_PMULL: usize = 1 << 4;
const HWCAP_CPUID: usize = 1 << 11;
if hwcap & HWCAP_ASIMD != 0 {
caps |= 1 << 0; }
if hwcap & HWCAP_PMULL != 0 {
caps |= 1 << 5; }
if hwcap & HWCAP_CPUID != 0 {
caps |= 1 << 7; }
}
#[cfg(target_arch = "arm")]
{
const HWCAP_NEON: usize = 1 << 12;
if hwcap & HWCAP_NEON != 0 {
caps |= 1 << 0; }
if let Some(hwcap2) = hwcap2 {
const HWCAP2_AES: usize = 1 << 0;
if hwcap2 & HWCAP2_PMULL != 0 {
caps |= 1 << 5; }
}
}
caps
}
pub fn init() {
if INITIALIZED.swap(true, Ordering::Relaxed) {
return;
}
#[cfg(all(any(target_os = "linux", target_os = "android")))]
{
let hwcap = get_auxv(16).unwrap_or(0);
#[cfg(target_arch = "arm")]
let hwcap2 = get_auxv(26);
#[cfg(target_arch = "aarch64")]
let hwcap2 = None;
let caps = detect_arm_capabilities(hwcap, hwcap2);
unsafe {
OPENSSL_armcap_P = caps;
}
}
#[cfg(all(any(target_os = "macos", target_os = "windows"), target_arch = "aarch64"))]
{
unsafe {
OPENSSL_armcap_P = (1 << 0) | (1 << 3) | (1 << 4);
}
}
INITIALIZED.store(true, Ordering::Release);
}