Skip to content

Commit f56215a

Browse files
authored
Add missing ARM-v7A CRC intrinsics (#1515)
* Move aarch64 crc into arm shared module * Add missing 32-bit arm crc intrinsics On 32-bit ARM, this intrinsic emits two instructions and splits its 64-bit input parameter between them. https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/ARM-ACLE-Intrinsics.html
1 parent b01e4a0 commit f56215a

File tree

4 files changed

+74
-57
lines changed

4 files changed

+74
-57
lines changed

crates/core_arch/src/aarch64/crc.rs

Lines changed: 0 additions & 51 deletions
This file was deleted.

crates/core_arch/src/aarch64/mod.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ mod tme;
1717
#[unstable(feature = "stdarch_aarch64_tme", issue = "117216")]
1818
pub use self::tme::*;
1919

20-
mod crc;
21-
#[unstable(feature = "stdarch_arm_crc32", issue = "117215")]
22-
pub use self::crc::*;
23-
2420
mod prefetch;
2521
#[unstable(feature = "stdarch_aarch64_prefetch", issue = "117217")]
2622
pub use self::prefetch::*;

crates/core_arch/src/arm_shared/crc.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ extern "unadjusted" {
1818
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crc32cw")]
1919
#[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32cw")]
2020
fn crc32cw_(crc: u32, data: u32) -> u32;
21+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crc32x")]
22+
fn crc32x_(crc: u32, data: u64) -> u32;
23+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.crc32cx")]
24+
fn crc32cx_(crc: u32, data: u64) -> u32;
2125
}
2226

2327
#[cfg(test)]
@@ -95,12 +99,82 @@ pub unsafe fn __crc32cw(crc: u32, data: u32) -> u32 {
9599
crc32cw_(crc, data)
96100
}
97101

102+
/// CRC32 single round checksum for quad words (64 bits).
103+
///
104+
/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32d)
105+
#[inline]
106+
#[target_feature(enable = "crc")]
107+
#[cfg(target_arch = "aarch64")]
108+
#[cfg_attr(test, assert_instr(crc32x))]
109+
#[unstable(feature = "stdarch_arm_crc32", issue = "117215")]
110+
pub unsafe fn __crc32d(crc: u32, data: u64) -> u32 {
111+
crc32x_(crc, data)
112+
}
113+
114+
/// CRC32 single round checksum for quad words (64 bits).
115+
///
116+
/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32d)
117+
#[inline]
118+
#[target_feature(enable = "crc")]
119+
#[cfg(target_arch = "arm")]
120+
#[cfg_attr(test, assert_instr(crc32w))]
121+
#[unstable(feature = "stdarch_arm_crc32", issue = "117215")]
122+
pub unsafe fn __crc32d(crc: u32, data: u64) -> u32 {
123+
// On 32-bit ARM this intrinsic emits a chain of two `crc32_w` instructions
124+
// and truncates the data to 32 bits in both clang and gcc
125+
crc32w_(
126+
crc32w_(crc, (data & 0xffffffff) as u32),
127+
(data >> 32) as u32,
128+
)
129+
}
130+
131+
/// CRC32 single round checksum for quad words (64 bits).
132+
///
133+
/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32cd)
134+
#[inline]
135+
#[target_feature(enable = "crc")]
136+
#[cfg(target_arch = "aarch64")]
137+
#[cfg_attr(test, assert_instr(crc32cx))]
138+
#[unstable(feature = "stdarch_arm_crc32", issue = "117215")]
139+
pub unsafe fn __crc32cd(crc: u32, data: u64) -> u32 {
140+
crc32cx_(crc, data)
141+
}
142+
143+
/// CRC32 single round checksum for quad words (64 bits).
144+
///
145+
/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32cd)
146+
#[inline]
147+
#[target_feature(enable = "crc")]
148+
#[cfg(target_arch = "arm")]
149+
#[cfg_attr(test, assert_instr(crc32cw))]
150+
#[unstable(feature = "stdarch_arm_crc32", issue = "117215")]
151+
pub unsafe fn __crc32cd(crc: u32, data: u64) -> u32 {
152+
// On 32-bit ARM this intrinsic emits a chain of two `crc32_cw` instructions
153+
// and truncates the data to 32 bits in both clang and gcc
154+
crc32cw_(
155+
crc32cw_(crc, (data & 0xffffffff) as u32),
156+
(data >> 32) as u32,
157+
)
158+
}
159+
98160
#[cfg(test)]
99161
mod tests {
100162
use crate::core_arch::{arm_shared::*, simd::*};
101163
use std::mem;
102164
use stdarch_test::simd_test;
103165

166+
#[simd_test(enable = "crc")]
167+
unsafe fn test_crc32d() {
168+
assert_eq!(__crc32d(0, 0), 0);
169+
assert_eq!(__crc32d(0, 18446744073709551615), 1147535477);
170+
}
171+
172+
#[simd_test(enable = "crc")]
173+
unsafe fn test_crc32cd() {
174+
assert_eq!(__crc32cd(0, 0), 0);
175+
assert_eq!(__crc32cd(0, 18446744073709551615), 3293575501);
176+
}
177+
104178
#[simd_test(enable = "crc")]
105179
unsafe fn test_crc32b() {
106180
assert_eq!(__crc32b(0, 0), 0);

crates/intrinsic-test/missing_arm.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ vbfmlaltq_laneq_f32
1414
vbfmmlaq_f32
1515

1616
# Implemented in Clang and stdarch for A64 only even though CSV claims A32 support
17-
__crc32d
18-
__crc32cd
1917
vaddq_p64
2018
vbsl_p64
2119
vbslq_p64

0 commit comments

Comments
 (0)