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
14uint32_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