#![doc = include_str!("../README.md")]
#![no_std]
#![expect(clippy::inline_always, reason = "This is used rationally.")]
#[cfg(target_arch = "x86")]
use core::arch::x86;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64 as x86;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
use core::mem::transmute;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
use core::sync::atomic::{AtomicPtr, Ordering};
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
use self::x86::{__cpuid, CpuidResult};
#[must_use]
#[inline(always)]
pub fn has_fast_pdep() -> bool {
inner()
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
#[must_use]
#[inline(always)]
fn inner() -> bool {
false
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
static SELECTED_FN: AtomicPtr<()> = AtomicPtr::new(inner_bootstrap as *mut ());
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[must_use]
#[inline(always)]
fn inner() -> bool {
let fn_ptr = SELECTED_FN.load(Ordering::Acquire);
let selected_fn = unsafe { transmute::<*mut (), fn() -> bool>(fn_ptr) };
selected_fn()
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[must_use]
const fn inner_true() -> bool {
true
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[must_use]
const fn inner_false() -> bool {
false
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[must_use]
fn inner_bootstrap() -> bool {
const AMD: [u8; 12] = *b"AuthenticAMD";
const HYGON: [u8; 12] = *b"HygonGenuine";
let first_call = unsafe { __cpuid(0x00) };
let max_parameter = first_call.eax;
let manufacturer_id = unsafe {
let CpuidResult { ebx, ecx, edx, .. } = first_call;
transmute::<[u32; 3], [u8; 12]>([ebx, edx, ecx])
};
let slow_hint = if manufacturer_id == AMD || manufacturer_id == HYGON {
const ZEN: u32 = 0x17;
const HYGON_DHYANA: u32 = 0x18;
let leaf1 = unsafe { __cpuid(0x01) };
let family = (leaf1.eax >> 8) & 0x0F;
let extended_family = (leaf1.eax >> 20) & 0xFF;
let sum = unsafe { family.unchecked_add(extended_family) };
matches!(sum, ZEN | HYGON_DHYANA)
} else {
false
};
let supports_bmi2 = if max_parameter >= 0x07 {
let leaf = unsafe { __cpuid(0x07) };
(leaf.ebx >> 8) & 0x01 == 1
} else {
false
};
let fast_pdep = supports_bmi2 && !slow_hint;
let selected_fn = if fast_pdep { inner_true } else { inner_false };
SELECTED_FN.store(selected_fn as *mut (), Ordering::Release);
fast_pdep
}