#[cfg(target_arch = "aarch64")]
#[allow(dead_code)]
use core::arch::asm;
#[cfg(target_arch = "aarch64")]
lazy_static::lazy_static! {
#[allow(dead_code)]
pub static ref HARDWARE_SUPPORT_CRC32: bool = has_hardware_crc32();
}
#[cfg(target_arch = "aarch64")]
#[allow(dead_code)]
use core::arch::aarch64::{__crc32cb, __crc32cd, __crc32ch, __crc32cw};
#[cfg(target_arch = "aarch64")]
#[inline]
#[allow(dead_code)]
pub fn has_hardware_crc32() -> bool {
use log::warn;
let mut reg_val: u64;
unsafe {
asm!("mrs {}, ID_AA64ISAR0_EL1", out(reg) reg_val);
}
let crc_field = (reg_val >> 16) & 0xF;
warn!("ID_AA64ISAR0_EL1[19:16]: {crc_field:#x}");
if crc_field >= 1 {
warn!("Hardware CRC32C support detected.");
true
} else {
warn!("No hardware CRC32C support.");
false
}
}
#[cfg(target_arch = "aarch64")]
#[target_feature(enable = "crc")] #[inline]
#[allow(dead_code)]
pub unsafe fn crc32c_hardware(mut crc: u32, data: &[u8]) -> u32 {
unsafe {
let mut p = data.as_ptr();
let mut len = data.len();
while len > 0 && (p as usize) % 8 != 0 {
crc = __crc32cb(crc, *p);
p = p.add(1);
len -= 1;
}
while len >= 8 {
let val = *(p as *const u64);
crc = __crc32cd(crc, val);
p = p.add(8);
len -= 8;
}
if len >= 4 {
let val = *(p as *const u32);
crc = __crc32cw(crc, val);
p = p.add(4);
len -= 4;
}
if len >= 2 {
let val = *(p as *const u16);
crc = __crc32ch(crc, val);
p = p.add(2);
len -= 2;
}
if len > 0 {
crc = __crc32cb(crc, *p);
}
crc
}
}