]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/crc32c_ppc.c
update ceph source to reef 18.2.0
[ceph.git] / ceph / src / common / crc32c_ppc.c
CommitLineData
7c673cae
FG
1/* Copyright (C) 2017 International Business Machines Corp.
2 * All rights reserved.
3 *
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.
8 */
9#define CRC_TABLE
31f18b77
FG
10#define FAST_ZERO_TABLE
11
7c673cae
FG
12#include "acconfig.h"
13#include "include/int_types.h"
14#include "crc32c_ppc_constants.h"
31f18b77 15#include "reverse.h"
7c673cae
FG
16
17#include <stdlib.h>
18#include <strings.h>
19
20#define VMX_ALIGN 16
21#define VMX_ALIGN_MASK (VMX_ALIGN-1)
22
11fdf7f2 23#ifdef HAVE_PPC64LE
7c673cae
FG
24#ifdef REFLECT
25static unsigned int crc32_align(unsigned int crc, unsigned char const *p,
26 unsigned long len)
27{
28 while (len--)
29 crc = crc_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
30 return crc;
31}
32#else
33static unsigned int crc32_align(unsigned int crc, unsigned char const *p,
34 unsigned long len)
35{
36 while (len--)
37 crc = crc_table[((crc >> 24) ^ *p++) & 0xff] ^ (crc << 8);
38 return crc;
39}
40#endif
41
31f18b77
FG
42static 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;
46
47 __asm__("vpmsumw %0,%1,%2" : "=v"(vt) : "v"(va), "v"(vb));
48
49 return vt[0];
50}
51
52unsigned int barrett_reduction(unsigned long val);
53
54static inline unsigned int gf_multiply(unsigned int a, unsigned int b) {
55 return barrett_reduction(polynomial_multiply(a, b));
56}
57
58unsigned int append_zeros(unsigned int crc, unsigned long length) {
59 unsigned long i = 0;
60
61 while (length) {
62 if (length & 1) {
63 crc = gf_multiply(crc, crc_zero[i]);
64 }
65 i++;
66 length /= 2;
67 }
68
69 return crc;
70}
71
72
7c673cae
FG
73unsigned int __crc32_vpmsum(unsigned int crc, unsigned char const *p,
74 unsigned long len);
75
76static uint32_t crc32_vpmsum(uint32_t crc, unsigned char const *data,
77 unsigned len)
78{
79 unsigned int prealign;
80 unsigned int tail;
81
82#ifdef CRC_XOR
83 crc ^= 0xffffffff;
84#endif
85
86 if (len < VMX_ALIGN + VMX_ALIGN_MASK) {
87 crc = crc32_align(crc, data, (unsigned long)len);
88 goto out;
89 }
90
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);
94 len -= prealign;
95 data += prealign;
96 }
97
98 crc = __crc32_vpmsum(crc, data, (unsigned long)len & ~VMX_ALIGN_MASK);
99
100 tail = len & VMX_ALIGN_MASK;
101 if (tail) {
102 data += len & ~VMX_ALIGN_MASK;
103 crc = crc32_align(crc, data, tail);
104 }
105
106out:
107#ifdef CRC_XOR
108 crc ^= 0xffffffff;
109#endif
110
111 return crc;
112}
113
114/* This wrapper function works around the fact that crc32_vpmsum
31f18b77 115 * does not gracefully handle the case where the data pointer is NULL.
7c673cae
FG
116 */
117uint32_t ceph_crc32c_ppc(uint32_t crc, unsigned char const *data, unsigned len)
118{
7c673cae 119 if (!data) {
31f18b77
FG
120 /* Handle the NULL buffer case. */
121#ifdef REFLECT
122 crc = reverse_bits(crc);
123#endif
124
125 crc = append_zeros(crc, len);
126
127#ifdef REFLECT
128 crc = reverse_bits(crc);
129#endif
7c673cae 130 } else {
31f18b77 131 /* Handle the valid buffer case. */
7c673cae
FG
132 crc = crc32_vpmsum(crc, data, (unsigned long)len);
133 }
134 return crc;
135}
136
11fdf7f2 137#else /* HAVE_PPC64LE */
7c673cae
FG
138
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.
142 */
143uint32_t ceph_crc32c_ppc(uint32_t crc, unsigned char const *data, unsigned len)
144{
145 return 0;
146}
147
11fdf7f2 148#endif /* HAVE_PPC64LE */