/* Constants of one CRC-32 polynomial, in bit-reflected form.
See the use sites in rv_crc32_impl() for what each field is. */ struct rv_crc32_tab {
alignas(16) uint32_t fold[4]; /* x^(64*i+64) mod P for i=1..4 */
uint64_t const0; /* x^64 mod P */
uint64_t const1; /* x^96 mod P */
uint64_t quo; /* floor(x^64 / P) */
uint64_t poly; /* P(x) true LE full */
uint32_t bitwise_poly; /* reflected polynomial, small-chunk path */
};
// Bitwise CRC fallback for small chunks staticinline uint32_t rv_crc32_bitwise(uint32_t crc, const uint8_t* buf,
size_t len, uint32_t poly) {
uint32_t c = crc; for (size_t i = 0; i < len; ++i) {
c ^= buf[i]; for (int k = 0; k < 8; ++k) {
c = (c >> 1) ^ ((c & 1) ? poly : 0);
}
} return c;
}
// Fold the 128-bit CRC state (lo:hi) with fold constants k0/k1, then XOR in // the value (v0:v1). The latter is either the next chunk of input data or // another folded state to be combined. staticinlinevoid rv_fold_pair(uint64_t* lo, uint64_t* hi,
uint64_t k0, uint64_t k1,
uint64_t v0, uint64_t v1) {
uint64_t l = rv_clmul(*lo, k0) ^ rv_clmul(*hi, k1);
uint64_t h = rv_clmulh(*lo, k0) ^ rv_clmulh(*hi, k1);
*lo = l ^ v0;
*hi = h ^ v1;
}
// Hardware-accelerated CRC-32 using RISC-V Zbc carry-less multiplication. // Processes data in 64-byte chunks with 128-bit folding, then Barrett reduces. static uint32_t rv_crc32_impl(uint32_t crc, constchar* buf, size_t len, const rv_crc32_tab &tab) { // Convert external CRC to internal register state
crc ^= 0xFFFFFFFF;
const uint8_t* p = reinterpret_cast<const uint8_t*>(buf);
size_t n = len;
// Small data: use bitwise fallback if (n < 64) { return rv_crc32_bitwise(crc, p, n, tab.bitwise_poly) ^ 0xFFFFFFFF;
}
// Align to 16-byte boundary if (uintptr_t mis= reinterpret_cast<uintptr_t>(p) & 0xF) {
size_t pre = 16 - mis; if (pre > n) pre = n;
crc = rv_crc32_bitwise(crc, p, pre, tab.bitwise_poly);
p += pre;
n -= pre; if (n < 64) { return rv_crc32_bitwise(crc, p, n, tab.bitwise_poly) ^ 0xFFFFFFFF;
}
}
// Load first 64 bytes and XOR CRC into the first 8 bytes. // p is 16-byte aligned here, hence memcpy_aligned<8> is safe.
uint64_t x0, x1, y0, y1, z0, z1, w0, w1;
memcpy_aligned<8>(&x0, p + 0, 8);
memcpy_aligned<8>(&x1, p + 8, 8);
memcpy_aligned<8>(&y0, p + 16, 8);
memcpy_aligned<8>(&y1, p + 24, 8);
memcpy_aligned<8>(&z0, p + 32, 8);
memcpy_aligned<8>(&z1, p + 40, 8);
memcpy_aligned<8>(&w0, p + 48, 8);
memcpy_aligned<8>(&w1, p + 56, 8);
uint32_t c = (uint32_t)((t4 >> 32) & RV_CRC32_MASK32); // Handle remaining bytes if (n) {
c = rv_crc32_bitwise(c, p, n, tab.bitwise_poly);
} // Convert internal register state to external CRC return c ^ 0xFFFFFFFF;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.