12940b44dSPeter Avalos /////////////////////////////////////////////////////////////////////////////// 22940b44dSPeter Avalos // 32940b44dSPeter Avalos /// \file crc32.c 42940b44dSPeter Avalos /// \brief CRC32 calculation 52940b44dSPeter Avalos /// 62940b44dSPeter Avalos /// Calculate the CRC32 using the slice-by-eight algorithm. 72940b44dSPeter Avalos /// It is explained in this document: 82940b44dSPeter Avalos /// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf 92940b44dSPeter Avalos /// The code in this file is not the same as in Intel's paper, but 102940b44dSPeter Avalos /// the basic principle is identical. 112940b44dSPeter Avalos // 122940b44dSPeter Avalos // Author: Lasse Collin 132940b44dSPeter Avalos // 142940b44dSPeter Avalos // This file has been put into the public domain. 152940b44dSPeter Avalos // You can do whatever you want with this file. 162940b44dSPeter Avalos // 172940b44dSPeter Avalos /////////////////////////////////////////////////////////////////////////////// 182940b44dSPeter Avalos 192940b44dSPeter Avalos #include "check.h" 202940b44dSPeter Avalos #include "crc_macros.h" 212940b44dSPeter Avalos 222940b44dSPeter Avalos 232940b44dSPeter Avalos // If you make any changes, do some benchmarking! Seemingly unrelated 242940b44dSPeter Avalos // changes can very easily ruin the performance (and very probably is 252940b44dSPeter Avalos // very compiler dependent). 262940b44dSPeter Avalos extern LZMA_API(uint32_t) lzma_crc32(const uint8_t * buf,size_t size,uint32_t crc)272940b44dSPeter Avaloslzma_crc32(const uint8_t *buf, size_t size, uint32_t crc) 282940b44dSPeter Avalos { 292940b44dSPeter Avalos crc = ~crc; 302940b44dSPeter Avalos 312940b44dSPeter Avalos #ifdef WORDS_BIGENDIAN 322940b44dSPeter Avalos crc = bswap32(crc); 332940b44dSPeter Avalos #endif 342940b44dSPeter Avalos 352940b44dSPeter Avalos if (size > 8) { 362940b44dSPeter Avalos // Fix the alignment, if needed. The if statement above 372940b44dSPeter Avalos // ensures that this won't read past the end of buf[]. 382940b44dSPeter Avalos while ((uintptr_t)(buf) & 7) { 392940b44dSPeter Avalos crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc); 402940b44dSPeter Avalos --size; 412940b44dSPeter Avalos } 422940b44dSPeter Avalos 432940b44dSPeter Avalos // Calculate the position where to stop. 442940b44dSPeter Avalos const uint8_t *const limit = buf + (size & ~(size_t)(7)); 452940b44dSPeter Avalos 462940b44dSPeter Avalos // Calculate how many bytes must be calculated separately 472940b44dSPeter Avalos // before returning the result. 482940b44dSPeter Avalos size &= (size_t)(7); 492940b44dSPeter Avalos 502940b44dSPeter Avalos // Calculate the CRC32 using the slice-by-eight algorithm. 512940b44dSPeter Avalos while (buf < limit) { 52*e151908bSDaniel Fojt crc ^= aligned_read32ne(buf); 532940b44dSPeter Avalos buf += 4; 542940b44dSPeter Avalos 552940b44dSPeter Avalos crc = lzma_crc32_table[7][A(crc)] 562940b44dSPeter Avalos ^ lzma_crc32_table[6][B(crc)] 572940b44dSPeter Avalos ^ lzma_crc32_table[5][C(crc)] 582940b44dSPeter Avalos ^ lzma_crc32_table[4][D(crc)]; 592940b44dSPeter Avalos 60*e151908bSDaniel Fojt const uint32_t tmp = aligned_read32ne(buf); 612940b44dSPeter Avalos buf += 4; 622940b44dSPeter Avalos 632940b44dSPeter Avalos // At least with some compilers, it is critical for 642940b44dSPeter Avalos // performance, that the crc variable is XORed 652940b44dSPeter Avalos // between the two table-lookup pairs. 662940b44dSPeter Avalos crc = lzma_crc32_table[3][A(tmp)] 672940b44dSPeter Avalos ^ lzma_crc32_table[2][B(tmp)] 682940b44dSPeter Avalos ^ crc 692940b44dSPeter Avalos ^ lzma_crc32_table[1][C(tmp)] 702940b44dSPeter Avalos ^ lzma_crc32_table[0][D(tmp)]; 712940b44dSPeter Avalos } 722940b44dSPeter Avalos } 732940b44dSPeter Avalos 742940b44dSPeter Avalos while (size-- != 0) 752940b44dSPeter Avalos crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc); 762940b44dSPeter Avalos 772940b44dSPeter Avalos #ifdef WORDS_BIGENDIAN 782940b44dSPeter Avalos crc = bswap32(crc); 792940b44dSPeter Avalos #endif 802940b44dSPeter Avalos 812940b44dSPeter Avalos return ~crc; 822940b44dSPeter Avalos } 83