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
crc32_acle(uint32_t crc,const unsigned char * buf,uint64_t len)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(c, *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(c, *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(c, *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(c, *buf8++);
54 len -= sizeof(uint64_t);
55 }
56
57 if (len >= sizeof(uint32_t)) {
58 buf4 = (const uint32_t *) buf8;
59 c = __crc32w(c, *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(c, *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(c, *buf);
105 }
106
107 c = ~c;
108 return c;
109 }
110 #endif
111