diff --git a/FEXCore/Source/Interface/Core/CodeCache.cpp b/FEXCore/Source/Interface/Core/CodeCache.cpp index 229d6e9bf..a9de6c722 100644 --- a/FEXCore/Source/Interface/Core/CodeCache.cpp +++ b/FEXCore/Source/Interface/Core/CodeCache.cpp @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT +#include "Utils/crc32.h" #include "FEXCore/Utils/LogManager.h" #include "FEXCore/Utils/MathUtils.h" #include "FEXCore/Utils/TypeDefines.h" @@ -30,9 +31,6 @@ #include #include -#if defined(ARCHITECTURE_arm64) -#include -#endif namespace FEXCore { @@ -561,26 +559,6 @@ static inline void ApplyPatchableDataRelocation(uint64_t SiteAddress, uint8_t Va CPU::Arm64Emitter::PadType::DOPAD); } -static inline uint32_t crc32(const uint8_t* Ptr, size_t Size) { -#if defined(ARCHITECTURE_arm64) - uint32_t Result {}; -#define do_crc(type, suffix) \ - while (Size >= sizeof(type)) { \ - Result = __crc32##suffix(Result, *reinterpret_cast(Ptr)); \ - Ptr += sizeof(type); \ - Size -= sizeof(type); \ - } - do_crc(uint64_t, d); - do_crc(uint32_t, w); - do_crc(uint16_t, h); - do_crc(uint8_t, b); - return Result; -#else - // Unsupported on non-arm. - return 0; -#endif -}; - static inline void ApplyPatchableRIPLiteralRelocation(uint64_t SiteAddress, uint8_t ValueSize, CPU::Arm64Emitter& Emitter) { Emitter.dc64(SiteAddress + ValueSize + ReadLiveGuestData(SiteAddress, ValueSize)); } @@ -591,7 +569,7 @@ static inline void ApplyPatchableRIPMoveRelocation(uint64_t SiteAddress, uint8_t } static inline void ApplyPatchableCRCMoveRelocation(uint64_t SiteAddress, uint8_t ValueSize, uint8_t RegisterIndex, CPU::Arm64Emitter& Emitter) { - const uint64_t Target = crc32(reinterpret_cast(SiteAddress), ValueSize); + const uint64_t Target = FEXCore::Utils::crc32(reinterpret_cast(SiteAddress), ValueSize); Emitter.LoadConstant(ARMEmitter::Size::i64Bit, ARMEmitter::Register(RegisterIndex), Target, CPU::Arm64Emitter::PadType::DOPAD); } diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index 843ec3275..c250cd3c4 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -30,6 +30,7 @@ $end_info$ #include "Interface/IR/RegisterAllocationData.h" #include "Utils/Allocator.h" #include "Utils/Allocator/HostAllocator.h" +#include "Utils/crc32.h" #include #include "Utils/variable_length_integer.h" @@ -76,9 +77,6 @@ $end_info$ #include #include #include -#if defined(ARCHITECTURE_arm64) -#include -#endif namespace FEXCore::Context { ContextImpl::ContextImpl(const FEXCore::HostFeatures& Features) @@ -639,26 +637,7 @@ ContextImpl::GenerateIR(FEXCore::Core::InternalThreadState* Thread, uint64_t Gue auto ExistingCodePtr = reinterpret_cast(Block.Entry + BlockInstructionsLength); auto InstAddressReg = Thread->OpDispatcher->_EntrypointOffset(GPRSize, InstAddress - GuestRIP); - auto crc32 = [](const uint8_t* Ptr, size_t Size) -> uint32_t { -#if defined(ARCHITECTURE_arm64) - uint32_t Result {}; -#define do_crc(type, suffix) \ - while (Size >= sizeof(type)) { \ - Result = __crc32##suffix(Result, *reinterpret_cast(Ptr)); \ - Ptr += sizeof(type); \ - Size -= sizeof(type); \ - } - do_crc(uint64_t, d); - do_crc(uint32_t, w); - do_crc(uint16_t, h); - do_crc(uint8_t, b); - return Result; -#else - // Unsupported on non-arm. - return 0; -#endif - }; - auto Value = crc32(ExistingCodePtr, DecodedInfo->InstSize); + auto Value = FEXCore::Utils::crc32(ExistingCodePtr, DecodedInfo->InstSize); auto CRC = WantsDiskCachePatching ? Thread->OpDispatcher->_PatchableGuestCRC(IR::OpSize::i64Bit, Value, (int64_t)ExistingCodePtr, DecodedInfo->InstSize) : Thread->OpDispatcher->Constant(Value); diff --git a/FEXCore/Source/Utils/crc32.h b/FEXCore/Source/Utils/crc32.h new file mode 100644 index 000000000..5af0e7cc4 --- /dev/null +++ b/FEXCore/Source/Utils/crc32.h @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +#pragma once +#include +#include +#if defined(ARCHITECTURE_arm64) +#include +#elif defined(ARCHITECTURE_x86_64) +#include +#endif + +namespace FEXCore::Utils { +template +static inline uint32_t crc32(const T* Ptr, size_t Size) { + uint32_t Result {}; +#if defined(ARCHITECTURE_arm64) +#define do_crc(type, suffix) \ + while (Size >= sizeof(type)) { \ + Result = __crc32##suffix(Result, *reinterpret_cast(Ptr)); \ + Ptr += sizeof(type); \ + Size -= sizeof(type); \ + } + do_crc(uint64_t, d); + 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(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 + return Result; +} +} // namespace FEXCore::Utils diff --git a/FEXCore/unittests/APITests/CMakeLists.txt b/FEXCore/unittests/APITests/CMakeLists.txt index 5a204fdae..983d10d5f 100644 --- a/FEXCore/unittests/APITests/CMakeLists.txt +++ b/FEXCore/unittests/APITests/CMakeLists.txt @@ -6,6 +6,7 @@ foreach(TEST ${TESTS}) add_executable(FEXCore_Tests_${TEST_NAME} ${TEST}) target_link_libraries(FEXCore_Tests_${TEST_NAME} PRIVATE ${LIBS}) target_include_directories(FEXCore_Tests_${TEST_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../../Source/") + target_compile_options(FEXCore_Tests_${TEST_NAME} PRIVATE ${FEX_TUNE_COMPILE_FLAGS}) set_target_properties(FEXCore_Tests_${TEST_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/FEXCore_Tests") catch_discover_tests(FEXCore_Tests_${TEST_NAME} TEST_SUFFIX ".${TEST_NAME}.FEXCore_Tests") endforeach() diff --git a/FEXCore/unittests/APITests/crc32.cpp b/FEXCore/unittests/APITests/crc32.cpp new file mode 100644 index 000000000..eadb6adc0 --- /dev/null +++ b/FEXCore/unittests/APITests/crc32.cpp @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +#include + +#include "Utils/crc32.h" + +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 +}