Implementazione del CRC32C di SSE 4.2 nel software

Quindi ho un progetto che incorpora i checksum CRC32C per garantire che i dati non siano stati danneggiati. Ho deciso di utilizzare CRC32C perché posso avere sia una versione software che una versione con accelerazione hardware se il computer su cui è installato il software supporta SSE 4.2

Vado dal manuale per sviluppatori Intel (vol 2A), che sembra fornire l’algoritmo dietro l’istruzione crc32 . Tuttavia, sto avendo poca fortuna. La guida per gli sviluppatori di Intel dice quanto segue:

 BIT_REFLECT32: DEST[31-0] = SRC[0-31] MOD2: Remainder from Polynomial division modulus 2 TEMP1[31-0] <- BIT_REFLECT(SRC[31-0]) TEMP2[31-0] <- BIT_REFLECT(DEST[31-0]) TEMP3[63-0] <- TEMP1[31-0] << 32 TEMP4[63-0] <- TEMP2[31-0] << 32 TEMP5[63-0] <- TEMP3[63-0] XOR TEMP4[63-0] TEMP6[31-0] <- TEMP5[63-0] MOD2 0x11EDC6F41 DEST[31-0] <- BIT_REFLECT(TEMP6[31-0]) 

Ora, per quanto posso dire, ho fatto tutto fino alla linea iniziando correttamente TEMP6 , ma penso che potrei essere fraintendere la divisione polinomiale, o implementarla in modo errato. Se la mia comprensione è corretta, 1 / 1 mod 2 = 1 , 0 / 1 mod 2 = 0 , ed entrambe le divisioni per zero non sono definite.

Quello che non capisco è come funzionerà la divisione binaria con operandi a 64-bit e 33-bit. Se SRC è 0x00000000 e DEST è 0xFFFFFFFF , TEMP5[63-32] saranno tutti bit impostati, mentre TEMP5[31-0] saranno tutti bit non impostati.

Se dovessi usare i bit da TEMP5 come numeratore, ci sarebbero 30 divisioni per zero in quanto il polinomio 11EDC6F41 è lungo solo 33 bit (e quindi convertirlo in un numero intero senza segno a 64 bit lascia 11EDC6F41 i primi 30 bit), e quindi il denominatore non viene impostato per 30 bit.

Tuttavia, se dovessi usare il polinomio come numeratore, i 32 bit inferiori di TEMP5 sono disinseriti, con conseguente divisione per zero lì, e i primi 30 bit del risultato sarebbero zero, poiché i primi 30 bit del numeratore sarebbero essere zero, come 0 / 1 mod 2 = 0 .

Sto fraintendendo come funziona? Semplicemente manca qualcosa? O Intel ha omesso qualche passo cruciale nella loro documentazione?

La ragione per cui sono andato alla guida per sviluppatori di Intel per quello che sembrava essere l’algoritmo che hanno usato è perché hanno usato un polinomio a 33 bit, e volevo rendere identiche le uscite, cosa che non accadeva quando 1EDC6F41 polinomio a 32 bit 1EDC6F41 ( mostra sotto).

 uint32_t poly = 0x1EDC6F41, sres, crcTable[256], data = 0x00000000; for (n = 0; n < 256; n++) { sres = n; for (k = 0; k > 1) : (sres >> 1); crcTable[n] = sres; } sres = 0xFFFFFFFF; for (n = 0; n > 8); } 

Il codice sopra riportato produce 4138093821 come output e l’opcode crc32 produce 2346497208 utilizzando l’input 0x00000000 .

Scusate se questo è scritto male o incomprensibile in alcuni punti, è piuttosto tardi per me.