1 /* Copyright (C) 2017 International Business Machines Corp.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
10 #define FAST_ZERO_TABLE
13 #include "include/int_types.h"
14 #include "crc32c_ppc_constants.h"
21 #define VMX_ALIGN_MASK (VMX_ALIGN-1)
24 static unsigned int crc32_align(unsigned int crc, unsigned char const *p,
28 crc = crc_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
32 static unsigned int crc32_align(unsigned int crc, unsigned char const *p,
36 crc = crc_table[((crc >> 24) ^ *p++) & 0xff] ^ (crc << 8);
42 static inline unsigned long polynomial_multiply(unsigned int a, unsigned int b) {
43 vector unsigned int va = {a, 0, 0, 0};
44 vector unsigned int vb = {b, 0, 0, 0};
45 vector unsigned long vt;
47 __asm__("vpmsumw %0,%1,%2" : "=v"(vt) : "v"(va), "v"(vb));
52 unsigned int barrett_reduction(unsigned long val);
54 static inline unsigned int gf_multiply(unsigned int a, unsigned int b) {
55 return barrett_reduction(polynomial_multiply(a, b));
58 unsigned int append_zeros(unsigned int crc, unsigned long length) {
63 crc = gf_multiply(crc, crc_zero[i]);
73 unsigned int __crc32_vpmsum(unsigned int crc, unsigned char const *p,
76 static uint32_t crc32_vpmsum(uint32_t crc, unsigned char const *data,
79 unsigned int prealign;
86 if (len < VMX_ALIGN + VMX_ALIGN_MASK) {
87 crc = crc32_align(crc, data, (unsigned long)len);
91 if ((unsigned long)data & VMX_ALIGN_MASK) {
92 prealign = VMX_ALIGN - ((unsigned long)data & VMX_ALIGN_MASK);
93 crc = crc32_align(crc, data, prealign);
98 crc = __crc32_vpmsum(crc, data, (unsigned long)len & ~VMX_ALIGN_MASK);
100 tail = len & VMX_ALIGN_MASK;
102 data += len & ~VMX_ALIGN_MASK;
103 crc = crc32_align(crc, data, tail);
114 /* This wrapper function works around the fact that crc32_vpmsum
115 * does not gracefully handle the case where the data pointer is NULL.
117 uint32_t ceph_crc32c_ppc(uint32_t crc, unsigned char const *data, unsigned len)
120 /* Handle the NULL buffer case. */
122 crc = reverse_bits(crc);
125 crc = append_zeros(crc, len);
128 crc = reverse_bits(crc);
131 /* Handle the valid buffer case. */
132 crc = crc32_vpmsum(crc, data, (unsigned long)len);
137 #else /* HAVE_POWER8 */
139 /* This symbol has to exist on non-ppc architectures (and on legacy
140 * ppc systems using power7 or below) in order to compile properly
141 * there, even though it won't be called.
143 uint32_t ceph_crc32c_ppc(uint32_t crc, unsigned char const *data, unsigned len)
148 #endif /* HAVE_POWER8 */