luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

CRC32.c (4093B)


      1 /*
      2  * CRC32 Implementation with Hardware Acceleration
      3  * Uses CRC32 instruction (SSE 4.2) when available
      4  */
      5 
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <stdint.h>
     10 #include <immintrin.h>
     11 
     12 #ifdef __GNUC__
     13 #include <cpuid.h>
     14 #endif
     15 
     16 // CPU feature detection
     17 static int has_crc32_inst = 0;
     18 static int features_detected = 0;
     19 
     20 static void detect_cpu_features(void) {
     21     if (features_detected) return;
     22 #ifdef __GNUC__
     23     unsigned int eax, ebx, ecx, edx;
     24     if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
     25         has_crc32_inst = (ecx & bit_SSE4_2) != 0;
     26     }
     27 #endif
     28     features_detected = 1;
     29 }
     30 
     31 // CRC32 lookup table (for software fallback)
     32 static uint32_t crc32_table[256];
     33 static int table_initialized = 0;
     34 
     35 static void crc32_init_table(void) {
     36     if (table_initialized) return;
     37 
     38     for (uint32_t i = 0; i < 256; i++) {
     39         uint32_t crc = i;
     40         for (int j = 0; j < 8; j++) {
     41             if (crc & 1) {
     42                 crc = (crc >> 1) ^ 0xEDB88320;
     43             } else {
     44                 crc >>= 1;
     45             }
     46         }
     47         crc32_table[i] = crc;
     48     }
     49     table_initialized = 1;
     50 }
     51 
     52 // Software CRC32 implementation
     53 static uint32_t crc32_software(const uint8_t *data, size_t len, uint32_t crc) {
     54     if (!table_initialized) {
     55         crc32_init_table();
     56     }
     57 
     58     crc = ~crc;
     59     for (size_t i = 0; i < len; i++) {
     60         crc = crc32_table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
     61     }
     62     return ~crc;
     63 }
     64 
     65 // Hardware CRC32 implementation (SSE 4.2)
     66 #ifdef __SSE4_2__
     67 static uint32_t crc32_hardware(const uint8_t *data, size_t len, uint32_t crc) {
     68     size_t i;
     69 
     70     // Process 8 bytes at a time on 64-bit
     71     #if defined(__x86_64__) || defined(_M_X64)
     72     for (i = 0; i + 7 < len; i += 8) {
     73         uint64_t val;
     74         memcpy(&val, data + i, 8);
     75         crc = _mm_crc32_u64(crc, val);
     76     }
     77     #else
     78     // Process 4 bytes at a time on 32-bit
     79     for (i = 0; i + 3 < len; i += 4) {
     80         uint32_t val;
     81         memcpy(&val, data + i, 4);
     82         crc = _mm_crc32_u32(crc, val);
     83     }
     84     #endif
     85 
     86     // Process remaining bytes
     87     for (; i < len; i++) {
     88         crc = _mm_crc32_u8(crc, data[i]);
     89     }
     90 
     91     return crc;
     92 }
     93 #endif
     94 
     95 // Public CRC32 function
     96 uint32_t crc32(const uint8_t *data, size_t len) {
     97     if (!features_detected) {
     98         detect_cpu_features();
     99     }
    100 
    101 #ifdef __SSE4_2__
    102     if (has_crc32_inst) {
    103         return crc32_hardware(data, len, 0);
    104     }
    105 #endif
    106 
    107     return crc32_software(data, len, 0);
    108 }
    109 
    110 // CRC32 with initial value
    111 uint32_t crc32_continue(const uint8_t *data, size_t len, uint32_t initial_crc) {
    112     if (!features_detected) {
    113         detect_cpu_features();
    114     }
    115 
    116 #ifdef __SSE4_2__
    117     if (has_crc32_inst) {
    118         return crc32_hardware(data, len, initial_crc);
    119     }
    120 #endif
    121 
    122     return crc32_software(data, len, initial_crc);
    123 }
    124 
    125 // Test program
    126 #ifndef LIB_MODE
    127 int main(void) {
    128     detect_cpu_features();
    129 
    130     printf("CRC32 Implementation\n");
    131     printf("====================\n");
    132     printf("Hardware acceleration (CRC32 instruction): %s\n\n", has_crc32_inst ? "Yes" : "No");
    133 
    134     // Test vectors
    135     const char *test1 = "";
    136     const char *test2 = "The quick brown fox jumps over the lazy dog";
    137     const char *test3 = "123456789";
    138 
    139     uint32_t crc;
    140 
    141     // Test 1
    142     printf("Test 1: \"%s\"\n", test1);
    143     crc = crc32((uint8_t*)test1, strlen(test1));
    144     printf("CRC32: 0x%08x\n", crc);
    145     printf("Expected: 0x00000000\n\n");
    146 
    147     // Test 2
    148     printf("Test 2: \"%s\"\n", test2);
    149     crc = crc32((uint8_t*)test2, strlen(test2));
    150     printf("CRC32: 0x%08x\n", crc);
    151     printf("Expected: 0x414fa339\n\n");
    152 
    153     // Test 3
    154     printf("Test 3: \"%s\"\n", test3);
    155     crc = crc32((uint8_t*)test3, strlen(test3));
    156     printf("CRC32: 0x%08x\n", crc);
    157     printf("Expected: 0xcbf43926\n\n");
    158 
    159     // Test incremental CRC
    160     printf("Test 4: Incremental CRC of \"123\" + \"456789\"\n");
    161     uint32_t crc1 = crc32((uint8_t*)"123", 3);
    162     uint32_t crc2 = crc32_continue((uint8_t*)"456789", 6, crc1);
    163     printf("CRC32: 0x%08x\n", crc2);
    164     printf("Expected: 0xcbf43926 (same as Test 3)\n\n");
    165 
    166     return 0;
    167 }
    168 #endif