core/stdarch/crates/core_arch/src/arm_shared/
crc.rs

1extern "unadjusted" {
2    #[cfg_attr(
3        any(target_arch = "aarch64", target_arch = "arm64ec"),
4        link_name = "llvm.aarch64.crc32b"
5    )]
6    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32b")]
7    fn crc32b_(crc: u32, data: u32) -> u32;
8    #[cfg_attr(
9        any(target_arch = "aarch64", target_arch = "arm64ec"),
10        link_name = "llvm.aarch64.crc32h"
11    )]
12    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32h")]
13    fn crc32h_(crc: u32, data: u32) -> u32;
14    #[cfg_attr(
15        any(target_arch = "aarch64", target_arch = "arm64ec"),
16        link_name = "llvm.aarch64.crc32w"
17    )]
18    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32w")]
19    fn crc32w_(crc: u32, data: u32) -> u32;
20
21    #[cfg_attr(
22        any(target_arch = "aarch64", target_arch = "arm64ec"),
23        link_name = "llvm.aarch64.crc32cb"
24    )]
25    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32cb")]
26    fn crc32cb_(crc: u32, data: u32) -> u32;
27    #[cfg_attr(
28        any(target_arch = "aarch64", target_arch = "arm64ec"),
29        link_name = "llvm.aarch64.crc32ch"
30    )]
31    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32ch")]
32    fn crc32ch_(crc: u32, data: u32) -> u32;
33    #[cfg_attr(
34        any(target_arch = "aarch64", target_arch = "arm64ec"),
35        link_name = "llvm.aarch64.crc32cw"
36    )]
37    #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.crc32cw")]
38    fn crc32cw_(crc: u32, data: u32) -> u32;
39    #[cfg_attr(
40        any(target_arch = "aarch64", target_arch = "arm64ec"),
41        link_name = "llvm.aarch64.crc32x"
42    )]
43    fn crc32x_(crc: u32, data: u64) -> u32;
44    #[cfg_attr(
45        any(target_arch = "aarch64", target_arch = "arm64ec"),
46        link_name = "llvm.aarch64.crc32cx"
47    )]
48    fn crc32cx_(crc: u32, data: u64) -> u32;
49}
50
51#[cfg(test)]
52use stdarch_test::assert_instr;
53
54/// CRC32 single round checksum for bytes (8 bits).
55///
56/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32b)
57#[inline]
58#[target_feature(enable = "crc")]
59#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
60#[cfg_attr(test, assert_instr(crc32b))]
61#[cfg_attr(
62    target_arch = "arm",
63    unstable(feature = "stdarch_aarch32_crc32", issue = "125085")
64)]
65#[cfg_attr(
66    not(target_arch = "arm"),
67    stable(feature = "stdarch_aarch64_crc32", since = "1.80.0")
68)]
69pub unsafe fn __crc32b(crc: u32, data: u8) -> u32 {
70    crc32b_(crc, data as u32)
71}
72
73/// CRC32 single round checksum for half words (16 bits).
74///
75/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32h)
76#[inline]
77#[target_feature(enable = "crc")]
78#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
79#[cfg_attr(test, assert_instr(crc32h))]
80#[cfg_attr(
81    target_arch = "arm",
82    unstable(feature = "stdarch_aarch32_crc32", issue = "125085")
83)]
84#[cfg_attr(
85    not(target_arch = "arm"),
86    stable(feature = "stdarch_aarch64_crc32", since = "1.80.0")
87)]
88pub unsafe fn __crc32h(crc: u32, data: u16) -> u32 {
89    crc32h_(crc, data as u32)
90}
91
92/// CRC32 single round checksum for words (32 bits).
93///
94/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32w)
95#[inline]
96#[target_feature(enable = "crc")]
97#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
98#[cfg_attr(test, assert_instr(crc32w))]
99#[cfg_attr(
100    target_arch = "arm",
101    unstable(feature = "stdarch_aarch32_crc32", issue = "125085")
102)]
103#[cfg_attr(
104    not(target_arch = "arm"),
105    stable(feature = "stdarch_aarch64_crc32", since = "1.80.0")
106)]
107pub unsafe fn __crc32w(crc: u32, data: u32) -> u32 {
108    crc32w_(crc, data)
109}
110
111/// CRC32-C single round checksum for bytes (8 bits).
112///
113/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32cb)
114#[inline]
115#[target_feature(enable = "crc")]
116#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
117#[cfg_attr(test, assert_instr(crc32cb))]
118#[cfg_attr(
119    target_arch = "arm",
120    unstable(feature = "stdarch_aarch32_crc32", issue = "125085")
121)]
122#[cfg_attr(
123    not(target_arch = "arm"),
124    stable(feature = "stdarch_aarch64_crc32", since = "1.80.0")
125)]
126pub unsafe fn __crc32cb(crc: u32, data: u8) -> u32 {
127    crc32cb_(crc, data as u32)
128}
129
130/// CRC32-C single round checksum for half words (16 bits).
131///
132/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32ch)
133#[inline]
134#[target_feature(enable = "crc")]
135#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
136#[cfg_attr(test, assert_instr(crc32ch))]
137#[cfg_attr(
138    target_arch = "arm",
139    unstable(feature = "stdarch_aarch32_crc32", issue = "125085")
140)]
141#[cfg_attr(
142    not(target_arch = "arm"),
143    stable(feature = "stdarch_aarch64_crc32", since = "1.80.0")
144)]
145pub unsafe fn __crc32ch(crc: u32, data: u16) -> u32 {
146    crc32ch_(crc, data as u32)
147}
148
149/// CRC32-C single round checksum for words (32 bits).
150///
151/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32cw)
152#[inline]
153#[target_feature(enable = "crc")]
154#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))]
155#[cfg_attr(test, assert_instr(crc32cw))]
156#[cfg_attr(
157    target_arch = "arm",
158    unstable(feature = "stdarch_aarch32_crc32", issue = "125085")
159)]
160#[cfg_attr(
161    not(target_arch = "arm"),
162    stable(feature = "stdarch_aarch64_crc32", since = "1.80.0")
163)]
164pub unsafe fn __crc32cw(crc: u32, data: u32) -> u32 {
165    crc32cw_(crc, data)
166}
167
168/// CRC32 single round checksum for quad words (64 bits).
169///
170/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32d)
171#[inline]
172#[target_feature(enable = "crc")]
173#[cfg(not(target_arch = "arm"))]
174#[cfg_attr(test, assert_instr(crc32x))]
175#[stable(feature = "stdarch_aarch64_crc32", since = "1.80.0")]
176pub unsafe fn __crc32d(crc: u32, data: u64) -> u32 {
177    crc32x_(crc, data)
178}
179
180/// CRC32 single round checksum for quad words (64 bits).
181///
182/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32d)
183#[inline]
184#[target_feature(enable = "crc")]
185#[cfg(target_arch = "arm")]
186#[cfg_attr(test, assert_instr(crc32w))]
187#[unstable(feature = "stdarch_aarch32_crc32", issue = "125085")]
188pub unsafe fn __crc32d(crc: u32, data: u64) -> u32 {
189    // On 32-bit ARM this intrinsic emits a chain of two `crc32_w` instructions
190    // and truncates the data to 32 bits in both clang and gcc
191    crc32w_(
192        crc32w_(crc, (data & 0xffffffff) as u32),
193        (data >> 32) as u32,
194    )
195}
196
197/// CRC32 single round checksum for quad words (64 bits).
198///
199/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32cd)
200#[inline]
201#[target_feature(enable = "crc")]
202#[cfg(not(target_arch = "arm"))]
203#[cfg_attr(test, assert_instr(crc32cx))]
204#[stable(feature = "stdarch_aarch64_crc32", since = "1.80.0")]
205pub unsafe fn __crc32cd(crc: u32, data: u64) -> u32 {
206    crc32cx_(crc, data)
207}
208
209/// CRC32 single round checksum for quad words (64 bits).
210///
211/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32cd)
212#[inline]
213#[target_feature(enable = "crc")]
214#[cfg(target_arch = "arm")]
215#[cfg_attr(test, assert_instr(crc32cw))]
216#[unstable(feature = "stdarch_aarch32_crc32", issue = "125085")]
217pub unsafe fn __crc32cd(crc: u32, data: u64) -> u32 {
218    // On 32-bit ARM this intrinsic emits a chain of two `crc32_cw` instructions
219    // and truncates the data to 32 bits in both clang and gcc
220    crc32cw_(
221        crc32cw_(crc, (data & 0xffffffff) as u32),
222        (data >> 32) as u32,
223    )
224}
225
226#[cfg(test)]
227mod tests {
228    use crate::core_arch::{arm_shared::*, simd::*};
229    use std::mem;
230    use stdarch_test::simd_test;
231
232    #[simd_test(enable = "crc")]
233    unsafe fn test_crc32d() {
234        assert_eq!(__crc32d(0, 0), 0);
235        assert_eq!(__crc32d(0, 18446744073709551615), 1147535477);
236    }
237
238    #[simd_test(enable = "crc")]
239    unsafe fn test_crc32cd() {
240        assert_eq!(__crc32cd(0, 0), 0);
241        assert_eq!(__crc32cd(0, 18446744073709551615), 3293575501);
242    }
243
244    #[simd_test(enable = "crc")]
245    unsafe fn test_crc32b() {
246        assert_eq!(__crc32b(0, 0), 0);
247        assert_eq!(__crc32b(0, 255), 755167117);
248    }
249
250    #[simd_test(enable = "crc")]
251    unsafe fn test_crc32h() {
252        assert_eq!(__crc32h(0, 0), 0);
253        assert_eq!(__crc32h(0, 16384), 1994146192);
254    }
255
256    #[simd_test(enable = "crc")]
257    unsafe fn test_crc32w() {
258        assert_eq!(__crc32w(0, 0), 0);
259        assert_eq!(__crc32w(0, 4294967295), 3736805603);
260    }
261
262    #[simd_test(enable = "crc")]
263    unsafe fn test_crc32cb() {
264        assert_eq!(__crc32cb(0, 0), 0);
265        assert_eq!(__crc32cb(0, 255), 2910671697);
266    }
267
268    #[simd_test(enable = "crc")]
269    unsafe fn test_crc32ch() {
270        assert_eq!(__crc32ch(0, 0), 0);
271        assert_eq!(__crc32ch(0, 16384), 1098587580);
272    }
273
274    #[simd_test(enable = "crc")]
275    unsafe fn test_crc32cw() {
276        assert_eq!(__crc32cw(0, 0), 0);
277        assert_eq!(__crc32cw(0, 4294967295), 3080238136);
278    }
279}