]>
Commit | Line | Data |
---|---|---|
f67539c2 | 1 | // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. |
11fdf7f2 TL |
2 | // Copyright (c) 2017 International Business Machines Corp. |
3 | // All rights reserved. | |
f67539c2 TL |
4 | // This source code is licensed under both the GPLv2 (found in the |
5 | // COPYING file in the root directory) and Apache 2.0 License | |
6 | // (found in the LICENSE.Apache file in the root directory). | |
11fdf7f2 TL |
7 | |
8 | #define CRC_TABLE | |
f67539c2 | 9 | #include <stdint.h> |
11fdf7f2 TL |
10 | #include <stdlib.h> |
11 | #include <strings.h> | |
12 | #include "util/crc32c_ppc_constants.h" | |
13 | ||
14 | #define VMX_ALIGN 16 | |
15 | #define VMX_ALIGN_MASK (VMX_ALIGN - 1) | |
16 | ||
17 | #ifdef REFLECT | |
18 | static unsigned int crc32_align(unsigned int crc, unsigned char const *p, | |
19 | unsigned long len) { | |
20 | while (len--) crc = crc_table[(crc ^ *p++) & 0xff] ^ (crc >> 8); | |
21 | return crc; | |
22 | } | |
23 | #endif | |
24 | ||
25 | #ifdef HAVE_POWER8 | |
26 | unsigned int __crc32_vpmsum(unsigned int crc, unsigned char const *p, | |
27 | unsigned long len); | |
28 | ||
29 | static uint32_t crc32_vpmsum(uint32_t crc, unsigned char const *data, | |
1e59de90 | 30 | size_t len) { |
11fdf7f2 TL |
31 | unsigned int prealign; |
32 | unsigned int tail; | |
33 | ||
34 | #ifdef CRC_XOR | |
35 | crc ^= 0xffffffff; | |
36 | #endif | |
37 | ||
38 | if (len < VMX_ALIGN + VMX_ALIGN_MASK) { | |
39 | crc = crc32_align(crc, data, (unsigned long)len); | |
40 | goto out; | |
41 | } | |
42 | ||
43 | if ((unsigned long)data & VMX_ALIGN_MASK) { | |
44 | prealign = VMX_ALIGN - ((unsigned long)data & VMX_ALIGN_MASK); | |
45 | crc = crc32_align(crc, data, prealign); | |
46 | len -= prealign; | |
47 | data += prealign; | |
48 | } | |
49 | ||
50 | crc = __crc32_vpmsum(crc, data, (unsigned long)len & ~VMX_ALIGN_MASK); | |
51 | ||
52 | tail = len & VMX_ALIGN_MASK; | |
53 | if (tail) { | |
54 | data += len & ~VMX_ALIGN_MASK; | |
55 | crc = crc32_align(crc, data, tail); | |
56 | } | |
57 | ||
58 | out: | |
59 | #ifdef CRC_XOR | |
60 | crc ^= 0xffffffff; | |
61 | #endif | |
62 | ||
63 | return crc; | |
64 | } | |
65 | ||
66 | /* This wrapper function works around the fact that crc32_vpmsum | |
67 | * does not gracefully handle the case where the data pointer is NULL. There | |
68 | * may be room for performance improvement here. | |
69 | */ | |
1e59de90 | 70 | uint32_t crc32c_ppc(uint32_t crc, unsigned char const *data, size_t len) { |
11fdf7f2 TL |
71 | unsigned char *buf2; |
72 | ||
73 | if (!data) { | |
74 | buf2 = (unsigned char *)malloc(len); | |
75 | bzero(buf2, len); | |
76 | crc = crc32_vpmsum(crc, buf2, len); | |
77 | free(buf2); | |
78 | } else { | |
79 | crc = crc32_vpmsum(crc, data, (unsigned long)len); | |
80 | } | |
81 | return crc; | |
82 | } | |
83 | ||
84 | #else /* HAVE_POWER8 */ | |
85 | ||
86 | /* This symbol has to exist on non-ppc architectures (and on legacy | |
87 | * ppc systems using power7 or below) in order to compile properly | |
88 | * there, even though it won't be called. | |
89 | */ | |
1e59de90 | 90 | uint32_t crc32c_ppc(uint32_t crc, unsigned char const *data, size_t len) { |
11fdf7f2 TL |
91 | return 0; |
92 | } | |
93 | ||
94 | #endif /* HAVE_POWER8 */ |