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
167 lines
5.0 KiB
Rust
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));
|
|
}
|
|
}
|