15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 7zCrc.c -- CRC32 calculation
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)2009-11-23 : Igor Pavlov : Public domain */
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "7zCrc.h"
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "CpuArch.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define kCrcPoly 0xEDB88320
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef MY_CPU_LE
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CRC_NUM_TABLES 8
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CRC_NUM_TABLES 1
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static CRC_FUNC g_CrcUpdate;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if CRC_NUM_TABLES == 1
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Byte *p = (const Byte *)data;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; size > 0; size--, p++)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v = CRC_UPDATE_BYTE_2(v, *p);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return v;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_CrcUpdate(v, data, size, g_CrcTable);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MY_FAST_CALL CrcGenerateTable()
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UInt32 i;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < 256; i++)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 r = i;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned j;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (j = 0; j < 8; j++)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_CrcTable[i] = r;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #if CRC_NUM_TABLES == 1
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_CrcUpdate = CrcUpdateT1;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #else
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; i < 256 * CRC_NUM_TABLES; i++)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UInt32 r = g_CrcTable[i - 256];
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_CrcUpdate = CrcUpdateT4;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #ifdef MY_CPU_X86_OR_AMD64
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CPU_Is_InOrder())
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_CrcUpdate = CrcUpdateT8;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #endif
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #endif
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
75