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