1218887Sdim///////////////////////////////////////////////////////////////////////////////
2218887Sdim//
3218887Sdim/// \file       crc32.c
4218887Sdim/// \brief      CRC32 calculation
5218887Sdim///
6218887Sdim/// Calculate the CRC32 using the slice-by-eight algorithm.
7218887Sdim/// It is explained in this document:
8218887Sdim/// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
9218887Sdim/// The code in this file is not the same as in Intel's paper, but
10218887Sdim/// the basic principle is identical.
11218887Sdim//
12218887Sdim//  Author:     Lasse Collin
13218887Sdim//
14218887Sdim//  This file has been put into the public domain.
15218887Sdim//  You can do whatever you want with this file.
16243830Sdim//
17249423Sdim///////////////////////////////////////////////////////////////////////////////
18243830Sdim
19243830Sdim#include "check.h"
20218887Sdim#include "crc_macros.h"
21243830Sdim
22218887Sdim
23243830Sdim// If you make any changes, do some benchmarking! Seemingly unrelated
24243830Sdim// changes can very easily ruin the performance (and very probably is
25243830Sdim// very compiler dependent).
26234353Sdimextern LZMA_API(uint32_t)
27243830Sdimlzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
28218887Sdim{
29218887Sdim	crc = ~crc;
30218887Sdim
31218887Sdim#ifdef WORDS_BIGENDIAN
32243830Sdim	crc = bswap32(crc);
33243830Sdim#endif
34243830Sdim
35243830Sdim	if (size > 8) {
36243830Sdim		// Fix the alignment, if needed. The if statement above
37243830Sdim		// ensures that this won't read past the end of buf[].
38243830Sdim		while ((uintptr_t)(buf) & 7) {
39243830Sdim			crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
40243830Sdim			--size;
41243830Sdim		}
42243830Sdim
43243830Sdim		// Calculate the position where to stop.
44243830Sdim		const uint8_t *const limit = buf + (size & ~(size_t)(7));
45243830Sdim
46243830Sdim		// Calculate how many bytes must be calculated separately
47243830Sdim		// before returning the result.
48243830Sdim		size &= (size_t)(7);
49243830Sdim
50243830Sdim		// Calculate the CRC32 using the slice-by-eight algorithm.
51243830Sdim		while (buf < limit) {
52243830Sdim			crc ^= *(const uint32_t *)(buf);
53243830Sdim			buf += 4;
54243830Sdim
55243830Sdim			crc = lzma_crc32_table[7][A(crc)]
56243830Sdim			    ^ lzma_crc32_table[6][B(crc)]
57243830Sdim			    ^ lzma_crc32_table[5][C(crc)]
58243830Sdim			    ^ lzma_crc32_table[4][D(crc)];
59243830Sdim
60243830Sdim			const uint32_t tmp = *(const uint32_t *)(buf);
61243830Sdim			buf += 4;
62243830Sdim
63243830Sdim			// At least with some compilers, it is critical for
64243830Sdim			// performance, that the crc variable is XORed
65218887Sdim			// between the two table-lookup pairs.
66218887Sdim			crc = lzma_crc32_table[3][A(tmp)]
67218887Sdim			    ^ lzma_crc32_table[2][B(tmp)]
68218887Sdim			    ^ crc
69218887Sdim			    ^ lzma_crc32_table[1][C(tmp)]
70218887Sdim			    ^ lzma_crc32_table[0][D(tmp)];
71218887Sdim		}
72218887Sdim	}
73218887Sdim
74218887Sdim	while (size-- != 0)
75218887Sdim		crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
76218887Sdim
77218887Sdim#ifdef WORDS_BIGENDIAN
78218887Sdim	crc = bswap32(crc);
79218887Sdim#endif
80218887Sdim
81218887Sdim	return ~crc;
82218887Sdim}
83218887Sdim