diff --git a/include/dynarmic/A32/config.h b/include/dynarmic/A32/config.h index da17ce82..a64cf737 100644 --- a/include/dynarmic/A32/config.h +++ b/include/dynarmic/A32/config.h @@ -197,6 +197,13 @@ struct UserConfig { /// NOTE: Calling Jit::SetCpsr with CPSR.E=1 while this option is enabled may result /// in unusual behavior. bool always_little_endian = false; + + // Minimum size is about 8MiB. Maximum size is about 2GiB. Maximum size is limited by + // the maximum length of a x64 jump. + size_t code_cache_size = 256 * 1024 * 1024; // bytes + // Determines the relative size of the near and far code caches. Must be smaller than + // code_cache_size. + size_t far_code_offset = 200 * 1024 * 1024; // bytes }; } // namespace A32 diff --git a/include/dynarmic/A64/config.h b/include/dynarmic/A64/config.h index 9846f70a..7249c6fa 100644 --- a/include/dynarmic/A64/config.h +++ b/include/dynarmic/A64/config.h @@ -245,6 +245,13 @@ struct UserConfig { // Determines whether AddTicks and GetTicksRemaining are called. // If false, execution will continue until soon after Jit::HaltExecution is called. // bool enable_ticks = true; // TODO + + // Minimum size is about 8MiB. Maximum size is about 2GiB. Maximum size is limited by + // the maximum length of a x64 jump. + size_t code_cache_size = 256 * 1024 * 1024; // bytes + // Determines the relative size of the near and far code caches. Must be smaller than + // code_cache_size. + size_t far_code_offset = 200 * 1024 * 1024; // bytes }; } // namespace A64 diff --git a/src/backend/x64/a32_interface.cpp b/src/backend/x64/a32_interface.cpp index 85f934c8..09d9d6c7 100644 --- a/src/backend/x64/a32_interface.cpp +++ b/src/backend/x64/a32_interface.cpp @@ -53,7 +53,7 @@ static std::function GenRCP(const A32::UserConfig& conf) { struct Jit::Impl { Impl(Jit* jit, A32::UserConfig conf) - : block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, GenRCP(conf)) + : block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, conf.code_cache_size, conf.far_code_offset, GenRCP(conf)) , emitter(block_of_code, conf, jit) , conf(std::move(conf)) , jit_interface(jit) diff --git a/src/backend/x64/a64_interface.cpp b/src/backend/x64/a64_interface.cpp index 646b426a..acde3f34 100644 --- a/src/backend/x64/a64_interface.cpp +++ b/src/backend/x64/a64_interface.cpp @@ -45,7 +45,7 @@ struct Jit::Impl final { public: Impl(Jit* jit, UserConfig conf) : conf(conf) - , block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, GenRCP(conf)) + , block_of_code(GenRunCodeCallbacks(conf.callbacks, &GetCurrentBlockThunk, this), JitStateInfo{jit_state}, conf.code_cache_size, conf.far_code_offset, GenRCP(conf)) , emitter(block_of_code, conf, jit) { ASSERT(conf.page_table_address_space_bits >= 12 && conf.page_table_address_space_bits <= 64); diff --git a/src/backend/x64/block_of_code.cpp b/src/backend/x64/block_of_code.cpp index 752ff7cc..8b96b8af 100644 --- a/src/backend/x64/block_of_code.cpp +++ b/src/backend/x64/block_of_code.cpp @@ -44,8 +44,6 @@ const std::array BlockOfCode::ABI_PARAMS = {BlockOfCode::ABI_PA namespace { -constexpr size_t TOTAL_CODE_SIZE = 256 * 1024 * 1024; -constexpr size_t FAR_CODE_OFFSET = 200 * 1024 * 1024; constexpr size_t CONSTANT_POOL_SIZE = 2 * 1024 * 1024; class CustomXbyakAllocator : public Xbyak::Allocator { @@ -75,10 +73,11 @@ void ProtectMemory(const void* base, size_t size, bool is_executable) { } // anonymous namespace -BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, std::function rcp) - : Xbyak::CodeGenerator(TOTAL_CODE_SIZE, nullptr, &s_allocator) +BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, size_t far_code_offset, std::function rcp) + : Xbyak::CodeGenerator(total_code_size, nullptr, &s_allocator) , cb(std::move(cb)) , jsi(jsi) + , far_code_offset(far_code_offset) , constant_pool(*this, CONSTANT_POOL_SIZE) { EnableWriting(); @@ -88,7 +87,7 @@ BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, std::function(near_code_ptr) - getCode(); - far_code_offset = getCurr() - getCode(); - } else { - near_code_offset = getCurr() - getCode(); - far_code_offset = static_cast(far_code_ptr) - getCode(); - } - if (far_code_offset > TOTAL_CODE_SIZE) + const u8* current_near_ptr = in_far_code ? reinterpret_cast(near_code_ptr) : getCode(); + const u8* current_far_ptr = in_far_code ? getCode() : reinterpret_cast(far_code_ptr); + if (current_near_ptr >= far_code_begin) return 0; - if (near_code_offset > FAR_CODE_OFFSET) + if (current_far_ptr >= &top_[maxSize_]) return 0; - return std::min(TOTAL_CODE_SIZE - far_code_offset, FAR_CODE_OFFSET - near_code_offset); + return std::min(current_near_ptr - reinterpret_cast(far_code_begin), current_far_ptr - &top_[maxSize_]); } void BlockOfCode::RunCode(void* jit_state, CodePtr code_ptr) const { diff --git a/src/backend/x64/block_of_code.h b/src/backend/x64/block_of_code.h index 23ed1683..596c31bd 100644 --- a/src/backend/x64/block_of_code.h +++ b/src/backend/x64/block_of_code.h @@ -31,7 +31,7 @@ struct RunCodeCallbacks { class BlockOfCode final : public Xbyak::CodeGenerator { public: - BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, std::function rcp); + BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, size_t far_code_offset, std::function rcp); BlockOfCode(const BlockOfCode&) = delete; /// Call when external emitters have finished emitting their preludes. @@ -164,10 +164,11 @@ public: private: RunCodeCallbacks cb; JitStateInfo jsi; + size_t far_code_offset; bool prelude_complete = false; - CodePtr near_code_begin; - CodePtr far_code_begin; + CodePtr near_code_begin = nullptr; + CodePtr far_code_begin = nullptr; ConstantPool constant_pool;