Merge pull request #5961 from Sonicadvance1/248

FEXCore/Utils: Make crc32 match between architectures
This commit is contained in:
LC authored and GitHub committed 2026-09-15 18:59:52 -04:00
commit 4bc4d785af
2 files changed
+32 -24

No files matched your search

+32 -19
View File
@@ -4,8 +4,6 @@
#include <cstdint>
#if defined(ARCHITECTURE_arm64)
#include <arm_acle.h>
#elif defined(ARCHITECTURE_x86_64)
#include <nmmintrin.h>
#endif
namespace FEXCore::Utils {
@@ -23,24 +21,39 @@ static inline uint32_t crc32(const T* Ptr, size_t Size) {
do_crc(uint32_t, w);
do_crc(uint16_t, h);
do_crc(uint8_t, b);
#elif defined(ARCHITECTURE_x86_64)
#define do_crc(type, intrinsic) \
while (Size >= sizeof(type)) { \
Result = intrinsic(Result, *reinterpret_cast<const type*>(Ptr)); \
Ptr += sizeof(type); \
Size -= sizeof(type); \
}
do_crc(uint64_t, _mm_crc32_u64);
do_crc(uint32_t, _mm_crc32_u32);
do_crc(uint16_t, _mm_crc32_u16);
do_crc(uint8_t, _mm_crc32_u8);
#else
// Unsupported on non-arm.
return 0;
#endif
#undef do_crc
#else
// Emulate arm64 crc32.
// This is basically just the pseudo-code for crc32b.
// Doesn't need to be fast, just needs to match.
auto reverse_bits = [](auto bits) {
decltype(bits) Result {};
for (size_t i = 0; i < (sizeof(decltype(bits)) * 8); ++i) {
Result = (Result << 1) | ((bits >> i) & 1);
}
return Result;
};
auto Poly32Mod2 = [](uint64_t data) -> uint32_t {
constexpr static size_t bits = 40;
constexpr static uint64_t poly = 0x04C11DB7U;
for (size_t i = (bits - 1); i >= 32; --i) {
if (((data >> i) & 1) != 0) {
const uint64_t poly_shift = poly << (i - 32);
const uint64_t data_mask = (1ULL << i) - 1;
data = (data & data_mask) ^ poly_shift;
}
}
return data;
};
for (size_t i = 0; i < Size; ++i) {
uint64_t TempAcc = static_cast<uint64_t>(reverse_bits(Result)) << 8;
uint64_t TempVal = static_cast<uint64_t>(reverse_bits(reinterpret_cast<const uint8_t*>(Ptr)[i])) << 32;
Result = reverse_bits(Poly32Mod2(TempAcc ^ TempVal));
}
#endif
return Result;
}
} // namespace FEXCore::Utils
-5
View File
@@ -5,10 +5,5 @@
TEST_CASE("Simple") {
uint32_t data = 0x41424344U;
// Arm and x86 use different polynomials by default.
#if defined(ARCHITECTURE_arm64)
CHECK(FEXCore::Utils::crc32(&data, sizeof(data)) == 0xa53ea072);
#elif defined(ARCHITECTURE_x86_64)
CHECK(FEXCore::Utils::crc32(&data, sizeof(data)) == 0x968d46eb);
#endif
}