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