Line | Count | Source |
1 | | /* functable.c -- Choose relevant optimized functions at runtime |
2 | | * Copyright (C) 2017 Hans Kristian Rosbach |
3 | | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | | */ |
5 | | #ifndef DISABLE_RUNTIME_CPU_DETECTION |
6 | | |
7 | | #include "zbuild.h" |
8 | | |
9 | | #if defined(_MSC_VER) |
10 | | # include <intrin.h> |
11 | | #endif |
12 | | |
13 | | #include "functable.h" |
14 | | #include "cpu_features.h" |
15 | | #include "arch_functions.h" |
16 | | |
17 | | /* Platform has pointer size atomic store */ |
18 | | #if defined(__GNUC__) || defined(__clang__) |
19 | | # define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ |
20 | 24 | __atomic_store(&(functable.FUNC_NAME), &(VAR.FUNC_NAME), __ATOMIC_SEQ_CST) |
21 | 2 | # define FUNCTABLE_BARRIER() __atomic_thread_fence(__ATOMIC_SEQ_CST) |
22 | | #elif defined(_MSC_VER) |
23 | | # define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ |
24 | | _InterlockedExchangePointer((void * volatile *)&(functable.FUNC_NAME), (void *)(VAR.FUNC_NAME)) |
25 | | # ifdef ARCH_ARM |
26 | | # define FUNCTABLE_BARRIER() do { \ |
27 | | _ReadWriteBarrier(); \ |
28 | | __dmb(0xB); /* _ARM_BARRIER_ISH */ \ |
29 | | _ReadWriteBarrier(); \ |
30 | | } while (0) |
31 | | # else |
32 | | # define FUNCTABLE_BARRIER() _ReadWriteBarrier() |
33 | | # endif |
34 | | #else |
35 | | # warning Unable to detect atomic intrinsic support. |
36 | | # define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ |
37 | | *((void * volatile *)&(functable.FUNC_NAME)) = (void *)(VAR.FUNC_NAME) |
38 | | # define FUNCTABLE_BARRIER() do { /* Empty */ } while (0) |
39 | | #endif |
40 | | |
41 | | /* Verify all pointers are valid before assigning, return 1 on failure |
42 | | * This allows inflateinit/deflateinit functions to gracefully return Z_VERSION_ERROR |
43 | | * if functable initialization fails. |
44 | | */ |
45 | | #define FUNCTABLE_VERIFY_ASSIGN(VAR, FUNC_NAME) \ |
46 | 22 | if (!VAR.FUNC_NAME) { \ |
47 | 0 | fprintf(stderr, "Zlib-ng functable failed initialization!\n"); \ |
48 | 0 | return 1; \ |
49 | 0 | } \ |
50 | 22 | FUNCTABLE_ASSIGN(VAR, FUNC_NAME); |
51 | | |
52 | | /* Functable init & abort on failure. |
53 | | * Abort is needed because some stub functions are reachable without first |
54 | | * calling any inflateinit/deflateinit functions, and have no error propagation. |
55 | | */ |
56 | | #define FUNCTABLE_INIT_ABORT \ |
57 | 2 | if (init_functable()) { \ |
58 | 0 | fprintf(stderr, "Zlib-ng functable failed initialization!\n"); \ |
59 | 0 | abort(); \ |
60 | 2 | }; |
61 | | |
62 | | // Empty stub, used when functable has already been initialized |
63 | 7.19k | static int force_init_empty(void) { |
64 | 7.19k | return 0; |
65 | 7.19k | } |
66 | | |
67 | | /* Functable initialization. |
68 | | * Selects the best available optimized functions appropriate for the runtime cpu. |
69 | | */ |
70 | 2 | static int init_functable(void) { |
71 | 2 | struct functable_s ft; |
72 | 2 | struct cpu_features cf; |
73 | | |
74 | 2 | memset(&ft, 0, sizeof(struct functable_s)); |
75 | 2 | cpu_check_features(&cf); |
76 | 2 | ft.force_init = &force_init_empty; |
77 | | |
78 | | // Only use necessary generic functions when no suitable simd versions are available. |
79 | 2 | #ifdef ADLER32_FALLBACK |
80 | 2 | ft.adler32 = &adler32_c; |
81 | 2 | ft.adler32_copy = &adler32_copy_c; |
82 | 2 | #endif |
83 | | #ifdef CHUNKSET_FALLBACK |
84 | | ft.chunkmemset_safe = &chunkmemset_safe_c; |
85 | | ft.inflate_fast = &inflate_fast_c; |
86 | | #endif |
87 | | #ifdef COMPARE256_FALLBACK |
88 | | ft.compare256 = &compare256_c; |
89 | | ft.longest_match = &longest_match_c; |
90 | | ft.longest_match_roll = &longest_match_roll_c; |
91 | | #endif |
92 | 2 | #ifdef CRC32_BRAID_FALLBACK |
93 | 2 | ft.crc32 = &crc32_braid; |
94 | 2 | ft.crc32_copy = &crc32_copy_braid; |
95 | 2 | #endif |
96 | | #ifdef SLIDE_HASH_FALLBACK |
97 | | ft.slide_hash = &slide_hash_c; |
98 | | ft.slide_hash_head = &slide_hash_head_c; |
99 | | #endif |
100 | | |
101 | | // Select arch-optimized functions |
102 | 2 | #ifdef WITH_OPTIM |
103 | | |
104 | | // Chorba generic C fallback |
105 | 2 | #ifdef CRC32_CHORBA_FALLBACK |
106 | 2 | ft.crc32 = &crc32_chorba; |
107 | 2 | ft.crc32_copy = &crc32_copy_chorba; |
108 | 2 | #endif |
109 | | |
110 | | // X86 - SSE2 |
111 | 2 | #ifdef X86_SSE2 |
112 | | # ifndef X86_SSE2_NATIVE |
113 | | if (cf.x86.has_sse2) |
114 | | # endif |
115 | 2 | { |
116 | 2 | # ifndef X86_AVX2_NATIVE |
117 | 2 | ft.chunkmemset_safe = &chunkmemset_safe_sse2; |
118 | 2 | ft.compare256 = &compare256_sse2; |
119 | 2 | ft.inflate_fast = &inflate_fast_sse2; |
120 | 2 | ft.longest_match = &longest_match_sse2; |
121 | 2 | ft.longest_match_roll = &longest_match_roll_sse2; |
122 | 2 | ft.slide_hash = &slide_hash_sse2; |
123 | 2 | ft.slide_hash_head = &slide_hash_head_sse2; |
124 | 2 | # endif |
125 | 2 | # if defined(CRC32_CHORBA_SSE_FALLBACK) && !defined(X86_SSE41_NATIVE) && !defined(X86_PCLMULQDQ_NATIVE) |
126 | 2 | ft.crc32 = &crc32_chorba_sse2; |
127 | 2 | ft.crc32_copy = &crc32_copy_chorba_sse2; |
128 | 2 | # endif |
129 | 2 | } |
130 | 2 | #endif |
131 | | // X86 - SSSE3 |
132 | 2 | #ifdef X86_SSSE3 |
133 | 2 | # ifndef X86_SSSE3_NATIVE |
134 | 2 | if (cf.x86.has_ssse3) |
135 | 2 | # endif |
136 | 2 | { |
137 | 2 | ft.adler32 = &adler32_ssse3; |
138 | 2 | ft.adler32_copy = &adler32_copy_ssse3; |
139 | 2 | # ifndef X86_AVX2_NATIVE |
140 | 2 | ft.chunkmemset_safe = &chunkmemset_safe_ssse3; |
141 | 2 | ft.inflate_fast = &inflate_fast_ssse3; |
142 | 2 | # endif |
143 | 2 | } |
144 | 2 | #endif |
145 | | |
146 | | // X86 - SSE4.1 |
147 | 2 | #if defined(X86_SSE41) && !defined(X86_PCLMULQDQ_NATIVE) |
148 | 2 | # ifndef X86_SSE41_NATIVE |
149 | 2 | if (cf.x86.has_sse41) |
150 | 2 | # endif |
151 | 2 | { |
152 | 2 | # ifdef CRC32_CHORBA_SSE_FALLBACK |
153 | 2 | ft.crc32 = &crc32_chorba_sse41; |
154 | 2 | ft.crc32_copy = &crc32_copy_chorba_sse41; |
155 | 2 | # endif |
156 | 2 | } |
157 | 2 | #endif |
158 | | |
159 | | // X86 - SSE4.2 |
160 | 2 | #if defined(X86_SSE42) && !defined(X86_AVX512_NATIVE) |
161 | 2 | # ifndef X86_SSE42_NATIVE |
162 | 2 | if (cf.x86.has_sse42) |
163 | 2 | # endif |
164 | 2 | { |
165 | 2 | ft.adler32_copy = &adler32_copy_sse42; |
166 | 2 | } |
167 | 2 | #endif |
168 | | // X86 - PCLMUL |
169 | 2 | #if defined(X86_PCLMULQDQ_CRC) && !defined(X86_VPCLMULQDQ_NATIVE) |
170 | 2 | # ifndef X86_PCLMULQDQ_NATIVE |
171 | 2 | if (cf.x86.has_pclmulqdq) |
172 | 2 | # endif |
173 | 2 | { |
174 | 2 | ft.crc32 = &crc32_pclmulqdq; |
175 | 2 | ft.crc32_copy = &crc32_copy_pclmulqdq; |
176 | 2 | } |
177 | 2 | #endif |
178 | | // X86 - AVX2 |
179 | 2 | #ifdef X86_AVX2 |
180 | | /* BMI2 support is all but implicit with AVX2 but let's sanity check this just in case. Enabling BMI2 allows for |
181 | | * flagless shifts, resulting in fewer flag stalls for the pipeline, and allows us to set destination registers |
182 | | * for the shift results as an operand, eliminating several register-register moves when the original value needs |
183 | | * to remain intact. They also allow for a count operand that isn't the CL register, avoiding contention there */ |
184 | 2 | # ifndef X86_AVX2_NATIVE |
185 | 2 | if (cf.x86.has_avx2 && cf.x86.has_bmi2) |
186 | 2 | # endif |
187 | 2 | { |
188 | 2 | # ifndef X86_AVX512_NATIVE |
189 | 2 | ft.adler32 = &adler32_avx2; |
190 | 2 | ft.adler32_copy = &adler32_copy_avx2; |
191 | 2 | ft.chunkmemset_safe = &chunkmemset_safe_avx2; |
192 | 2 | ft.compare256 = &compare256_avx2; |
193 | 2 | ft.inflate_fast = &inflate_fast_avx2; |
194 | 2 | ft.longest_match = &longest_match_avx2; |
195 | 2 | ft.longest_match_roll = &longest_match_roll_avx2; |
196 | 2 | # endif |
197 | 2 | ft.slide_hash = &slide_hash_avx2; |
198 | 2 | ft.slide_hash_head = &slide_hash_head_avx2; |
199 | 2 | } |
200 | 2 | #endif |
201 | 2 | #ifdef X86_AVX2VNNI |
202 | 2 | if (cf.x86.has_avx2vnni) { |
203 | 0 | ft.adler32 = &adler32_avx2_vnni; |
204 | | //ft.adler32_copy = &adler32_copy_avx2_vnni; |
205 | 0 | } |
206 | 2 | #endif |
207 | | // X86 - AVX512 (F,DQ,BW,Vl) |
208 | 2 | #ifdef X86_AVX512 |
209 | 2 | # ifndef X86_AVX512_NATIVE |
210 | 2 | if (cf.x86.has_avx512_common) |
211 | 0 | # endif |
212 | 0 | { |
213 | 0 | # ifndef X86_AVX512VNNI_NATIVE |
214 | 0 | ft.adler32 = &adler32_avx512; |
215 | 0 | ft.adler32_copy = &adler32_copy_avx512; |
216 | 0 | # endif |
217 | 0 | ft.chunkmemset_safe = &chunkmemset_safe_avx512; |
218 | 0 | ft.compare256 = &compare256_avx512; |
219 | 0 | ft.inflate_fast = &inflate_fast_avx512; |
220 | 0 | ft.longest_match = &longest_match_avx512; |
221 | 0 | ft.longest_match_roll = &longest_match_roll_avx512; |
222 | 0 | } |
223 | 2 | #endif |
224 | 2 | #ifdef X86_AVX512VNNI |
225 | 2 | # ifndef X86_AVX512VNNI_NATIVE |
226 | 2 | if (cf.x86.has_avx512vnni) |
227 | 0 | # endif |
228 | 0 | { |
229 | 0 | ft.adler32 = &adler32_avx512_vnni; |
230 | 0 | ft.adler32_copy = &adler32_copy_avx512_vnni; |
231 | 0 | } |
232 | 2 | #endif |
233 | | // X86 - VPCLMULQDQ (AVX2) |
234 | 2 | #ifdef X86_VPCLMULQDQ_AVX2 |
235 | 2 | # ifndef X86_VPCLMULQDQ_AVX2_NATIVE |
236 | 2 | if (cf.x86.has_pclmulqdq && cf.x86.has_avx2 && cf.x86.has_vpclmulqdq) |
237 | 0 | # endif |
238 | 0 | { |
239 | 0 | ft.crc32 = &crc32_vpclmulqdq_avx2; |
240 | 0 | ft.crc32_copy = &crc32_copy_vpclmulqdq_avx2; |
241 | 0 | } |
242 | 2 | #endif |
243 | | // X86 - VPCLMULQDQ (AVX-512) |
244 | 2 | #ifdef X86_VPCLMULQDQ_AVX512 |
245 | 2 | # ifndef X86_VPCLMULQDQ_AVX512_NATIVE |
246 | 2 | if (cf.x86.has_pclmulqdq && cf.x86.has_avx512_common && cf.x86.has_vpclmulqdq) |
247 | 0 | # endif |
248 | 0 | { |
249 | 0 | ft.crc32 = &crc32_vpclmulqdq_avx512; |
250 | 0 | ft.crc32_copy = &crc32_copy_vpclmulqdq_avx512; |
251 | 0 | } |
252 | 2 | #endif |
253 | | |
254 | | |
255 | | // ARM - SIMD |
256 | | #if defined(ARM_SIMD) && !defined(ARM_NEON_NATIVE) |
257 | | # ifndef ARM_SIMD_NATIVE |
258 | | if (cf.arm.has_simd) |
259 | | # endif |
260 | | { |
261 | | ft.slide_hash = &slide_hash_armv6; |
262 | | ft.slide_hash_head = &slide_hash_head_armv6; |
263 | | } |
264 | | #endif |
265 | | // ARM - NEON |
266 | | #ifdef ARM_NEON |
267 | | # ifndef ARM_NEON_NATIVE |
268 | | if (cf.arm.has_neon) |
269 | | # endif |
270 | | { |
271 | | ft.adler32 = &adler32_neon; |
272 | | ft.adler32_copy = &adler32_copy_neon; |
273 | | ft.chunkmemset_safe = &chunkmemset_safe_neon; |
274 | | ft.compare256 = &compare256_neon; |
275 | | ft.inflate_fast = &inflate_fast_neon; |
276 | | ft.longest_match = &longest_match_neon; |
277 | | ft.longest_match_roll = &longest_match_roll_neon; |
278 | | ft.slide_hash = &slide_hash_neon; |
279 | | ft.slide_hash_head = &slide_hash_head_neon; |
280 | | } |
281 | | #endif |
282 | | // ARM - NEON DotProd |
283 | | #ifdef ARM_NEON_DOTPROD |
284 | | # ifndef ARM_NEON_DOTPROD_NATIVE |
285 | | if (cf.arm.has_neon && cf.arm.has_dotprod) |
286 | | # endif |
287 | | { |
288 | | ft.adler32 = &adler32_neon_dotprod; |
289 | | ft.adler32_copy = &adler32_copy_neon_dotprod; |
290 | | } |
291 | | #endif |
292 | | // ARM - CRC32 |
293 | | #if defined(ARM_CRC32) && !defined(ARM_PMULL_EOR3_NATIVE) |
294 | | # ifndef ARM_CRC32_NATIVE |
295 | | if (cf.arm.has_crc32) |
296 | | # endif |
297 | | { |
298 | | ft.crc32 = &crc32_armv8; |
299 | | ft.crc32_copy = &crc32_copy_armv8; |
300 | | } |
301 | | #endif |
302 | | // ARM - PMULL EOR3 |
303 | | #ifdef ARM_PMULL_EOR3 |
304 | | # ifndef ARM_PMULL_EOR3_NATIVE |
305 | | if (cf.arm.has_crc32 && cf.arm.has_pmull && cf.arm.has_eor3 && cf.arm.has_fast_pmull) |
306 | | # endif |
307 | | { |
308 | | ft.crc32 = &crc32_armv8_pmull_eor3; |
309 | | ft.crc32_copy = &crc32_copy_armv8_pmull_eor3; |
310 | | } |
311 | | #endif |
312 | | |
313 | | // Power - VMX |
314 | | #ifdef PPC_VMX |
315 | | # ifndef PPC_VMX_NATIVE |
316 | | if (cf.power.has_altivec) |
317 | | # endif |
318 | | { |
319 | | ft.adler32 = &adler32_vmx; |
320 | | ft.adler32_copy = &adler32_copy_vmx; |
321 | | ft.slide_hash = &slide_hash_vmx; |
322 | | ft.slide_hash_head = &slide_hash_head_vmx; |
323 | | } |
324 | | #endif |
325 | | // Power8 - VSX |
326 | | #ifdef POWER8_VSX |
327 | | # ifndef POWER8_VSX_NATIVE |
328 | | if (cf.power.has_arch_2_07) |
329 | | # endif |
330 | | { |
331 | | ft.adler32 = &adler32_power8; |
332 | | ft.adler32_copy = &adler32_copy_power8; |
333 | | ft.chunkmemset_safe = &chunkmemset_safe_power8; |
334 | | ft.inflate_fast = &inflate_fast_power8; |
335 | | ft.slide_hash = &slide_hash_power8; |
336 | | ft.slide_hash_head = &slide_hash_head_power8; |
337 | | } |
338 | | #endif |
339 | | #ifdef POWER8_VSX_CRC32 |
340 | | # ifndef POWER8_VSX_CRC32_NATIVE |
341 | | if (cf.power.has_arch_2_07) |
342 | | # endif |
343 | | { |
344 | | ft.crc32 = &crc32_power8; |
345 | | ft.crc32_copy = &crc32_copy_power8; |
346 | | } |
347 | | #endif |
348 | | // Power9 |
349 | | #ifdef POWER9 |
350 | | # ifndef POWER9_NATIVE |
351 | | if (cf.power.has_arch_3_00) |
352 | | # endif |
353 | | { |
354 | | ft.compare256 = &compare256_power9; |
355 | | ft.longest_match = &longest_match_power9; |
356 | | ft.longest_match_roll = &longest_match_roll_power9; |
357 | | } |
358 | | #endif |
359 | | |
360 | | |
361 | | // RISCV - RVV |
362 | | #ifdef RISCV_RVV |
363 | | # ifndef RISCV_RVV_NATIVE |
364 | | if (cf.riscv.has_rvv) |
365 | | # endif |
366 | | { |
367 | | ft.adler32 = &adler32_rvv; |
368 | | ft.adler32_copy = &adler32_copy_rvv; |
369 | | ft.chunkmemset_safe = &chunkmemset_safe_rvv; |
370 | | ft.compare256 = &compare256_rvv; |
371 | | ft.inflate_fast = &inflate_fast_rvv; |
372 | | ft.longest_match = &longest_match_rvv; |
373 | | ft.longest_match_roll = &longest_match_roll_rvv; |
374 | | ft.slide_hash = &slide_hash_rvv; |
375 | | ft.slide_hash_head = &slide_hash_head_rvv; |
376 | | } |
377 | | #endif |
378 | | |
379 | | // RISCV - ZBC |
380 | | #ifdef RISCV_CRC32_ZBC |
381 | | # ifndef RISCV_ZBC_NATIVE |
382 | | if (cf.riscv.has_zbc) |
383 | | # endif |
384 | | { |
385 | | ft.crc32 = &crc32_riscv64_zbc; |
386 | | ft.crc32_copy = &crc32_copy_riscv64_zbc; |
387 | | } |
388 | | #endif |
389 | | |
390 | | // S390 |
391 | | #ifdef S390_VX |
392 | | # ifndef S390_VX_NATIVE |
393 | | if (cf.s390.has_vx) |
394 | | # endif |
395 | | { |
396 | | ft.crc32 = &crc32_s390_vx; |
397 | | ft.crc32_copy = &crc32_copy_s390_vx; |
398 | | ft.slide_hash = &slide_hash_vx; |
399 | | ft.slide_hash_head = &slide_hash_head_vx; |
400 | | } |
401 | | #endif |
402 | | |
403 | | // LOONGARCH |
404 | | #ifdef LOONGARCH_CRC |
405 | | # ifndef LOONGARCH_CRC_NATIVE |
406 | | if (cf.loongarch.has_crc) |
407 | | # endif |
408 | | { |
409 | | ft.crc32 = &crc32_loongarch64; |
410 | | ft.crc32_copy = &crc32_copy_loongarch64; |
411 | | } |
412 | | #endif |
413 | | #if defined(LOONGARCH_LSX) && !defined(LOONGARCH_LASX_NATIVE) |
414 | | # ifndef LOONGARCH_LSX_NATIVE |
415 | | if (cf.loongarch.has_lsx) |
416 | | # endif |
417 | | { |
418 | | ft.adler32 = &adler32_lsx; |
419 | | ft.adler32_copy = &adler32_copy_lsx; |
420 | | ft.chunkmemset_safe = &chunkmemset_safe_lsx; |
421 | | ft.compare256 = &compare256_lsx; |
422 | | ft.inflate_fast = &inflate_fast_lsx; |
423 | | ft.longest_match = &longest_match_lsx; |
424 | | ft.longest_match_roll = &longest_match_roll_lsx; |
425 | | ft.slide_hash = &slide_hash_lsx; |
426 | | ft.slide_hash_head = &slide_hash_head_lsx; |
427 | | } |
428 | | #endif |
429 | | #ifdef LOONGARCH_LASX |
430 | | # ifndef LOONGARCH_LASX_NATIVE |
431 | | if (cf.loongarch.has_lasx) |
432 | | # endif |
433 | | { |
434 | | ft.adler32 = &adler32_lasx; |
435 | | ft.adler32_copy = &adler32_copy_lasx; |
436 | | ft.chunkmemset_safe = &chunkmemset_safe_lasx; |
437 | | ft.compare256 = &compare256_lasx; |
438 | | ft.inflate_fast = &inflate_fast_lasx; |
439 | | ft.longest_match = &longest_match_lasx; |
440 | | ft.longest_match_roll = &longest_match_roll_lasx; |
441 | | ft.slide_hash = &slide_hash_lasx; |
442 | | ft.slide_hash_head = &slide_hash_head_lasx; |
443 | | } |
444 | | #endif |
445 | | |
446 | 2 | #endif // WITH_OPTIM |
447 | | |
448 | | // Assign function pointers individually for atomic operation |
449 | 2 | FUNCTABLE_ASSIGN(ft, force_init); |
450 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, adler32); |
451 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, adler32_copy); |
452 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, chunkmemset_safe); |
453 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, compare256); |
454 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, crc32); |
455 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, crc32_copy); |
456 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, inflate_fast); |
457 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, longest_match); |
458 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, longest_match_roll); |
459 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, slide_hash); |
460 | 2 | FUNCTABLE_VERIFY_ASSIGN(ft, slide_hash_head); |
461 | | |
462 | | // Memory barrier for weak memory order CPUs |
463 | 2 | FUNCTABLE_BARRIER(); |
464 | | |
465 | 2 | return Z_OK; |
466 | 2 | } |
467 | | |
468 | | #if !defined(_WIN32) && (defined(__GNUC__) || defined(__clang__)) |
469 | 2 | static void __attribute__((constructor)) functable_constructor(void) { |
470 | 2 | FUNCTABLE_INIT_ABORT; |
471 | 2 | } |
472 | | #endif |
473 | | |
474 | | /* stub functions */ |
475 | 0 | static int force_init_stub(void) { |
476 | 0 | return init_functable(); |
477 | 0 | } |
478 | | |
479 | 0 | static uint32_t adler32_stub(uint32_t adler, const uint8_t* buf, size_t len) { |
480 | 0 | FUNCTABLE_INIT_ABORT; |
481 | 0 | return functable.adler32(adler, buf, len); |
482 | 0 | } |
483 | | |
484 | 0 | static uint32_t adler32_copy_stub(uint32_t adler, uint8_t* dst, const uint8_t* src, size_t len) { |
485 | 0 | FUNCTABLE_INIT_ABORT; |
486 | 0 | return functable.adler32_copy(adler, dst, src, len); |
487 | 0 | } |
488 | | |
489 | 0 | static uint8_t* chunkmemset_safe_stub(uint8_t* out, uint8_t *from, size_t len, size_t left) { |
490 | 0 | FUNCTABLE_INIT_ABORT; |
491 | 0 | return functable.chunkmemset_safe(out, from, len, left); |
492 | 0 | } |
493 | | |
494 | 0 | static uint32_t compare256_stub(const uint8_t* src0, const uint8_t* src1) { |
495 | 0 | FUNCTABLE_INIT_ABORT; |
496 | 0 | return functable.compare256(src0, src1); |
497 | 0 | } |
498 | | |
499 | 0 | static uint32_t crc32_stub(uint32_t crc, const uint8_t* buf, size_t len) { |
500 | 0 | FUNCTABLE_INIT_ABORT; |
501 | 0 | return functable.crc32(crc, buf, len); |
502 | 0 | } |
503 | | |
504 | 0 | static uint32_t crc32_copy_stub(uint32_t crc, uint8_t *dst, const uint8_t *src, size_t len) { |
505 | 0 | FUNCTABLE_INIT_ABORT; |
506 | 0 | return functable.crc32_copy(crc, dst, src, len); |
507 | 0 | } |
508 | | |
509 | 0 | static void inflate_fast_stub(PREFIX3(stream) *strm, uint32_t start, int safe_mode) { |
510 | 0 | FUNCTABLE_INIT_ABORT; |
511 | 0 | functable.inflate_fast(strm, start, safe_mode); |
512 | 0 | } |
513 | | |
514 | 0 | static uint32_t longest_match_stub(deflate_state* const s, uint32_t cur_match) { |
515 | 0 | FUNCTABLE_INIT_ABORT; |
516 | 0 | return functable.longest_match(s, cur_match); |
517 | 0 | } |
518 | | |
519 | 0 | static uint32_t longest_match_roll_stub(deflate_state* const s, uint32_t cur_match) { |
520 | 0 | FUNCTABLE_INIT_ABORT; |
521 | 0 | return functable.longest_match_roll(s, cur_match); |
522 | 0 | } |
523 | | |
524 | 0 | static void slide_hash_stub(deflate_state* s) { |
525 | 0 | FUNCTABLE_INIT_ABORT; |
526 | 0 | functable.slide_hash(s); |
527 | 0 | } |
528 | | |
529 | 0 | static void slide_hash_head_stub(deflate_state *s) { |
530 | 0 | FUNCTABLE_INIT_ABORT; |
531 | 0 | functable.slide_hash_head(s); |
532 | 0 | } |
533 | | |
534 | | /* functable init */ |
535 | | Z_INTERNAL struct functable_s functable = { |
536 | | force_init_stub, |
537 | | adler32_stub, |
538 | | adler32_copy_stub, |
539 | | chunkmemset_safe_stub, |
540 | | compare256_stub, |
541 | | crc32_stub, |
542 | | crc32_copy_stub, |
543 | | inflate_fast_stub, |
544 | | longest_match_stub, |
545 | | longest_match_roll_stub, |
546 | | slide_hash_stub, |
547 | | slide_hash_head_stub, |
548 | | }; |
549 | | |
550 | | #endif |