Files
zstd-rs/rust/src/cpu.rs
T
ddidderr 089f8e5b4d feat(rust): add common primitive compatibility layer
Introduce the Rust static library and move the shared byte, bitstream, CPU,
error, xxHash, debug, and public-common implementations into it. Thin C shims
preserve the existing header-driven C build while original tests link the Rust
archive.

This establishes the ABI-safe foundation for later codec and CLI ports;
entropy coding, runtime support, codecs, dictionaries, and the CLI remain C.
The top-down migration map documents that boundary and its validation path.

Test Plan:
- cargo fmt --check
- cargo test --all-targets
- cargo clippy --all-targets -- -D warnings
- cargo build --release

Refs: rust/README.md
2026-07-10 20:02:17 +02:00

167 lines
5.0 KiB
Rust

#![allow(non_snake_case)]
use crate::mem::U32;
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]
pub struct ZstdCpuid {
pub f1c: U32,
pub f1d: U32,
pub f7b: U32,
pub f7c: U32,
}
#[inline]
pub fn ZSTD_cpuid() -> ZstdCpuid {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
cpuid_x86()
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
{
ZstdCpuid::default()
}
}
#[cfg(target_arch = "x86")]
use core::arch::x86::{__cpuid, __cpuid_count, CpuidResult};
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::{__cpuid, __cpuid_count, CpuidResult};
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn cpuid_x86() -> ZstdCpuid {
let mut out = ZstdCpuid::default();
let max: CpuidResult = __cpuid(0);
if max.eax >= 1 {
let r = __cpuid(1);
out.f1c = r.ecx;
out.f1d = r.edx;
}
if max.eax >= 7 {
let r = __cpuid_count(7, 0);
out.f7b = r.ebx;
out.f7c = r.ecx;
}
out
}
macro_rules! cpuid_bit {
($fn_name:ident, $field:ident, $bit:expr) => {
#[inline]
pub fn $fn_name(cpuid: ZstdCpuid) -> bool {
(cpuid.$field & (1u32 << $bit)) != 0
}
};
}
cpuid_bit!(ZSTD_cpuid_sse3, f1c, 0);
cpuid_bit!(ZSTD_cpuid_pclmuldq, f1c, 1);
cpuid_bit!(ZSTD_cpuid_dtes64, f1c, 2);
cpuid_bit!(ZSTD_cpuid_monitor, f1c, 3);
cpuid_bit!(ZSTD_cpuid_dscpl, f1c, 4);
cpuid_bit!(ZSTD_cpuid_vmx, f1c, 5);
cpuid_bit!(ZSTD_cpuid_smx, f1c, 6);
cpuid_bit!(ZSTD_cpuid_eist, f1c, 7);
cpuid_bit!(ZSTD_cpuid_tm2, f1c, 8);
cpuid_bit!(ZSTD_cpuid_ssse3, f1c, 9);
cpuid_bit!(ZSTD_cpuid_cnxtid, f1c, 10);
cpuid_bit!(ZSTD_cpuid_fma, f1c, 12);
cpuid_bit!(ZSTD_cpuid_cx16, f1c, 13);
cpuid_bit!(ZSTD_cpuid_xtpr, f1c, 14);
cpuid_bit!(ZSTD_cpuid_pdcm, f1c, 15);
cpuid_bit!(ZSTD_cpuid_pcid, f1c, 17);
cpuid_bit!(ZSTD_cpuid_dca, f1c, 18);
cpuid_bit!(ZSTD_cpuid_sse41, f1c, 19);
cpuid_bit!(ZSTD_cpuid_sse42, f1c, 20);
cpuid_bit!(ZSTD_cpuid_x2apic, f1c, 21);
cpuid_bit!(ZSTD_cpuid_movbe, f1c, 22);
cpuid_bit!(ZSTD_cpuid_popcnt, f1c, 23);
cpuid_bit!(ZSTD_cpuid_tscdeadline, f1c, 24);
cpuid_bit!(ZSTD_cpuid_aes, f1c, 25);
cpuid_bit!(ZSTD_cpuid_xsave, f1c, 26);
cpuid_bit!(ZSTD_cpuid_osxsave, f1c, 27);
cpuid_bit!(ZSTD_cpuid_avx, f1c, 28);
cpuid_bit!(ZSTD_cpuid_f16c, f1c, 29);
cpuid_bit!(ZSTD_cpuid_rdrand, f1c, 30);
cpuid_bit!(ZSTD_cpuid_fpu, f1d, 0);
cpuid_bit!(ZSTD_cpuid_vme, f1d, 1);
cpuid_bit!(ZSTD_cpuid_de, f1d, 2);
cpuid_bit!(ZSTD_cpuid_pse, f1d, 3);
cpuid_bit!(ZSTD_cpuid_tsc, f1d, 4);
cpuid_bit!(ZSTD_cpuid_msr, f1d, 5);
cpuid_bit!(ZSTD_cpuid_pae, f1d, 6);
cpuid_bit!(ZSTD_cpuid_mce, f1d, 7);
cpuid_bit!(ZSTD_cpuid_cx8, f1d, 8);
cpuid_bit!(ZSTD_cpuid_apic, f1d, 9);
cpuid_bit!(ZSTD_cpuid_sep, f1d, 11);
cpuid_bit!(ZSTD_cpuid_mtrr, f1d, 12);
cpuid_bit!(ZSTD_cpuid_pge, f1d, 13);
cpuid_bit!(ZSTD_cpuid_mca, f1d, 14);
cpuid_bit!(ZSTD_cpuid_cmov, f1d, 15);
cpuid_bit!(ZSTD_cpuid_pat, f1d, 16);
cpuid_bit!(ZSTD_cpuid_pse36, f1d, 17);
cpuid_bit!(ZSTD_cpuid_psn, f1d, 18);
cpuid_bit!(ZSTD_cpuid_clfsh, f1d, 19);
cpuid_bit!(ZSTD_cpuid_ds, f1d, 21);
cpuid_bit!(ZSTD_cpuid_acpi, f1d, 22);
cpuid_bit!(ZSTD_cpuid_mmx, f1d, 23);
cpuid_bit!(ZSTD_cpuid_fxsr, f1d, 24);
cpuid_bit!(ZSTD_cpuid_sse, f1d, 25);
cpuid_bit!(ZSTD_cpuid_sse2, f1d, 26);
cpuid_bit!(ZSTD_cpuid_ss, f1d, 27);
cpuid_bit!(ZSTD_cpuid_htt, f1d, 28);
cpuid_bit!(ZSTD_cpuid_tm, f1d, 29);
cpuid_bit!(ZSTD_cpuid_pbe, f1d, 31);
cpuid_bit!(ZSTD_cpuid_bmi1, f7b, 3);
cpuid_bit!(ZSTD_cpuid_hle, f7b, 4);
cpuid_bit!(ZSTD_cpuid_avx2, f7b, 5);
cpuid_bit!(ZSTD_cpuid_smep, f7b, 7);
cpuid_bit!(ZSTD_cpuid_bmi2, f7b, 8);
cpuid_bit!(ZSTD_cpuid_erms, f7b, 9);
cpuid_bit!(ZSTD_cpuid_invpcid, f7b, 10);
cpuid_bit!(ZSTD_cpuid_rtm, f7b, 11);
cpuid_bit!(ZSTD_cpuid_mpx, f7b, 14);
cpuid_bit!(ZSTD_cpuid_avx512f, f7b, 16);
cpuid_bit!(ZSTD_cpuid_avx512dq, f7b, 17);
cpuid_bit!(ZSTD_cpuid_rdseed, f7b, 18);
cpuid_bit!(ZSTD_cpuid_adx, f7b, 19);
cpuid_bit!(ZSTD_cpuid_smap, f7b, 20);
cpuid_bit!(ZSTD_cpuid_avx512ifma, f7b, 21);
cpuid_bit!(ZSTD_cpuid_pcommit, f7b, 22);
cpuid_bit!(ZSTD_cpuid_clflushopt, f7b, 23);
cpuid_bit!(ZSTD_cpuid_clwb, f7b, 24);
cpuid_bit!(ZSTD_cpuid_avx512pf, f7b, 26);
cpuid_bit!(ZSTD_cpuid_avx512er, f7b, 27);
cpuid_bit!(ZSTD_cpuid_avx512cd, f7b, 28);
cpuid_bit!(ZSTD_cpuid_sha, f7b, 29);
cpuid_bit!(ZSTD_cpuid_avx512bw, f7b, 30);
cpuid_bit!(ZSTD_cpuid_avx512vl, f7b, 31);
cpuid_bit!(ZSTD_cpuid_prefetchwt1, f7c, 0);
cpuid_bit!(ZSTD_cpuid_avx512vbmi, f7c, 1);
#[inline]
pub fn ZSTD_cpuSupportsBmi2() -> bool {
let cpuid = ZSTD_cpuid();
ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn feature_helpers_read_the_header_defined_bits() {
let cpuid = ZstdCpuid {
f1c: 1 << 20,
f1d: 1 << 26,
f7b: (1 << 3) | (1 << 8),
f7c: 1 << 1,
};
assert!(ZSTD_cpuid_sse42(cpuid));
assert!(ZSTD_cpuid_sse2(cpuid));
assert!(ZSTD_cpuid_bmi1(cpuid));
assert!(ZSTD_cpuid_bmi2(cpuid));
assert!(ZSTD_cpuid_avx512vbmi(cpuid));
assert!(!ZSTD_cpuid_avx2(cpuid));
}
}