1 /* 7zCrcOpt.c -- CRC32 calculation (optimized functions)
2 2023-12-07 : Igor Pavlov : Public domain */
3
4 #include "Precomp.h"
5
6 #include "CpuArch.h"
7
8 #if !defined(Z7_CRC_NUM_TABLES) || Z7_CRC_NUM_TABLES > 1
9
10 // for debug only : define Z7_CRC_DEBUG_BE to test big-endian code in little-endian cpu
11 // #define Z7_CRC_DEBUG_BE
12 #ifdef Z7_CRC_DEBUG_BE
13 #undef MY_CPU_LE
14 #define MY_CPU_BE
15 #endif
16
17 // the value Z7_CRC_NUM_TABLES_USE must be defined to same value as in 7zCrc.c
18 #ifdef Z7_CRC_NUM_TABLES
19 #define Z7_CRC_NUM_TABLES_USE Z7_CRC_NUM_TABLES
20 #else
21 #define Z7_CRC_NUM_TABLES_USE 12
22 #endif
23
24 #if Z7_CRC_NUM_TABLES_USE % 4 || \
25 Z7_CRC_NUM_TABLES_USE < 4 * 1 || \
26 Z7_CRC_NUM_TABLES_USE > 4 * 6
27 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
28 #endif
29
30
31 #ifndef MY_CPU_BE
32
33 #define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
34
35 #define Q(n, d) \
36 ( (table + ((n) * 4 + 3) * 0x100)[(Byte)(d)] \
37 ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 1 * 8) & 0xFF] \
38 ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 2 * 8) & 0xFF] \
39 ^ (table + ((n) * 4 + 0) * 0x100)[((d) >> 3 * 8)] )
40
41 #define R(a) *((const UInt32 *)(const void *)p + (a))
42
43 #define CRC_FUNC_PRE_LE2(step) \
44 UInt32 Z7_FASTCALL CrcUpdateT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
45
46 #define CRC_FUNC_PRE_LE(step) \
47 CRC_FUNC_PRE_LE2(step); \
48 CRC_FUNC_PRE_LE2(step)
49
CRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE)50 CRC_FUNC_PRE_LE(Z7_CRC_NUM_TABLES_USE)
51 {
52 const Byte *p = (const Byte *)data;
53 const Byte *lim;
54 for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
55 v = CRC_UPDATE_BYTE_2(v, *p);
56 lim = p + size;
57 if (size >= Z7_CRC_NUM_TABLES_USE)
58 {
59 lim -= Z7_CRC_NUM_TABLES_USE;
60 do
61 {
62 v ^= R(0);
63 {
64 #if Z7_CRC_NUM_TABLES_USE == 1 * 4
65 v = Q(0, v);
66 #else
67 #define U2(r, op) \
68 { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
69 UInt32 d, x;
70 U2(1, =)
71 #if Z7_CRC_NUM_TABLES_USE >= 3 * 4
72 #define U(r) U2(r, ^=)
73 U(2)
74 #if Z7_CRC_NUM_TABLES_USE >= 4 * 4
75 U(3)
76 #if Z7_CRC_NUM_TABLES_USE >= 5 * 4
77 U(4)
78 #if Z7_CRC_NUM_TABLES_USE >= 6 * 4
79 U(5)
80 #if Z7_CRC_NUM_TABLES_USE >= 7 * 4
81 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
82 #endif
83 #endif
84 #endif
85 #endif
86 #endif
87 #undef U
88 #undef U2
89 v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
90 #endif
91 }
92 p += Z7_CRC_NUM_TABLES_USE;
93 }
94 while (p <= lim);
95 lim += Z7_CRC_NUM_TABLES_USE;
96 }
97 for (; p < lim; p++)
98 v = CRC_UPDATE_BYTE_2(v, *p);
99 return v;
100 }
101
102 #undef CRC_UPDATE_BYTE_2
103 #undef R
104 #undef Q
105 #undef CRC_FUNC_PRE_LE
106 #undef CRC_FUNC_PRE_LE2
107
108 #endif
109
110
111
112
113 #ifndef MY_CPU_LE
114
115 #define CRC_UPDATE_BYTE_2_BE(crc, b) (table[((crc) >> 24) ^ (b)] ^ ((crc) << 8))
116
117 #define Q(n, d) \
118 ( (table + ((n) * 4 + 0) * 0x100)[((d)) & 0xFF] \
119 ^ (table + ((n) * 4 + 1) * 0x100)[((d) >> 1 * 8) & 0xFF] \
120 ^ (table + ((n) * 4 + 2) * 0x100)[((d) >> 2 * 8) & 0xFF] \
121 ^ (table + ((n) * 4 + 3) * 0x100)[((d) >> 3 * 8)] )
122
123 #ifdef Z7_CRC_DEBUG_BE
124 #define R(a) GetBe32a((const UInt32 *)(const void *)p + (a))
125 #else
126 #define R(a) *((const UInt32 *)(const void *)p + (a))
127 #endif
128
129
130 #define CRC_FUNC_PRE_BE2(step) \
131 UInt32 Z7_FASTCALL CrcUpdateT1_BeT ## step (UInt32 v, const void *data, size_t size, const UInt32 *table)
132
133 #define CRC_FUNC_PRE_BE(step) \
134 CRC_FUNC_PRE_BE2(step); \
135 CRC_FUNC_PRE_BE2(step)
136
CRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE)137 CRC_FUNC_PRE_BE(Z7_CRC_NUM_TABLES_USE)
138 {
139 const Byte *p = (const Byte *)data;
140 const Byte *lim;
141 table += 0x100;
142 v = Z7_BSWAP32(v);
143 for (; size && ((unsigned)(ptrdiff_t)p & (7 - (Z7_CRC_NUM_TABLES_USE & 4))) != 0; size--, p++)
144 v = CRC_UPDATE_BYTE_2_BE(v, *p);
145 lim = p + size;
146 if (size >= Z7_CRC_NUM_TABLES_USE)
147 {
148 lim -= Z7_CRC_NUM_TABLES_USE;
149 do
150 {
151 v ^= R(0);
152 {
153 #if Z7_CRC_NUM_TABLES_USE == 1 * 4
154 v = Q(0, v);
155 #else
156 #define U2(r, op) \
157 { d = R(r); x op Q(Z7_CRC_NUM_TABLES_USE / 4 - 1 - (r), d); }
158 UInt32 d, x;
159 U2(1, =)
160 #if Z7_CRC_NUM_TABLES_USE >= 3 * 4
161 #define U(r) U2(r, ^=)
162 U(2)
163 #if Z7_CRC_NUM_TABLES_USE >= 4 * 4
164 U(3)
165 #if Z7_CRC_NUM_TABLES_USE >= 5 * 4
166 U(4)
167 #if Z7_CRC_NUM_TABLES_USE >= 6 * 4
168 U(5)
169 #if Z7_CRC_NUM_TABLES_USE >= 7 * 4
170 #error Stop_Compiling_Bad_Z7_CRC_NUM_TABLES
171 #endif
172 #endif
173 #endif
174 #endif
175 #endif
176 #undef U
177 #undef U2
178 v = x ^ Q(Z7_CRC_NUM_TABLES_USE / 4 - 1, v);
179 #endif
180 }
181 p += Z7_CRC_NUM_TABLES_USE;
182 }
183 while (p <= lim);
184 lim += Z7_CRC_NUM_TABLES_USE;
185 }
186 for (; p < lim; p++)
187 v = CRC_UPDATE_BYTE_2_BE(v, *p);
188 return Z7_BSWAP32(v);
189 }
190
191 #undef CRC_UPDATE_BYTE_2_BE
192 #undef R
193 #undef Q
194 #undef CRC_FUNC_PRE_BE
195 #undef CRC_FUNC_PRE_BE2
196
197 #endif
198 #undef Z7_CRC_NUM_TABLES_USE
199 #endif
200