1*9356374aSAndroid Build Coastguard Worker // Copyright 2022 The Abseil Authors.
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_CRC_INTERNAL_CRC_INTERNAL_H_
16*9356374aSAndroid Build Coastguard Worker #define ABSL_CRC_INTERNAL_CRC_INTERNAL_H_
17*9356374aSAndroid Build Coastguard Worker
18*9356374aSAndroid Build Coastguard Worker #include <cstdint>
19*9356374aSAndroid Build Coastguard Worker #include <memory>
20*9356374aSAndroid Build Coastguard Worker #include <vector>
21*9356374aSAndroid Build Coastguard Worker
22*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/raw_logging.h"
23*9356374aSAndroid Build Coastguard Worker #include "absl/crc/internal/crc.h"
24*9356374aSAndroid Build Coastguard Worker
25*9356374aSAndroid Build Coastguard Worker namespace absl {
26*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
27*9356374aSAndroid Build Coastguard Worker
28*9356374aSAndroid Build Coastguard Worker namespace crc_internal {
29*9356374aSAndroid Build Coastguard Worker
30*9356374aSAndroid Build Coastguard Worker // Prefetch constants used in some Extend() implementations
31*9356374aSAndroid Build Coastguard Worker constexpr int kPrefetchHorizon = ABSL_CACHELINE_SIZE * 4; // Prefetch this far
32*9356374aSAndroid Build Coastguard Worker // Shorter prefetch distance for smaller buffers
33*9356374aSAndroid Build Coastguard Worker constexpr int kPrefetchHorizonMedium = ABSL_CACHELINE_SIZE * 1;
34*9356374aSAndroid Build Coastguard Worker static_assert(kPrefetchHorizon >= 64, "CRCPrefetchHorizon less than loop len");
35*9356374aSAndroid Build Coastguard Worker
36*9356374aSAndroid Build Coastguard Worker // We require the Scramble() function:
37*9356374aSAndroid Build Coastguard Worker // - to be reversible (Unscramble() must exist)
38*9356374aSAndroid Build Coastguard Worker // - to be non-linear in the polynomial's Galois field (so the CRC of a
39*9356374aSAndroid Build Coastguard Worker // scrambled CRC is not linearly affected by the scrambled CRC, even if
40*9356374aSAndroid Build Coastguard Worker // using the same polynomial)
41*9356374aSAndroid Build Coastguard Worker // - not to be its own inverse. Preferably, if X=Scramble^N(X) and N!=0, then
42*9356374aSAndroid Build Coastguard Worker // N is large.
43*9356374aSAndroid Build Coastguard Worker // - to be fast.
44*9356374aSAndroid Build Coastguard Worker // - not to change once defined.
45*9356374aSAndroid Build Coastguard Worker // We introduce non-linearity in two ways:
46*9356374aSAndroid Build Coastguard Worker // Addition of a constant.
47*9356374aSAndroid Build Coastguard Worker // - The carries introduce non-linearity; we use bits of an irrational
48*9356374aSAndroid Build Coastguard Worker // (phi) to make it unlikely that we introduce no carries.
49*9356374aSAndroid Build Coastguard Worker // Rotate by a constant number of bits.
50*9356374aSAndroid Build Coastguard Worker // - We use floor(degree/2)+1, which does not divide the degree, and
51*9356374aSAndroid Build Coastguard Worker // splits the bits nearly evenly, which makes it less likely the
52*9356374aSAndroid Build Coastguard Worker // halves will be the same or one will be all zeroes.
53*9356374aSAndroid Build Coastguard Worker // We do both things to improve the chances of non-linearity in the face of
54*9356374aSAndroid Build Coastguard Worker // bit patterns with low numbers of bits set, while still being fast.
55*9356374aSAndroid Build Coastguard Worker // Below is the constant that we add. The bits are the first 128 bits of the
56*9356374aSAndroid Build Coastguard Worker // fractional part of phi, with a 1 ored into the bottom bit to maximize the
57*9356374aSAndroid Build Coastguard Worker // cycle length of repeated adds.
58*9356374aSAndroid Build Coastguard Worker constexpr uint64_t kScrambleHi = (static_cast<uint64_t>(0x4f1bbcdcU) << 32) |
59*9356374aSAndroid Build Coastguard Worker static_cast<uint64_t>(0xbfa53e0aU);
60*9356374aSAndroid Build Coastguard Worker constexpr uint64_t kScrambleLo = (static_cast<uint64_t>(0xf9ce6030U) << 32) |
61*9356374aSAndroid Build Coastguard Worker static_cast<uint64_t>(0x2e76e41bU);
62*9356374aSAndroid Build Coastguard Worker
63*9356374aSAndroid Build Coastguard Worker class CRCImpl : public CRC { // Implementation of the abstract class CRC
64*9356374aSAndroid Build Coastguard Worker public:
65*9356374aSAndroid Build Coastguard Worker using Uint32By256 = uint32_t[256];
66*9356374aSAndroid Build Coastguard Worker
67*9356374aSAndroid Build Coastguard Worker CRCImpl() = default;
68*9356374aSAndroid Build Coastguard Worker ~CRCImpl() override = default;
69*9356374aSAndroid Build Coastguard Worker
70*9356374aSAndroid Build Coastguard Worker // The internal version of CRC::New().
71*9356374aSAndroid Build Coastguard Worker static CRCImpl* NewInternal();
72*9356374aSAndroid Build Coastguard Worker
73*9356374aSAndroid Build Coastguard Worker // Fill in a table for updating a CRC by one word of 'word_size' bytes
74*9356374aSAndroid Build Coastguard Worker // [last_lo, last_hi] contains the answer if the last bit in the word
75*9356374aSAndroid Build Coastguard Worker // is set.
76*9356374aSAndroid Build Coastguard Worker static void FillWordTable(uint32_t poly, uint32_t last, int word_size,
77*9356374aSAndroid Build Coastguard Worker Uint32By256* t);
78*9356374aSAndroid Build Coastguard Worker
79*9356374aSAndroid Build Coastguard Worker // Build the table for extending by zeroes, returning the number of entries.
80*9356374aSAndroid Build Coastguard Worker // For a in {1, 2, ..., ZEROES_BASE-1}, b in {0, 1, 2, 3, ...},
81*9356374aSAndroid Build Coastguard Worker // entry j=a-1+(ZEROES_BASE-1)*b
82*9356374aSAndroid Build Coastguard Worker // contains a polynomial Pi such that multiplying
83*9356374aSAndroid Build Coastguard Worker // a CRC by Pi mod P, where P is the CRC polynomial, is equivalent to
84*9356374aSAndroid Build Coastguard Worker // appending a*2**(ZEROES_BASE_LG*b) zero bytes to the original string.
85*9356374aSAndroid Build Coastguard Worker static int FillZeroesTable(uint32_t poly, Uint32By256* t);
86*9356374aSAndroid Build Coastguard Worker
87*9356374aSAndroid Build Coastguard Worker virtual void InitTables() = 0;
88*9356374aSAndroid Build Coastguard Worker
89*9356374aSAndroid Build Coastguard Worker private:
90*9356374aSAndroid Build Coastguard Worker CRCImpl(const CRCImpl&) = delete;
91*9356374aSAndroid Build Coastguard Worker CRCImpl& operator=(const CRCImpl&) = delete;
92*9356374aSAndroid Build Coastguard Worker };
93*9356374aSAndroid Build Coastguard Worker
94*9356374aSAndroid Build Coastguard Worker // This is the 32-bit implementation. It handles all sizes from 8 to 32.
95*9356374aSAndroid Build Coastguard Worker class CRC32 : public CRCImpl {
96*9356374aSAndroid Build Coastguard Worker public:
97*9356374aSAndroid Build Coastguard Worker CRC32() = default;
98*9356374aSAndroid Build Coastguard Worker ~CRC32() override = default;
99*9356374aSAndroid Build Coastguard Worker
100*9356374aSAndroid Build Coastguard Worker void Extend(uint32_t* crc, const void* bytes, size_t length) const override;
101*9356374aSAndroid Build Coastguard Worker void ExtendByZeroes(uint32_t* crc, size_t length) const override;
102*9356374aSAndroid Build Coastguard Worker void Scramble(uint32_t* crc) const override;
103*9356374aSAndroid Build Coastguard Worker void Unscramble(uint32_t* crc) const override;
104*9356374aSAndroid Build Coastguard Worker void UnextendByZeroes(uint32_t* crc, size_t length) const override;
105*9356374aSAndroid Build Coastguard Worker
106*9356374aSAndroid Build Coastguard Worker void InitTables() override;
107*9356374aSAndroid Build Coastguard Worker
108*9356374aSAndroid Build Coastguard Worker private:
109*9356374aSAndroid Build Coastguard Worker // Common implementation guts for ExtendByZeroes and UnextendByZeroes().
110*9356374aSAndroid Build Coastguard Worker //
111*9356374aSAndroid Build Coastguard Worker // zeroes_table is a table as returned by FillZeroesTable(), containing
112*9356374aSAndroid Build Coastguard Worker // polynomials representing CRCs of strings-of-zeros of various lengths,
113*9356374aSAndroid Build Coastguard Worker // and which can be combined by polynomial multiplication. poly_table is
114*9356374aSAndroid Build Coastguard Worker // a table of CRC byte extension values. These tables are determined by
115*9356374aSAndroid Build Coastguard Worker // the generator polynomial.
116*9356374aSAndroid Build Coastguard Worker //
117*9356374aSAndroid Build Coastguard Worker // These will be set to reverse_zeroes_ and reverse_table0_ for Unextend, and
118*9356374aSAndroid Build Coastguard Worker // CRC32::zeroes_ and CRC32::table0_ for Extend.
119*9356374aSAndroid Build Coastguard Worker static void ExtendByZeroesImpl(uint32_t* crc, size_t length,
120*9356374aSAndroid Build Coastguard Worker const uint32_t zeroes_table[256],
121*9356374aSAndroid Build Coastguard Worker const uint32_t poly_table[256]);
122*9356374aSAndroid Build Coastguard Worker
123*9356374aSAndroid Build Coastguard Worker uint32_t table0_[256]; // table of byte extensions
124*9356374aSAndroid Build Coastguard Worker uint32_t zeroes_[256]; // table of zero extensions
125*9356374aSAndroid Build Coastguard Worker
126*9356374aSAndroid Build Coastguard Worker // table of 4-byte extensions shifted by 12 bytes of zeroes
127*9356374aSAndroid Build Coastguard Worker uint32_t table_[4][256];
128*9356374aSAndroid Build Coastguard Worker
129*9356374aSAndroid Build Coastguard Worker // Reverse lookup tables, using the alternate polynomial used by
130*9356374aSAndroid Build Coastguard Worker // UnextendByZeroes().
131*9356374aSAndroid Build Coastguard Worker uint32_t reverse_table0_[256]; // table of reverse byte extensions
132*9356374aSAndroid Build Coastguard Worker uint32_t reverse_zeroes_[256]; // table of reverse zero extensions
133*9356374aSAndroid Build Coastguard Worker
134*9356374aSAndroid Build Coastguard Worker CRC32(const CRC32&) = delete;
135*9356374aSAndroid Build Coastguard Worker CRC32& operator=(const CRC32&) = delete;
136*9356374aSAndroid Build Coastguard Worker };
137*9356374aSAndroid Build Coastguard Worker
138*9356374aSAndroid Build Coastguard Worker // Helpers
139*9356374aSAndroid Build Coastguard Worker
140*9356374aSAndroid Build Coastguard Worker // Return a bit mask containing len 1-bits.
141*9356374aSAndroid Build Coastguard Worker // Requires 0 < len <= sizeof(T)
142*9356374aSAndroid Build Coastguard Worker template <typename T>
MaskOfLength(int len)143*9356374aSAndroid Build Coastguard Worker T MaskOfLength(int len) {
144*9356374aSAndroid Build Coastguard Worker // shift 2 by len-1 rather than 1 by len because shifts of wordsize
145*9356374aSAndroid Build Coastguard Worker // are undefined.
146*9356374aSAndroid Build Coastguard Worker return (T(2) << (len - 1)) - 1;
147*9356374aSAndroid Build Coastguard Worker }
148*9356374aSAndroid Build Coastguard Worker
149*9356374aSAndroid Build Coastguard Worker // Rotate low-order "width" bits of "in" right by "r" bits,
150*9356374aSAndroid Build Coastguard Worker // setting other bits in word to arbitrary values.
151*9356374aSAndroid Build Coastguard Worker template <typename T>
RotateRight(T in,int width,int r)152*9356374aSAndroid Build Coastguard Worker T RotateRight(T in, int width, int r) {
153*9356374aSAndroid Build Coastguard Worker return (in << (width - r)) | ((in >> r) & MaskOfLength<T>(width - r));
154*9356374aSAndroid Build Coastguard Worker }
155*9356374aSAndroid Build Coastguard Worker
156*9356374aSAndroid Build Coastguard Worker // RoundUp<N>(p) returns the lowest address >= p aligned to an N-byte
157*9356374aSAndroid Build Coastguard Worker // boundary. Requires that N is a power of 2.
158*9356374aSAndroid Build Coastguard Worker template <int alignment>
RoundUp(const uint8_t * p)159*9356374aSAndroid Build Coastguard Worker const uint8_t* RoundUp(const uint8_t* p) {
160*9356374aSAndroid Build Coastguard Worker static_assert((alignment & (alignment - 1)) == 0, "alignment is not 2^n");
161*9356374aSAndroid Build Coastguard Worker constexpr uintptr_t mask = alignment - 1;
162*9356374aSAndroid Build Coastguard Worker const uintptr_t as_uintptr = reinterpret_cast<uintptr_t>(p);
163*9356374aSAndroid Build Coastguard Worker return reinterpret_cast<const uint8_t*>((as_uintptr + mask) & ~mask);
164*9356374aSAndroid Build Coastguard Worker }
165*9356374aSAndroid Build Coastguard Worker
166*9356374aSAndroid Build Coastguard Worker // Return a newly created CRC32AcceleratedX86ARMCombined if we can use Intel's
167*9356374aSAndroid Build Coastguard Worker // or ARM's CRC acceleration for a given polynomial. Return nullptr otherwise.
168*9356374aSAndroid Build Coastguard Worker CRCImpl* TryNewCRC32AcceleratedX86ARMCombined();
169*9356374aSAndroid Build Coastguard Worker
170*9356374aSAndroid Build Coastguard Worker // Return all possible hardware accelerated implementations. For testing only.
171*9356374aSAndroid Build Coastguard Worker std::vector<std::unique_ptr<CRCImpl>> NewCRC32AcceleratedX86ARMCombinedAll();
172*9356374aSAndroid Build Coastguard Worker
173*9356374aSAndroid Build Coastguard Worker } // namespace crc_internal
174*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
175*9356374aSAndroid Build Coastguard Worker } // namespace absl
176*9356374aSAndroid Build Coastguard Worker
177*9356374aSAndroid Build Coastguard Worker #endif // ABSL_CRC_INTERNAL_CRC_INTERNAL_H_
178