Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 4 additions & 14 deletions zlib-rs/src/crc32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,14 @@ impl Crc32Fold {
}
}

#[cfg_attr(not(target_arch = "x86_64"), allow(unused))]
pub(crate) fn is_pclmulqdq_enabled() -> bool {
crate::cpu_features::is_enabled_pclmulqdq()
}

#[cfg_attr(not(target_arch = "aarch64"), allow(unused))]
pub(crate) fn is_crc_enabled() -> bool {
crate::cpu_features::is_enabled_crc()
}

pub fn fold(&mut self, src: &[u8], _start: u32) {
#[cfg(target_arch = "x86_64")]
if Self::is_pclmulqdq_enabled() {
if crate::cpu_features::is_enabled_pclmulqdq() {
return unsafe { self.fold.fold(src, _start) };
}

#[cfg(target_arch = "aarch64")]
if Self::is_crc_enabled() {
if crate::cpu_features::is_enabled_crc() {
self.value = unsafe { self::acle::crc32_acle_aarch64(self.value, src) };
return;
}
Expand All @@ -80,7 +70,7 @@ impl Crc32Fold {

pub fn fold_copy(&mut self, dst: &mut [u8], src: &[u8]) {
#[cfg(target_arch = "x86_64")]
if Self::is_pclmulqdq_enabled() {
if crate::cpu_features::is_enabled_pclmulqdq() {
return unsafe { self.fold.fold_copy(dst, src) };
}

Expand All @@ -90,7 +80,7 @@ impl Crc32Fold {

pub fn finish(self) -> u32 {
#[cfg(target_arch = "x86_64")]
if Self::is_pclmulqdq_enabled() {
if crate::cpu_features::is_enabled_pclmulqdq() {
return unsafe { self.fold.finish() };
}

Expand Down
72 changes: 11 additions & 61 deletions zlib-rs/src/crc32/acle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! The functions in this module must only be executed on an ARM system with the CRC feature.

#[cfg_attr(not(target_arch = "aarch64"), allow(unused))]
#[target_feature(enable = "crc")]
pub unsafe fn crc32_acle_aarch64(crc: u32, buf: &[u8]) -> u32 {
let mut c = !crc;

Expand All @@ -24,29 +25,9 @@ pub unsafe fn crc32_acle_aarch64(crc: u32, buf: &[u8]) -> u32 {
!c
}

#[cfg_attr(not(target_arch = "arm"), allow(unused))]
pub unsafe fn crc32_acle_arm(crc: u32, buf: &[u8]) -> u32 {
let mut c = !crc;

// SAFETY: [u8; 4] safely transmutes into u32.
let (before, middle, after) = unsafe { buf.align_to::<u32>() };

c = remainder(c, before);

if middle.is_empty() && after.is_empty() {
return !c;
}

for w in middle {
c = unsafe { __crc32w(c, *w) };
}

c = remainder(c, after);

!c
}

fn remainder(mut c: u32, mut buf: &[u8]) -> u32 {
#[inline]
#[target_feature(enable = "crc")]
unsafe fn remainder(mut c: u32, mut buf: &[u8]) -> u32 {
if let [b0, b1, b2, b3, rest @ ..] = buf {
c = unsafe { __crc32w(c, u32::from_le_bytes([*b0, *b1, *b2, *b3])) };
buf = rest;
Expand All @@ -67,6 +48,9 @@ fn remainder(mut c: u32, mut buf: &[u8]) -> u32 {
c
}

// FIXME the intrinsics below are stable since rust 1.80.0: remove these and use the standard
// library versions once our MSRV reaches that version.

/// CRC32 single round checksum for bytes (8 bits).
///
/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32b)
Expand Down Expand Up @@ -115,18 +99,6 @@ unsafe fn __crc32d(mut crc: u32, data: u64) -> u32 {
}
}

/// CRC32-C single round checksum for words (32 bits).
///
/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32cw)
#[target_feature(enable = "crc")]
#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
pub unsafe fn __crc32cw(mut crc: u32, data: u32) -> u32 {
unsafe {
core::arch::asm!("crc32cw {crc:w}, {crc:w}, {data:w}", crc = inout(reg) crc, data = in(reg) data);
crc
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -142,21 +114,11 @@ mod tests {

a == b
}

fn crc32_acle_arm_is_crc32fast(v: Vec<u8>, start: u32) -> bool {
let mut h = crc32fast::Hasher::new_with_initial(start);
h.update(&v);

let a = unsafe { crc32_acle_arm(start, &v) };
let b = h.finalize();

a == b
}
}

#[test]
fn test_crc32b() {
if !crate::crc32::Crc32Fold::is_crc_enabled() {
if !crate::cpu_features::is_enabled_crc() {
return;
}

Expand All @@ -168,7 +130,7 @@ mod tests {

#[test]
fn test_crc32h() {
if !crate::crc32::Crc32Fold::is_crc_enabled() {
if !crate::cpu_features::is_enabled_crc() {
return;
}

Expand All @@ -180,7 +142,7 @@ mod tests {

#[test]
fn test_crc32w() {
if !crate::crc32::Crc32Fold::is_crc_enabled() {
if !crate::cpu_features::is_enabled_crc() {
return;
}

Expand All @@ -193,7 +155,7 @@ mod tests {
#[test]
#[cfg(target_arch = "aarch64")]
fn test_crc32d() {
if !crate::crc32::Crc32Fold::is_crc_enabled() {
if !crate::cpu_features::is_enabled_crc() {
return;
}

Expand All @@ -202,16 +164,4 @@ mod tests {
assert_eq!(__crc32d(0, 18446744073709551615), 1147535477);
}
}

#[test]
fn test_crc32cw() {
if !crate::crc32::Crc32Fold::is_crc_enabled() {
return;
}

unsafe {
assert_eq!(__crc32cw(0, 0), 0);
assert_eq!(__crc32cw(0, 4294967295), 3080238136);
}
}
}
Loading