1 | /* crc32_acle.c -- compute the CRC-32 of a data stream |
2 | * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler |
3 | * Copyright (C) 2016 Yang Zhang |
4 | * For conditions of distribution and use, see copyright notice in zlib.h |
5 | * |
6 | */ |
7 | |
8 | #ifdef ARM_ACLE_CRC_HASH |
9 | #ifndef _MSC_VER |
10 | # include <arm_acle.h> |
11 | #endif |
12 | #include "../../zutil.h" |
13 | |
14 | uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len) { |
15 | Z_REGISTER uint32_t c; |
16 | Z_REGISTER const uint16_t *buf2; |
17 | Z_REGISTER const uint32_t *buf4; |
18 | |
19 | c = ~crc; |
20 | if (len && ((ptrdiff_t)buf & 1)) { |
21 | c = __crc32b(a: c, b: *buf++); |
22 | len--; |
23 | } |
24 | |
25 | if ((len > sizeof(uint16_t)) && ((ptrdiff_t)buf & sizeof(uint16_t))) { |
26 | buf2 = (const uint16_t *) buf; |
27 | c = __crc32h(a: c, b: *buf2++); |
28 | len -= sizeof(uint16_t); |
29 | buf4 = (const uint32_t *) buf2; |
30 | } else { |
31 | buf4 = (const uint32_t *) buf; |
32 | } |
33 | |
34 | #if defined(__aarch64__) |
35 | if ((len > sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) { |
36 | c = __crc32w(a: c, b: *buf4++); |
37 | len -= sizeof(uint32_t); |
38 | } |
39 | |
40 | const uint64_t *buf8 = (const uint64_t *) buf4; |
41 | |
42 | #ifdef UNROLL_MORE |
43 | while (len >= 4 * sizeof(uint64_t)) { |
44 | c = __crc32d(c, *buf8++); |
45 | c = __crc32d(c, *buf8++); |
46 | c = __crc32d(c, *buf8++); |
47 | c = __crc32d(c, *buf8++); |
48 | len -= 4 * sizeof(uint64_t); |
49 | } |
50 | #endif |
51 | |
52 | while (len >= sizeof(uint64_t)) { |
53 | c = __crc32d(a: c, b: *buf8++); |
54 | len -= sizeof(uint64_t); |
55 | } |
56 | |
57 | if (len >= sizeof(uint32_t)) { |
58 | buf4 = (const uint32_t *) buf8; |
59 | c = __crc32w(a: c, b: *buf4++); |
60 | len -= sizeof(uint32_t); |
61 | buf2 = (const uint16_t *) buf4; |
62 | } else { |
63 | buf2 = (const uint16_t *) buf8; |
64 | } |
65 | |
66 | if (len >= sizeof(uint16_t)) { |
67 | c = __crc32h(a: c, b: *buf2++); |
68 | len -= sizeof(uint16_t); |
69 | } |
70 | |
71 | buf = (const unsigned char *) buf2; |
72 | #else /* __aarch64__ */ |
73 | |
74 | # ifdef UNROLL_MORE |
75 | while (len >= 8 * sizeof(uint32_t)) { |
76 | c = __crc32w(c, *buf4++); |
77 | c = __crc32w(c, *buf4++); |
78 | c = __crc32w(c, *buf4++); |
79 | c = __crc32w(c, *buf4++); |
80 | c = __crc32w(c, *buf4++); |
81 | c = __crc32w(c, *buf4++); |
82 | c = __crc32w(c, *buf4++); |
83 | c = __crc32w(c, *buf4++); |
84 | len -= 8 * sizeof(uint32_t); |
85 | } |
86 | # endif |
87 | |
88 | while (len >= sizeof(uint32_t)) { |
89 | c = __crc32w(c, *buf4++); |
90 | len -= sizeof(uint32_t); |
91 | } |
92 | |
93 | if (len >= sizeof(uint16_t)) { |
94 | buf2 = (const uint16_t *) buf4; |
95 | c = __crc32h(c, *buf2++); |
96 | len -= sizeof(uint16_t); |
97 | buf = (const unsigned char *) buf2; |
98 | } else { |
99 | buf = (const unsigned char *) buf4; |
100 | } |
101 | #endif /* __aarch64__ */ |
102 | |
103 | if (len) { |
104 | c = __crc32b(a: c, b: *buf); |
105 | } |
106 | |
107 | c = ~c; |
108 | return c; |
109 | } |
110 | #endif |
111 | |