mod scalar;
#[cfg(target_arch = "x86_64")]
mod simd;
pub use verify::verify_pattern;
#[cfg(target_arch = "x86_64")]
mod verify {
use super::scalar::verify_pattern_scalar;
#[cfg(target_arch = "x86_64")]
use super::simd::{verify_pattern_avx2, verify_pattern_avx512};
use crate::memory_aobscan::pattern::Pattern;
use std::sync::atomic::{AtomicBool, Ordering};
static AVX512_AVAILABLE: AtomicBool = AtomicBool::new(false);
static AVX2_AVAILABLE: AtomicBool = AtomicBool::new(false);
fn init_cpu_features() {
static INIT: AtomicBool = AtomicBool::new(false);
if INIT.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed).is_ok() {
if std::is_x86_feature_detected!("avx512f") {
AVX512_AVAILABLE.store(true, Ordering::Release);
}
if std::is_x86_feature_detected!("avx2") {
AVX2_AVAILABLE.store(true, Ordering::Release);
}
}
}
#[inline]
pub fn verify_pattern(buffer: &[u8], offset: usize, pattern: &Pattern) -> bool {
init_cpu_features();
let len = pattern.bytes.len();
if len >= 32 && AVX512_AVAILABLE.load(Ordering::Acquire) {
unsafe {
return verify_pattern_avx512(buffer, offset, pattern);
}
}
if len >= 16 && AVX2_AVAILABLE.load(Ordering::Acquire) {
unsafe {
return verify_pattern_avx2(buffer, offset, pattern);
}
}
verify_pattern_scalar(buffer, offset, pattern)
}
}
#[cfg(not(target_arch = "x86_64"))]
mod verify {
use super::scalar::verify_pattern_scalar;
use crate::memory_aobscan::pattern::Pattern;
#[inline]
pub fn verify_pattern(buffer: &[u8], offset: usize, pattern: &Pattern) -> bool {
verify_pattern_scalar(buffer, offset, pattern)
}
}