From a3c81745b17e05b019d0ac99d3dc93b97ea80370 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 25 Jan 2022 13:15:45 -0500 Subject: video_core/macro_hle: Move impl class into cpp file Given it's intended to be an internal implementation class, we can move it into the cpp file to ensure that. This also lets us move some header dependencies into the cpp file as well. --- src/video_core/macro/macro_hle.cpp | 30 +++++++++++++++++++----------- src/video_core/macro/macro_hle.h | 16 ---------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 70ac7c620..3f743ce55 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp @@ -5,12 +5,15 @@ #include #include #include "video_core/engines/maxwell_3d.h" +#include "video_core/macro/macro.h" #include "video_core/macro/macro_hle.h" #include "video_core/rasterizer_interface.h" namespace Tegra { - namespace { + +using HLEFunction = void (*)(Engines::Maxwell3D& maxwell3d, const std::vector& parameters); + // HLE'd functions void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, const std::vector& parameters) { const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B); @@ -77,7 +80,6 @@ void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, const std::vector& maxwell3d.CallMethodFromMME(0x8e5, 0x0); maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; } -} // Anonymous namespace constexpr std::array, 3> hle_funcs{{ {0x771BB18C62444DA0, &HLE_771BB18C62444DA0}, @@ -85,6 +87,21 @@ constexpr std::array, 3> hle_funcs{{ {0x0217920100488FF7, &HLE_0217920100488FF7}, }}; +class HLEMacroImpl final : public CachedMacro { +public: + explicit HLEMacroImpl(Engines::Maxwell3D& maxwell3d_, HLEFunction func_) + : maxwell3d{maxwell3d_}, func{func_} {} + + void Execute(const std::vector& parameters, u32 method) override { + func(maxwell3d, parameters); + } + +private: + Engines::Maxwell3D& maxwell3d; + HLEFunction func; +}; +} // Anonymous namespace + HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {} HLEMacro::~HLEMacro() = default; @@ -97,13 +114,4 @@ std::optional> HLEMacro::GetHLEProgram(u64 hash) co return std::make_unique(maxwell3d, it->second); } -HLEMacroImpl::~HLEMacroImpl() = default; - -HLEMacroImpl::HLEMacroImpl(Engines::Maxwell3D& maxwell3d_, HLEFunction func_) - : maxwell3d{maxwell3d_}, func{func_} {} - -void HLEMacroImpl::Execute(const std::vector& parameters, u32 method) { - func(maxwell3d, parameters); -} - } // namespace Tegra diff --git a/src/video_core/macro/macro_hle.h b/src/video_core/macro/macro_hle.h index cb3bd1600..c0a12e793 100644 --- a/src/video_core/macro/macro_hle.h +++ b/src/video_core/macro/macro_hle.h @@ -6,9 +6,7 @@ #include #include -#include #include "common/common_types.h" -#include "video_core/macro/macro.h" namespace Tegra { @@ -16,8 +14,6 @@ namespace Engines { class Maxwell3D; } -using HLEFunction = void (*)(Engines::Maxwell3D& maxwell3d, const std::vector& parameters); - class HLEMacro { public: explicit HLEMacro(Engines::Maxwell3D& maxwell3d_); @@ -29,16 +25,4 @@ private: Engines::Maxwell3D& maxwell3d; }; -class HLEMacroImpl : public CachedMacro { -public: - explicit HLEMacroImpl(Engines::Maxwell3D& maxwell3d, HLEFunction func); - ~HLEMacroImpl(); - - void Execute(const std::vector& parameters, u32 method) override; - -private: - Engines::Maxwell3D& maxwell3d; - HLEFunction func; -}; - } // namespace Tegra -- cgit v1.2.3 From 6b873b72ae5dcaad9a234d3f5375f309578e28fa Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 25 Jan 2022 13:24:53 -0500 Subject: video_core/macro_jit_x64: Move impl class into cpp file Keeps the implementation internalized and also reduces API-facing header dependencies. Notably, this fully internalizes all of the xbyak externals. --- src/video_core/macro/macro_jit_x64.cpp | 102 +++++++++++++++++++++++++++------ src/video_core/macro/macro_jit_x64.h | 71 ----------------------- 2 files changed, 86 insertions(+), 87 deletions(-) diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp index c6b2b2109..1934039c0 100644 --- a/src/video_core/macro/macro_jit_x64.cpp +++ b/src/video_core/macro/macro_jit_x64.cpp @@ -2,9 +2,17 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include +#include + +#include + #include "common/assert.h" +#include "common/bit_field.h" #include "common/logging/log.h" #include "common/microprofile.h" +#include "common/x64/xbyak_abi.h" #include "common/x64/xbyak_util.h" #include "video_core/engines/maxwell_3d.h" #include "video_core/macro/macro_interpreter.h" @@ -14,13 +22,14 @@ MICROPROFILE_DEFINE(MacroJitCompile, "GPU", "Compile macro JIT", MP_RGB(173, 255 MICROPROFILE_DEFINE(MacroJitExecute, "GPU", "Execute macro JIT", MP_RGB(255, 255, 0)); namespace Tegra { +namespace { constexpr Xbyak::Reg64 STATE = Xbyak::util::rbx; constexpr Xbyak::Reg32 RESULT = Xbyak::util::ebp; constexpr Xbyak::Reg64 PARAMETERS = Xbyak::util::r12; constexpr Xbyak::Reg32 METHOD_ADDRESS = Xbyak::util::r14d; constexpr Xbyak::Reg64 BRANCH_HOLDER = Xbyak::util::r15; -static const std::bitset<32> PERSISTENT_REGISTERS = Common::X64::BuildRegSet({ +const std::bitset<32> PERSISTENT_REGISTERS = Common::X64::BuildRegSet({ STATE, RESULT, PARAMETERS, @@ -28,19 +37,73 @@ static const std::bitset<32> PERSISTENT_REGISTERS = Common::X64::BuildRegSet({ BRANCH_HOLDER, }); -MacroJITx64::MacroJITx64(Engines::Maxwell3D& maxwell3d_) - : MacroEngine{maxwell3d_}, maxwell3d{maxwell3d_} {} +// Arbitrarily chosen based on current booting games. +constexpr size_t MAX_CODE_SIZE = 0x10000; -std::unique_ptr MacroJITx64::Compile(const std::vector& code) { - return std::make_unique(maxwell3d, code); -} +class MacroJITx64Impl final : public Xbyak::CodeGenerator, public CachedMacro { +public: + explicit MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_) + : CodeGenerator{MAX_CODE_SIZE}, code{code_}, maxwell3d{maxwell3d_} { + Compile(); + } -MacroJITx64Impl::MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_) - : CodeGenerator{MAX_CODE_SIZE}, code{code_}, maxwell3d{maxwell3d_} { - Compile(); -} + void Execute(const std::vector& parameters, u32 method) override; + + void Compile_ALU(Macro::Opcode opcode); + void Compile_AddImmediate(Macro::Opcode opcode); + void Compile_ExtractInsert(Macro::Opcode opcode); + void Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode); + void Compile_ExtractShiftLeftRegister(Macro::Opcode opcode); + void Compile_Read(Macro::Opcode opcode); + void Compile_Branch(Macro::Opcode opcode); + +private: + void Optimizer_ScanFlags(); + + void Compile(); + bool Compile_NextInstruction(); + + Xbyak::Reg32 Compile_FetchParameter(); + Xbyak::Reg32 Compile_GetRegister(u32 index, Xbyak::Reg32 dst); + + void Compile_ProcessResult(Macro::ResultOperation operation, u32 reg); + void Compile_Send(Xbyak::Reg32 value); -MacroJITx64Impl::~MacroJITx64Impl() = default; + Macro::Opcode GetOpCode() const; + std::bitset<32> PersistentCallerSavedRegs() const; + + struct JITState { + Engines::Maxwell3D* maxwell3d{}; + std::array registers{}; + u32 carry_flag{}; + }; + static_assert(offsetof(JITState, maxwell3d) == 0, "Maxwell3D is not at 0x0"); + using ProgramType = void (*)(JITState*, const u32*); + + struct OptimizerState { + bool can_skip_carry{}; + bool has_delayed_pc{}; + bool zero_reg_skip{}; + bool skip_dummy_addimmediate{}; + bool optimize_for_method_move{}; + bool enable_asserts{}; + }; + OptimizerState optimizer{}; + + std::optional next_opcode{}; + ProgramType program{nullptr}; + + std::array labels; + std::array delay_skip; + Xbyak::Label end_of_code{}; + + bool is_delay_slot{}; + u32 pc{}; + std::optional delayed_pc; + + const std::vector& code; + Engines::Maxwell3D& maxwell3d; +}; void MacroJITx64Impl::Execute(const std::vector& parameters, u32 method) { MICROPROFILE_SCOPE(MacroJitExecute); @@ -307,11 +370,11 @@ void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) { Compile_ProcessResult(opcode.result_operation, opcode.dst); } -static void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { +void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { maxwell3d->CallMethodFromMME(method_address.address, value); } -void Tegra::MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { +void MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { Common::X64::ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); mov(Common::X64::ABI_PARAM1, qword[STATE]); mov(Common::X64::ABI_PARAM2, METHOD_ADDRESS); @@ -338,7 +401,7 @@ void Tegra::MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { L(dont_process); } -void Tegra::MacroJITx64Impl::Compile_Branch(Macro::Opcode opcode) { +void MacroJITx64Impl::Compile_Branch(Macro::Opcode opcode) { ASSERT_MSG(!is_delay_slot, "Executing a branch in a delay slot is not valid"); const s32 jump_address = static_cast(pc) + static_cast(opcode.GetBranchTarget() / sizeof(s32)); @@ -392,7 +455,7 @@ void Tegra::MacroJITx64Impl::Compile_Branch(Macro::Opcode opcode) { L(end); } -void Tegra::MacroJITx64Impl::Optimizer_ScanFlags() { +void MacroJITx64Impl::Optimizer_ScanFlags() { optimizer.can_skip_carry = true; optimizer.has_delayed_pc = false; for (auto raw_op : code) { @@ -534,7 +597,7 @@ bool MacroJITx64Impl::Compile_NextInstruction() { return true; } -Xbyak::Reg32 Tegra::MacroJITx64Impl::Compile_FetchParameter() { +Xbyak::Reg32 MacroJITx64Impl::Compile_FetchParameter() { mov(eax, dword[PARAMETERS]); add(PARAMETERS, sizeof(u32)); return eax; @@ -615,5 +678,12 @@ Macro::Opcode MacroJITx64Impl::GetOpCode() const { std::bitset<32> MacroJITx64Impl::PersistentCallerSavedRegs() const { return PERSISTENT_REGISTERS & Common::X64::ABI_ALL_CALLER_SAVED; } +} // Anonymous namespace +MacroJITx64::MacroJITx64(Engines::Maxwell3D& maxwell3d_) + : MacroEngine{maxwell3d_}, maxwell3d{maxwell3d_} {} + +std::unique_ptr MacroJITx64::Compile(const std::vector& code) { + return std::make_unique(maxwell3d, code); +} } // namespace Tegra diff --git a/src/video_core/macro/macro_jit_x64.h b/src/video_core/macro/macro_jit_x64.h index d03d480b4..773b037ae 100644 --- a/src/video_core/macro/macro_jit_x64.h +++ b/src/video_core/macro/macro_jit_x64.h @@ -4,12 +4,7 @@ #pragma once -#include -#include -#include -#include "common/bit_field.h" #include "common/common_types.h" -#include "common/x64/xbyak_abi.h" #include "video_core/macro/macro.h" namespace Tegra { @@ -18,9 +13,6 @@ namespace Engines { class Maxwell3D; } -/// MAX_CODE_SIZE is arbitrarily chosen based on current booting games -constexpr size_t MAX_CODE_SIZE = 0x10000; - class MacroJITx64 final : public MacroEngine { public: explicit MacroJITx64(Engines::Maxwell3D& maxwell3d_); @@ -32,67 +24,4 @@ private: Engines::Maxwell3D& maxwell3d; }; -class MacroJITx64Impl : public Xbyak::CodeGenerator, public CachedMacro { -public: - explicit MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_); - ~MacroJITx64Impl(); - - void Execute(const std::vector& parameters, u32 method) override; - - void Compile_ALU(Macro::Opcode opcode); - void Compile_AddImmediate(Macro::Opcode opcode); - void Compile_ExtractInsert(Macro::Opcode opcode); - void Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode); - void Compile_ExtractShiftLeftRegister(Macro::Opcode opcode); - void Compile_Read(Macro::Opcode opcode); - void Compile_Branch(Macro::Opcode opcode); - -private: - void Optimizer_ScanFlags(); - - void Compile(); - bool Compile_NextInstruction(); - - Xbyak::Reg32 Compile_FetchParameter(); - Xbyak::Reg32 Compile_GetRegister(u32 index, Xbyak::Reg32 dst); - - void Compile_ProcessResult(Macro::ResultOperation operation, u32 reg); - void Compile_Send(Xbyak::Reg32 value); - - Macro::Opcode GetOpCode() const; - std::bitset<32> PersistentCallerSavedRegs() const; - - struct JITState { - Engines::Maxwell3D* maxwell3d{}; - std::array registers{}; - u32 carry_flag{}; - }; - static_assert(offsetof(JITState, maxwell3d) == 0, "Maxwell3D is not at 0x0"); - using ProgramType = void (*)(JITState*, const u32*); - - struct OptimizerState { - bool can_skip_carry{}; - bool has_delayed_pc{}; - bool zero_reg_skip{}; - bool skip_dummy_addimmediate{}; - bool optimize_for_method_move{}; - bool enable_asserts{}; - }; - OptimizerState optimizer{}; - - std::optional next_opcode{}; - ProgramType program{nullptr}; - - std::array labels; - std::array delay_skip; - Xbyak::Label end_of_code{}; - - bool is_delay_slot{}; - u32 pc{}; - std::optional delayed_pc; - - const std::vector& code; - Engines::Maxwell3D& maxwell3d; -}; - } // namespace Tegra -- cgit v1.2.3 From f11eefed5619319629b399aec07880cc12c760a3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 25 Jan 2022 13:30:51 -0500 Subject: video_core/macro_jit_x64: Decouple PersistentCallerSavedRegs() from impl This doesn't depend on class state and can just be a regular function. --- src/video_core/macro/macro_jit_x64.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp index 1934039c0..4b1b8c157 100644 --- a/src/video_core/macro/macro_jit_x64.cpp +++ b/src/video_core/macro/macro_jit_x64.cpp @@ -40,6 +40,10 @@ const std::bitset<32> PERSISTENT_REGISTERS = Common::X64::BuildRegSet({ // Arbitrarily chosen based on current booting games. constexpr size_t MAX_CODE_SIZE = 0x10000; +std::bitset<32> PersistentCallerSavedRegs() { + return PERSISTENT_REGISTERS & Common::X64::ABI_ALL_CALLER_SAVED; +} + class MacroJITx64Impl final : public Xbyak::CodeGenerator, public CachedMacro { public: explicit MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_) @@ -70,7 +74,6 @@ private: void Compile_Send(Xbyak::Reg32 value); Macro::Opcode GetOpCode() const; - std::bitset<32> PersistentCallerSavedRegs() const; struct JITState { Engines::Maxwell3D* maxwell3d{}; @@ -674,10 +677,6 @@ Macro::Opcode MacroJITx64Impl::GetOpCode() const { ASSERT(pc < code.size()); return {code[pc]}; } - -std::bitset<32> MacroJITx64Impl::PersistentCallerSavedRegs() const { - return PERSISTENT_REGISTERS & Common::X64::ABI_ALL_CALLER_SAVED; -} } // Anonymous namespace MacroJITx64::MacroJITx64(Engines::Maxwell3D& maxwell3d_) -- cgit v1.2.3 From 74f80299b0f6ce445413221e9be5fc2cac5c52f2 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 25 Jan 2022 13:33:06 -0500 Subject: video_core/macro_jit_x64: Remove unused impl class member Reduces the size of the impl class a tiny bit. --- src/video_core/macro/macro_jit_x64.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp index 4b1b8c157..924c9fe5c 100644 --- a/src/video_core/macro/macro_jit_x64.cpp +++ b/src/video_core/macro/macro_jit_x64.cpp @@ -102,7 +102,6 @@ private: bool is_delay_slot{}; u32 pc{}; - std::optional delayed_pc; const std::vector& code; Engines::Maxwell3D& maxwell3d; -- cgit v1.2.3 From a05d9405b9192b0e9402eba2305d1a35aac44a74 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 25 Jan 2022 13:41:35 -0500 Subject: video_core/macro: Remove unused parameter from Execute() Simplifies the function interface. --- src/video_core/engines/maxwell_3d.cpp | 2 +- src/video_core/macro/macro.cpp | 3 +-- src/video_core/macro/macro.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index b18b8a02a..c38ebd670 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -240,7 +240,7 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector& parameters) ((method - MacroRegistersStart) >> 1) % static_cast(macro_positions.size()); // Execute the current macro. - macro_engine->Execute(*this, macro_positions[entry], parameters); + macro_engine->Execute(macro_positions[entry], parameters); if (mme_draw.current_mode != MMEDrawMode::Undefined) { FlushMMEInlineDraw(); } diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp index d7fabe605..0870a7687 100644 --- a/src/video_core/macro/macro.cpp +++ b/src/video_core/macro/macro.cpp @@ -24,8 +24,7 @@ void MacroEngine::AddCode(u32 method, u32 data) { uploaded_macro_code[method].push_back(data); } -void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method, - const std::vector& parameters) { +void MacroEngine::Execute(u32 method, const std::vector& parameters) { auto compiled_macro = macro_cache.find(method); if (compiled_macro != macro_cache.end()) { const auto& cache_info = compiled_macro->second; diff --git a/src/video_core/macro/macro.h b/src/video_core/macro/macro.h index 31ee3440a..7aaa49286 100644 --- a/src/video_core/macro/macro.h +++ b/src/video_core/macro/macro.h @@ -119,7 +119,7 @@ public: void AddCode(u32 method, u32 data); // Compiles the macro if its not in the cache, and executes the compiled macro - void Execute(Engines::Maxwell3D& maxwell3d, u32 method, const std::vector& parameters); + void Execute(u32 method, const std::vector& parameters); protected: virtual std::unique_ptr Compile(const std::vector& code) = 0; -- cgit v1.2.3 From cfd9f7d25b4c1aea49b4dc017990f12142b8302b Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 25 Jan 2022 13:50:10 -0500 Subject: video_core/macro_hle: Return unique_ptr directly from GetHLEProgram() Same behavior, but less code and header dependencies. --- src/video_core/macro/macro.cpp | 5 ++--- src/video_core/macro/macro_hle.cpp | 4 ++-- src/video_core/macro/macro_hle.h | 5 +++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp index 0870a7687..0ae78a9e5 100644 --- a/src/video_core/macro/macro.cpp +++ b/src/video_core/macro/macro.cpp @@ -65,10 +65,9 @@ void MacroEngine::Execute(u32 method, const std::vector& parameters) { cache_info.lle_program = Compile(code); } - auto hle_program = hle_macros->GetHLEProgram(cache_info.hash); - if (hle_program.has_value()) { + if (auto hle_program = hle_macros->GetHLEProgram(cache_info.hash)) { cache_info.has_hle_program = true; - cache_info.hle_program = std::move(hle_program.value()); + cache_info.hle_program = std::move(hle_program); cache_info.hle_program->Execute(parameters, method); } else { cache_info.lle_program->Execute(parameters, method); diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 3f743ce55..900ad23c9 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp @@ -105,11 +105,11 @@ private: HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d_) : maxwell3d{maxwell3d_} {} HLEMacro::~HLEMacro() = default; -std::optional> HLEMacro::GetHLEProgram(u64 hash) const { +std::unique_ptr HLEMacro::GetHLEProgram(u64 hash) const { const auto it = std::find_if(hle_funcs.cbegin(), hle_funcs.cend(), [hash](const auto& pair) { return pair.first == hash; }); if (it == hle_funcs.end()) { - return std::nullopt; + return nullptr; } return std::make_unique(maxwell3d, it->second); } diff --git a/src/video_core/macro/macro_hle.h b/src/video_core/macro/macro_hle.h index c0a12e793..b86ba84a1 100644 --- a/src/video_core/macro/macro_hle.h +++ b/src/video_core/macro/macro_hle.h @@ -5,7 +5,6 @@ #pragma once #include -#include #include "common/common_types.h" namespace Tegra { @@ -19,7 +18,9 @@ public: explicit HLEMacro(Engines::Maxwell3D& maxwell3d_); ~HLEMacro(); - std::optional> GetHLEProgram(u64 hash) const; + // Allocates and returns a cached macro if the hash matches a known function. + // Returns nullptr otherwise. + [[nodiscard]] std::unique_ptr GetHLEProgram(u64 hash) const; private: Engines::Maxwell3D& maxwell3d; -- cgit v1.2.3 From 81d1a1133dad918cabc9f50948b6535b4a1e8893 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 25 Jan 2022 14:03:46 -0500 Subject: video_core/macro_interpreter: Move impl class to the cpp file Keeps the implementation hidden from the intended API and lessens the header dependencies on the interpreter's header. --- src/video_core/macro/macro_interpreter.cpp | 92 +++++++++++++++++++++++++++--- src/video_core/macro/macro_interpreter.h | 78 +------------------------ 2 files changed, 86 insertions(+), 84 deletions(-) diff --git a/src/video_core/macro/macro_interpreter.cpp b/src/video_core/macro/macro_interpreter.cpp index 8da26fd59..fba755448 100644 --- a/src/video_core/macro/macro_interpreter.cpp +++ b/src/video_core/macro/macro_interpreter.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include + #include "common/assert.h" #include "common/logging/log.h" #include "common/microprofile.h" @@ -11,16 +14,81 @@ MICROPROFILE_DEFINE(MacroInterp, "GPU", "Execute macro interpreter", MP_RGB(128, 128, 192)); namespace Tegra { -MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d_) - : MacroEngine{maxwell3d_}, maxwell3d{maxwell3d_} {} +namespace { +class MacroInterpreterImpl final : public CachedMacro { +public: + explicit MacroInterpreterImpl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_) + : maxwell3d{maxwell3d_}, code{code_} {} -std::unique_ptr MacroInterpreter::Compile(const std::vector& code) { - return std::make_unique(maxwell3d, code); -} + void Execute(const std::vector& params, u32 method) override; + +private: + /// Resets the execution engine state, zeroing registers, etc. + void Reset(); + + /** + * Executes a single macro instruction located at the current program counter. Returns whether + * the interpreter should keep running. + * + * @param is_delay_slot Whether the current step is being executed due to a delay slot in a + * previous instruction. + */ + bool Step(bool is_delay_slot); + + /// Calculates the result of an ALU operation. src_a OP src_b; + u32 GetALUResult(Macro::ALUOperation operation, u32 src_a, u32 src_b); + + /// Performs the result operation on the input result and stores it in the specified register + /// (if necessary). + void ProcessResult(Macro::ResultOperation operation, u32 reg, u32 result); + + /// Evaluates the branch condition and returns whether the branch should be taken or not. + bool EvaluateBranchCondition(Macro::BranchCondition cond, u32 value) const; + + /// Reads an opcode at the current program counter location. + Macro::Opcode GetOpcode() const; + + /// Returns the specified register's value. Register 0 is hardcoded to always return 0. + u32 GetRegister(u32 register_id) const; + + /// Sets the register to the input value. + void SetRegister(u32 register_id, u32 value); + + /// Sets the method address to use for the next Send instruction. + void SetMethodAddress(u32 address); -MacroInterpreterImpl::MacroInterpreterImpl(Engines::Maxwell3D& maxwell3d_, - const std::vector& code_) - : maxwell3d{maxwell3d_}, code{code_} {} + /// Calls a GPU Engine method with the input parameter. + void Send(u32 value); + + /// Reads a GPU register located at the method address. + u32 Read(u32 method) const; + + /// Returns the next parameter in the parameter queue. + u32 FetchParameter(); + + Engines::Maxwell3D& maxwell3d; + + /// Current program counter + u32 pc{}; + /// Program counter to execute at after the delay slot is executed. + std::optional delayed_pc; + + /// General purpose macro registers. + std::array registers = {}; + + /// Method address to use for the next Send instruction. + Macro::MethodAddress method_address = {}; + + /// Input parameters of the current macro. + std::unique_ptr parameters; + std::size_t num_parameters = 0; + std::size_t parameters_capacity = 0; + /// Index of the next parameter that will be fetched by the 'parm' instruction. + u32 next_parameter_index = 0; + + bool carry_flag = false; + const std::vector& code; +}; void MacroInterpreterImpl::Execute(const std::vector& params, u32 method) { MICROPROFILE_SCOPE(MacroInterp); @@ -283,5 +351,13 @@ u32 MacroInterpreterImpl::FetchParameter() { ASSERT(next_parameter_index < num_parameters); return parameters[next_parameter_index++]; } +} // Anonymous namespace + +MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d_) + : MacroEngine{maxwell3d_}, maxwell3d{maxwell3d_} {} + +std::unique_ptr MacroInterpreter::Compile(const std::vector& code) { + return std::make_unique(maxwell3d, code); +} } // namespace Tegra diff --git a/src/video_core/macro/macro_interpreter.h b/src/video_core/macro/macro_interpreter.h index d50c619ce..8a9648e46 100644 --- a/src/video_core/macro/macro_interpreter.h +++ b/src/video_core/macro/macro_interpreter.h @@ -3,10 +3,9 @@ // Refer to the license.txt file included. #pragma once -#include -#include + #include -#include "common/bit_field.h" + #include "common/common_types.h" #include "video_core/macro/macro.h" @@ -26,77 +25,4 @@ private: Engines::Maxwell3D& maxwell3d; }; -class MacroInterpreterImpl : public CachedMacro { -public: - explicit MacroInterpreterImpl(Engines::Maxwell3D& maxwell3d_, const std::vector& code_); - void Execute(const std::vector& params, u32 method) override; - -private: - /// Resets the execution engine state, zeroing registers, etc. - void Reset(); - - /** - * Executes a single macro instruction located at the current program counter. Returns whether - * the interpreter should keep running. - * - * @param is_delay_slot Whether the current step is being executed due to a delay slot in a - * previous instruction. - */ - bool Step(bool is_delay_slot); - - /// Calculates the result of an ALU operation. src_a OP src_b; - u32 GetALUResult(Macro::ALUOperation operation, u32 src_a, u32 src_b); - - /// Performs the result operation on the input result and stores it in the specified register - /// (if necessary). - void ProcessResult(Macro::ResultOperation operation, u32 reg, u32 result); - - /// Evaluates the branch condition and returns whether the branch should be taken or not. - bool EvaluateBranchCondition(Macro::BranchCondition cond, u32 value) const; - - /// Reads an opcode at the current program counter location. - Macro::Opcode GetOpcode() const; - - /// Returns the specified register's value. Register 0 is hardcoded to always return 0. - u32 GetRegister(u32 register_id) const; - - /// Sets the register to the input value. - void SetRegister(u32 register_id, u32 value); - - /// Sets the method address to use for the next Send instruction. - void SetMethodAddress(u32 address); - - /// Calls a GPU Engine method with the input parameter. - void Send(u32 value); - - /// Reads a GPU register located at the method address. - u32 Read(u32 method) const; - - /// Returns the next parameter in the parameter queue. - u32 FetchParameter(); - - Engines::Maxwell3D& maxwell3d; - - /// Current program counter - u32 pc; - /// Program counter to execute at after the delay slot is executed. - std::optional delayed_pc; - - /// General purpose macro registers. - std::array registers = {}; - - /// Method address to use for the next Send instruction. - Macro::MethodAddress method_address = {}; - - /// Input parameters of the current macro. - std::unique_ptr parameters; - std::size_t num_parameters = 0; - std::size_t parameters_capacity = 0; - /// Index of the next parameter that will be fetched by the 'parm' instruction. - u32 next_parameter_index = 0; - - bool carry_flag = false; - const std::vector& code; -}; - } // namespace Tegra -- cgit v1.2.3 From a8a4f37628015aace4c4192df41c69bda9706a3f Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 25 Jan 2022 14:09:59 -0500 Subject: video_core/macro: Add missing header Necessary since memcpy is used. --- src/video_core/macro/macro.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp index 0ae78a9e5..0aeda4ce8 100644 --- a/src/video_core/macro/macro.cpp +++ b/src/video_core/macro/macro.cpp @@ -2,12 +2,13 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include + #include + #include "common/assert.h" -#include "common/logging/log.h" #include "common/settings.h" -#include "video_core/engines/maxwell_3d.h" #include "video_core/macro/macro.h" #include "video_core/macro/macro_hle.h" #include "video_core/macro/macro_interpreter.h" -- cgit v1.2.3