diff options
| author | 2018-02-14 18:47:48 +0100 | |
|---|---|---|
| committer | 2018-02-25 11:44:21 +0100 | |
| commit | bc88cae0c730ece6d027778267eb0fa256479bda (patch) | |
| tree | eaf8581141f7240b6cf23eda17834558b6fe1c40 /src | |
| parent | Merge pull request #190 from bunnei/fix-qt-waittree (diff) | |
| download | yuzu-bc88cae0c730ece6d027778267eb0fa256479bda.tar.gz yuzu-bc88cae0c730ece6d027778267eb0fa256479bda.tar.xz yuzu-bc88cae0c730ece6d027778267eb0fa256479bda.zip | |
Implements citra-emu/citra#3184
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/arm_interface.h | 29 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.cpp | 19 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.h | 5 | ||||
| -rw-r--r-- | src/core/arm/unicorn/arm_unicorn.cpp | 9 | ||||
| -rw-r--r-- | src/core/arm/unicorn/arm_unicorn.h | 4 | ||||
| -rw-r--r-- | src/core/core.cpp | 12 | ||||
| -rw-r--r-- | src/core/core.h | 4 |
7 files changed, 41 insertions, 41 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 5ae60214e..9f2224b78 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -25,19 +25,11 @@ public: | |||
| 25 | VAddr tls_address; | 25 | VAddr tls_address; |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | /** | 28 | /// Runs the CPU until an event happens |
| 29 | * Runs the CPU for the given number of instructions | 29 | virtual void Run() = 0; |
| 30 | * @param num_instructions Number of instructions to run | ||
| 31 | */ | ||
| 32 | void Run(int num_instructions) { | ||
| 33 | ExecuteInstructions(num_instructions); | ||
| 34 | this->num_instructions += num_instructions; | ||
| 35 | } | ||
| 36 | 30 | ||
| 37 | /// Step CPU by one instruction | 31 | /// Step CPU by one instruction |
| 38 | void Step() { | 32 | virtual void Step() = 0; |
| 39 | Run(1); | ||
| 40 | } | ||
| 41 | 33 | ||
| 42 | virtual void MapBackingMemory(VAddr address, size_t size, u8* memory, | 34 | virtual void MapBackingMemory(VAddr address, size_t size, u8* memory, |
| 43 | Kernel::VMAPermission perms) {} | 35 | Kernel::VMAPermission perms) {} |
| @@ -122,19 +114,4 @@ public: | |||
| 122 | 114 | ||
| 123 | /// Prepare core for thread reschedule (if needed to correctly handle state) | 115 | /// Prepare core for thread reschedule (if needed to correctly handle state) |
| 124 | virtual void PrepareReschedule() = 0; | 116 | virtual void PrepareReschedule() = 0; |
| 125 | |||
| 126 | /// Getter for num_instructions | ||
| 127 | u64 GetNumInstructions() const { | ||
| 128 | return num_instructions; | ||
| 129 | } | ||
| 130 | |||
| 131 | protected: | ||
| 132 | /** | ||
| 133 | * Executes the given number of instructions | ||
| 134 | * @param num_instructions Number of instructions to executes | ||
| 135 | */ | ||
| 136 | virtual void ExecuteInstructions(int num_instructions) = 0; | ||
| 137 | |||
| 138 | private: | ||
| 139 | u64 num_instructions = 0; ///< Number of instructions executed | ||
| 140 | }; | 117 | }; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 283d20831..a64ce9551 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp | |||
| @@ -101,11 +101,22 @@ std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_C | |||
| 101 | return std::make_unique<Dynarmic::A64::Jit>(config); | 101 | return std::make_unique<Dynarmic::A64::Jit>(config); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | void ARM_Dynarmic::Run() { | ||
| 105 | ASSERT(Memory::GetCurrentPageTable() == current_page_table); | ||
| 106 | |||
| 107 | jit->Run(); | ||
| 108 | } | ||
| 109 | |||
| 110 | void ARM_Dynarmic::Step() { | ||
| 111 | cb->InterpreterFallback(jit->GetPC(), 1); | ||
| 112 | } | ||
| 113 | |||
| 104 | ARM_Dynarmic::ARM_Dynarmic() | 114 | ARM_Dynarmic::ARM_Dynarmic() |
| 105 | : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), jit(MakeJit(cb)) { | 115 | : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), jit(MakeJit(cb)) { |
| 106 | ARM_Interface::ThreadContext ctx; | 116 | ARM_Interface::ThreadContext ctx; |
| 107 | inner_unicorn.SaveContext(ctx); | 117 | inner_unicorn.SaveContext(ctx); |
| 108 | LoadContext(ctx); | 118 | LoadContext(ctx); |
| 119 | PageTableChanged(); | ||
| 109 | } | 120 | } |
| 110 | 121 | ||
| 111 | ARM_Dynarmic::~ARM_Dynarmic() = default; | 122 | ARM_Dynarmic::~ARM_Dynarmic() = default; |
| @@ -164,13 +175,6 @@ void ARM_Dynarmic::SetTlsAddress(u64 address) { | |||
| 164 | cb->tpidrro_el0 = address; | 175 | cb->tpidrro_el0 = address; |
| 165 | } | 176 | } |
| 166 | 177 | ||
| 167 | void ARM_Dynarmic::ExecuteInstructions(int num_instructions) { | ||
| 168 | cb->ticks_remaining = num_instructions; | ||
| 169 | jit->Run(); | ||
| 170 | CoreTiming::AddTicks(num_instructions - cb->num_interpreted_instructions); | ||
| 171 | cb->num_interpreted_instructions = 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) { | 178 | void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) { |
| 175 | ctx.cpu_registers = jit->GetRegisters(); | 179 | ctx.cpu_registers = jit->GetRegisters(); |
| 176 | ctx.sp = jit->GetSP(); | 180 | ctx.sp = jit->GetSP(); |
| @@ -203,4 +207,5 @@ void ARM_Dynarmic::ClearInstructionCache() { | |||
| 203 | 207 | ||
| 204 | void ARM_Dynarmic::PageTableChanged() { | 208 | void ARM_Dynarmic::PageTableChanged() { |
| 205 | jit = MakeJit(cb); | 209 | jit = MakeJit(cb); |
| 210 | current_page_table = Memory::GetCurrentPageTable(); | ||
| 206 | } | 211 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 1d9dcf5ff..a436ddd0f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h | |||
| @@ -29,6 +29,8 @@ public: | |||
| 29 | u32 GetVFPReg(int index) const override; | 29 | u32 GetVFPReg(int index) const override; |
| 30 | void SetVFPReg(int index, u32 value) override; | 30 | void SetVFPReg(int index, u32 value) override; |
| 31 | u32 GetCPSR() const override; | 31 | u32 GetCPSR() const override; |
| 32 | void Run() override; | ||
| 33 | void Step() override; | ||
| 32 | void SetCPSR(u32 cpsr) override; | 34 | void SetCPSR(u32 cpsr) override; |
| 33 | VAddr GetTlsAddress() const override; | 35 | VAddr GetTlsAddress() const override; |
| 34 | void SetTlsAddress(VAddr address) override; | 36 | void SetTlsAddress(VAddr address) override; |
| @@ -37,7 +39,6 @@ public: | |||
| 37 | void LoadContext(const ThreadContext& ctx) override; | 39 | void LoadContext(const ThreadContext& ctx) override; |
| 38 | 40 | ||
| 39 | void PrepareReschedule() override; | 41 | void PrepareReschedule() override; |
| 40 | void ExecuteInstructions(int num_instructions) override; | ||
| 41 | 42 | ||
| 42 | void ClearInstructionCache() override; | 43 | void ClearInstructionCache() override; |
| 43 | void PageTableChanged() override; | 44 | void PageTableChanged() override; |
| @@ -47,4 +48,6 @@ private: | |||
| 47 | std::unique_ptr<ARM_Dynarmic_Callbacks> cb; | 48 | std::unique_ptr<ARM_Dynarmic_Callbacks> cb; |
| 48 | std::unique_ptr<Dynarmic::A64::Jit> jit; | 49 | std::unique_ptr<Dynarmic::A64::Jit> jit; |
| 49 | ARM_Unicorn inner_unicorn; | 50 | ARM_Unicorn inner_unicorn; |
| 51 | |||
| 52 | Memory::PageTable* current_page_table = nullptr; | ||
| 50 | }; | 53 | }; |
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index fd64eab39..7542ed46a 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 5 | #include <unicorn/arm64.h> | 6 | #include <unicorn/arm64.h> |
| 6 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 7 | #include "common/microprofile.h" | 8 | #include "common/microprofile.h" |
| @@ -148,6 +149,14 @@ void ARM_Unicorn::SetTlsAddress(VAddr base) { | |||
| 148 | CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDRRO_EL0, &base)); | 149 | CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDRRO_EL0, &base)); |
| 149 | } | 150 | } |
| 150 | 151 | ||
| 152 | void ARM_Unicorn::Run() { | ||
| 153 | ExecuteInstructions(std::max(CoreTiming::GetDowncount(), 0)); | ||
| 154 | } | ||
| 155 | |||
| 156 | void ARM_Unicorn::Step() { | ||
| 157 | ExecuteInstructions(1); | ||
| 158 | } | ||
| 159 | |||
| 151 | MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64)); | 160 | MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64)); |
| 152 | 161 | ||
| 153 | void ARM_Unicorn::ExecuteInstructions(int num_instructions) { | 162 | void ARM_Unicorn::ExecuteInstructions(int num_instructions) { |
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h index c9a561dec..a2841c564 100644 --- a/src/core/arm/unicorn/arm_unicorn.h +++ b/src/core/arm/unicorn/arm_unicorn.h | |||
| @@ -29,7 +29,9 @@ public: | |||
| 29 | void SaveContext(ThreadContext& ctx) override; | 29 | void SaveContext(ThreadContext& ctx) override; |
| 30 | void LoadContext(const ThreadContext& ctx) override; | 30 | void LoadContext(const ThreadContext& ctx) override; |
| 31 | void PrepareReschedule() override; | 31 | void PrepareReschedule() override; |
| 32 | void ExecuteInstructions(int num_instructions) override; | 32 | void ExecuteInstructions(int num_instructions); |
| 33 | void Run() override; | ||
| 34 | void Step() override; | ||
| 33 | void ClearInstructionCache() override; | 35 | void ClearInstructionCache() override; |
| 34 | void PageTableChanged() override{}; | 36 | void PageTableChanged() override{}; |
| 35 | 37 | ||
diff --git a/src/core/core.cpp b/src/core/core.cpp index 613a98b4c..a42cb48eb 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -26,7 +26,7 @@ namespace Core { | |||
| 26 | 26 | ||
| 27 | /*static*/ System System::s_instance; | 27 | /*static*/ System System::s_instance; |
| 28 | 28 | ||
| 29 | System::ResultStatus System::RunLoop(int tight_loop) { | 29 | System::ResultStatus System::RunLoop(bool tight_loop) { |
| 30 | status = ResultStatus::Success; | 30 | status = ResultStatus::Success; |
| 31 | if (!cpu_core) { | 31 | if (!cpu_core) { |
| 32 | return ResultStatus::ErrorNotInitialized; | 32 | return ResultStatus::ErrorNotInitialized; |
| @@ -40,7 +40,7 @@ System::ResultStatus System::RunLoop(int tight_loop) { | |||
| 40 | if (GDBStub::GetCpuHaltFlag()) { | 40 | if (GDBStub::GetCpuHaltFlag()) { |
| 41 | if (GDBStub::GetCpuStepFlag()) { | 41 | if (GDBStub::GetCpuStepFlag()) { |
| 42 | GDBStub::SetCpuStepFlag(false); | 42 | GDBStub::SetCpuStepFlag(false); |
| 43 | tight_loop = 1; | 43 | tight_loop = false; |
| 44 | } else { | 44 | } else { |
| 45 | return ResultStatus::Success; | 45 | return ResultStatus::Success; |
| 46 | } | 46 | } |
| @@ -56,7 +56,11 @@ System::ResultStatus System::RunLoop(int tight_loop) { | |||
| 56 | PrepareReschedule(); | 56 | PrepareReschedule(); |
| 57 | } else { | 57 | } else { |
| 58 | CoreTiming::Advance(); | 58 | CoreTiming::Advance(); |
| 59 | cpu_core->Run(tight_loop); | 59 | if (tight_loop) { |
| 60 | cpu_core->Run(); | ||
| 61 | } else { | ||
| 62 | cpu_core->Step(); | ||
| 63 | } | ||
| 60 | } | 64 | } |
| 61 | 65 | ||
| 62 | HW::Update(); | 66 | HW::Update(); |
| @@ -66,7 +70,7 @@ System::ResultStatus System::RunLoop(int tight_loop) { | |||
| 66 | } | 70 | } |
| 67 | 71 | ||
| 68 | System::ResultStatus System::SingleStep() { | 72 | System::ResultStatus System::SingleStep() { |
| 69 | return RunLoop(1); | 73 | return RunLoop(false); |
| 70 | } | 74 | } |
| 71 | 75 | ||
| 72 | System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) { | 76 | System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) { |
diff --git a/src/core/core.h b/src/core/core.h index f63cc47cc..2d15ebe34 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -51,10 +51,10 @@ public: | |||
| 51 | * is not required to do a full dispatch with each instruction. NOTE: the number of instructions | 51 | * is not required to do a full dispatch with each instruction. NOTE: the number of instructions |
| 52 | * requested is not guaranteed to run, as this will be interrupted preemptively if a hardware | 52 | * requested is not guaranteed to run, as this will be interrupted preemptively if a hardware |
| 53 | * update is requested (e.g. on a thread switch). | 53 | * update is requested (e.g. on a thread switch). |
| 54 | * @param tight_loop Number of instructions to execute. | 54 | * @param tight_loop If false, the CPU single-steps. |
| 55 | * @return Result status, indicating whether or not the operation succeeded. | 55 | * @return Result status, indicating whether or not the operation succeeded. |
| 56 | */ | 56 | */ |
| 57 | ResultStatus RunLoop(int tight_loop = 100000); | 57 | ResultStatus RunLoop(bool tight_loop = true); |
| 58 | 58 | ||
| 59 | /** | 59 | /** |
| 60 | * Step the CPU one instruction | 60 | * Step the CPU one instruction |