/* * CRC32 (Castagnoli 1993) * * Based on Michael E. Kounavis and Frank L. Berry: A Systematic Approach * to Building High Performance Software-based CRC Generators * (Proceedings of the 10th IEEE Symposium on Computers and Communications 2005) * * Includes code from http://sourceforge.net/projects/slicing-by-8/, * which carried the following copyright notice: * * Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved * * This software program is licensed subject to the BSD License, * available at http://www.opensource.org/licenses/bsd-license.html * * Adapted for LibUCW by Martin Mares in 2012. */ #include #include #include static void crc32_update_by1(crc32_context *ctx, const byte *buf, uint len) { u32 crc = ctx->state; while (len--) crc = crc_tableil8_o32[(crc ^ *buf++) & 0x000000FF] ^ (crc >> 8); ctx->state = crc; } static void crc32_update_by4(crc32_context *ctx, const byte *buf, uint len) { uint init_bytes, words; u32 crc = ctx->state; u32 term1, term2; const u32 *buf32; // Special case if (len < 4) goto small; // Align start address to a multiple of 4 bytes init_bytes = ((uintptr_t) buf) & 3; if (init_bytes) { init_bytes = 4 - init_bytes; len -= init_bytes; while (init_bytes--) crc = crc_tableil8_o32[(crc ^ *buf++) & 0x000000FF] ^ (crc >> 8); } // Process 4 bytes at a time words = len/4; len -= 4*words; buf32 = (const u32 *) buf; while (words--) { crc ^= *buf32++; term1 = crc_tableil8_o56[crc & 0x000000FF] ^ crc_tableil8_o48[(crc >> 8) & 0x000000FF]; term2 = crc >> 16; crc = term1 ^ crc_tableil8_o40[term2 & 0x000000FF] ^ crc_tableil8_o32[(term2 >> 8) & 0x000000FF]; } // Process remaining up to 7 bytes buf = (const byte *) buf32; small: while (len--) crc = crc_tableil8_o32[(crc ^ *buf++) & 0x000000FF] ^ (crc >> 8); ctx->state = crc; } static void crc32_update_by8(crc32_context *ctx, const byte *buf, uint len) { uint init_bytes, quads; u32 crc = ctx->state; u32 term1, term2; const u32 *buf32; // Special case if (len < 8) goto small; // Align start address to a multiple of 8 bytes init_bytes = ((uintptr_t) buf) & 7; if (init_bytes) { init_bytes = 8 - init_bytes; len -= init_bytes; while (init_bytes--) crc = crc_tableil8_o32[(crc ^ *buf++) & 0x000000FF] ^ (crc >> 8); } // Process 8 bytes at a time quads = len/8; len -= 8*quads; buf32 = (const u32 *) buf; while (quads--) { crc ^= *buf32++; term1 = crc_tableil8_o88[crc & 0x000000FF] ^ crc_tableil8_o80[(crc >> 8) & 0x000000FF]; term2 = crc >> 16; crc = term1 ^ crc_tableil8_o72[term2 & 0x000000FF] ^ crc_tableil8_o64[(term2 >> 8) & 0x000000FF]; term1 = crc_tableil8_o56[*buf32 & 0x000000FF] ^ crc_tableil8_o48[(*buf32 >> 8) & 0x000000FF]; term2 = *buf32 >> 16; crc = crc ^ term1 ^ crc_tableil8_o40[term2 & 0x000000FF] ^ crc_tableil8_o32[(term2 >> 8) & 0x000000FF]; buf32++; } // Process remaining up to 7 bytes buf = (const byte *) buf32; small: while (len--) crc = crc_tableil8_o32[(crc ^ *buf++) & 0x000000FF] ^ (crc >> 8); ctx->state = crc; } void crc32_init(crc32_context *ctx, uint crc_mode) { ctx->state = 0xffffffff; switch (crc_mode) { case CRC_MODE_DEFAULT: ctx->update_func = crc32_update_by4; break; case CRC_MODE_SMALL: ctx->update_func = crc32_update_by1; break; case CRC_MODE_BIG: ctx->update_func = crc32_update_by8; break; default: ASSERT(0); } } u32 crc32_hash_buffer(const byte *buf, uint len) { crc32_context ctx; crc32_init(&ctx, CRC_MODE_DEFAULT); crc32_update(&ctx, buf, len); return crc32_final(&ctx); } #ifdef TEST #include #include int main(int argc, char **argv) { if (argc != 5) die("Usage: crc-t "); uint alg = atoi(argv[1]); uint len = atoi(argv[2]); uint block = atoi(argv[3]); uint iters = atoi(argv[4]); byte *buf = xmalloc(len); for (uint i=0; i> 5) ^ (i >> 11); for (uint i=0; i