1207753Smm///////////////////////////////////////////////////////////////////////////////
2207753Smm//
3207753Smm/// \file       crc32.c
4207753Smm/// \brief      CRC32 calculation
5207753Smm///
6207753Smm/// Calculate the CRC32 using the slice-by-eight algorithm.
7207753Smm/// It is explained in this document:
8207753Smm/// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
9207753Smm/// The code in this file is not the same as in Intel's paper, but
10207753Smm/// the basic principle is identical.
11207753Smm//
12207753Smm//  Author:     Lasse Collin
13207753Smm//
14207753Smm//  This file has been put into the public domain.
15207753Smm//  You can do whatever you want with this file.
16207753Smm//
17207753Smm///////////////////////////////////////////////////////////////////////////////
18207753Smm
19207753Smm#include "check.h"
20207753Smm#include "crc_macros.h"
21207753Smm
22207753Smm
23207753Smm// If you make any changes, do some bench marking! Seemingly unrelated
24207753Smm// changes can very easily ruin the performance (and very probably is
25207753Smm// very compiler dependent).
26207753Smmextern LZMA_API(uint32_t)
27207753Smmlzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
28207753Smm{
29207753Smm	crc = ~crc;
30207753Smm
31207753Smm#ifdef WORDS_BIGENDIAN
32207753Smm	crc = bswap32(crc);
33207753Smm#endif
34207753Smm
35207753Smm	if (size > 8) {
36207753Smm		// Fix the alignment, if needed. The if statement above
37207753Smm		// ensures that this won't read past the end of buf[].
38207753Smm		while ((uintptr_t)(buf) & 7) {
39207753Smm			crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
40207753Smm			--size;
41207753Smm		}
42207753Smm
43207753Smm		// Calculate the position where to stop.
44207753Smm		const uint8_t *const limit = buf + (size & ~(size_t)(7));
45207753Smm
46207753Smm		// Calculate how many bytes must be calculated separately
47207753Smm		// before returning the result.
48207753Smm		size &= (size_t)(7);
49207753Smm
50207753Smm		// Calculate the CRC32 using the slice-by-eight algorithm.
51207753Smm		while (buf < limit) {
52207753Smm			crc ^= *(const uint32_t *)(buf);
53207753Smm			buf += 4;
54207753Smm
55207753Smm			crc = lzma_crc32_table[7][A(crc)]
56207753Smm			    ^ lzma_crc32_table[6][B(crc)]
57207753Smm			    ^ lzma_crc32_table[5][C(crc)]
58207753Smm			    ^ lzma_crc32_table[4][D(crc)];
59207753Smm
60207753Smm			const uint32_t tmp = *(const uint32_t *)(buf);
61207753Smm			buf += 4;
62207753Smm
63207753Smm			// At least with some compilers, it is critical for
64207753Smm			// performance, that the crc variable is XORed
65207753Smm			// between the two table-lookup pairs.
66207753Smm			crc = lzma_crc32_table[3][A(tmp)]
67207753Smm			    ^ lzma_crc32_table[2][B(tmp)]
68207753Smm			    ^ crc
69207753Smm			    ^ lzma_crc32_table[1][C(tmp)]
70207753Smm			    ^ lzma_crc32_table[0][D(tmp)];
71207753Smm		}
72207753Smm	}
73207753Smm
74207753Smm	while (size-- != 0)
75207753Smm		crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
76207753Smm
77207753Smm#ifdef WORDS_BIGENDIAN
78207753Smm	crc = bswap32(crc);
79207753Smm#endif
80207753Smm
81207753Smm	return ~crc;
82207753Smm}
83