mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 13:00:15 +02:00
Merge pull request #5961 from Sonicadvance1/248
FEXCore/Utils: Make crc32 match between architectures
This commit is contained in:
2 files changed
+32
-24
No files matched your search
@@ -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,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
|
||||
}
|
||||
Reference in new issue
Block a user