Przeglądaj źródła

Implements citra-emu/citra#3184

N00byKing 8 lat temu
rodzic
commit
bc88cae0c7

+ 3 - 26
src/core/arm/arm_interface.h

@@ -25,19 +25,11 @@ public:
         VAddr tls_address;
     };
 
-    /**
-     * Runs the CPU for the given number of instructions
-     * @param num_instructions Number of instructions to run
-     */
-    void Run(int num_instructions) {
-        ExecuteInstructions(num_instructions);
-        this->num_instructions += num_instructions;
-    }
+    /// Runs the CPU until an event happens
+    virtual void Run() = 0;
 
     /// Step CPU by one instruction
-    void Step() {
-        Run(1);
-    }
+    virtual void Step() = 0;
 
     virtual void MapBackingMemory(VAddr address, size_t size, u8* memory,
                                   Kernel::VMAPermission perms) {}
@@ -122,19 +114,4 @@ public:
 
     /// Prepare core for thread reschedule (if needed to correctly handle state)
     virtual void PrepareReschedule() = 0;
-
-    /// Getter for num_instructions
-    u64 GetNumInstructions() const {
-        return num_instructions;
-    }
-
-protected:
-    /**
-     * Executes the given number of instructions
-     * @param num_instructions Number of instructions to executes
-     */
-    virtual void ExecuteInstructions(int num_instructions) = 0;
-
-private:
-    u64 num_instructions = 0; ///< Number of instructions executed
 };

+ 12 - 7
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
     return std::make_unique<Dynarmic::A64::Jit>(config);
 }
 
+void ARM_Dynarmic::Run() {
+    ASSERT(Memory::GetCurrentPageTable() == current_page_table);
+
+    jit->Run();
+}
+
+void ARM_Dynarmic::Step() {
+    cb->InterpreterFallback(jit->GetPC(), 1);
+}
+
 ARM_Dynarmic::ARM_Dynarmic()
     : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), jit(MakeJit(cb)) {
     ARM_Interface::ThreadContext ctx;
     inner_unicorn.SaveContext(ctx);
     LoadContext(ctx);
+    PageTableChanged();
 }
 
 ARM_Dynarmic::~ARM_Dynarmic() = default;
@@ -164,13 +175,6 @@ void ARM_Dynarmic::SetTlsAddress(u64 address) {
     cb->tpidrro_el0 = address;
 }
 
-void ARM_Dynarmic::ExecuteInstructions(int num_instructions) {
-    cb->ticks_remaining = num_instructions;
-    jit->Run();
-    CoreTiming::AddTicks(num_instructions - cb->num_interpreted_instructions);
-    cb->num_interpreted_instructions = 0;
-}
-
 void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
     ctx.cpu_registers = jit->GetRegisters();
     ctx.sp = jit->GetSP();
@@ -203,4 +207,5 @@ void ARM_Dynarmic::ClearInstructionCache() {
 
 void ARM_Dynarmic::PageTableChanged() {
     jit = MakeJit(cb);
+    current_page_table = Memory::GetCurrentPageTable();
 }

+ 4 - 1
src/core/arm/dynarmic/arm_dynarmic.h

@@ -29,6 +29,8 @@ public:
     u32 GetVFPReg(int index) const override;
     void SetVFPReg(int index, u32 value) override;
     u32 GetCPSR() const override;
+    void Run() override;
+    void Step() override;
     void SetCPSR(u32 cpsr) override;
     VAddr GetTlsAddress() const override;
     void SetTlsAddress(VAddr address) override;
@@ -37,7 +39,6 @@ public:
     void LoadContext(const ThreadContext& ctx) override;
 
     void PrepareReschedule() override;
-    void ExecuteInstructions(int num_instructions) override;
 
     void ClearInstructionCache() override;
     void PageTableChanged() override;
@@ -47,4 +48,6 @@ private:
     std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
     std::unique_ptr<Dynarmic::A64::Jit> jit;
     ARM_Unicorn inner_unicorn;
+
+    Memory::PageTable* current_page_table = nullptr;
 };

+ 9 - 0
src/core/arm/unicorn/arm_unicorn.cpp

@@ -2,6 +2,7 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
+#include <algorithm>
 #include <unicorn/arm64.h>
 #include "common/assert.h"
 #include "common/microprofile.h"
@@ -148,6 +149,14 @@ void ARM_Unicorn::SetTlsAddress(VAddr base) {
     CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDRRO_EL0, &base));
 }
 
+void ARM_Unicorn::Run() {
+    ExecuteInstructions(std::max(CoreTiming::GetDowncount(), 0));
+}
+
+void ARM_Unicorn::Step() {
+    ExecuteInstructions(1);
+}
+
 MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64));
 
 void ARM_Unicorn::ExecuteInstructions(int num_instructions) {

+ 3 - 1
src/core/arm/unicorn/arm_unicorn.h

@@ -29,7 +29,9 @@ public:
     void SaveContext(ThreadContext& ctx) override;
     void LoadContext(const ThreadContext& ctx) override;
     void PrepareReschedule() override;
-    void ExecuteInstructions(int num_instructions) override;
+    void ExecuteInstructions(int num_instructions);
+    void Run() override;
+    void Step() override;
     void ClearInstructionCache() override;
     void PageTableChanged() override{};
 

+ 8 - 4
src/core/core.cpp

@@ -26,7 +26,7 @@ namespace Core {
 
 /*static*/ System System::s_instance;
 
-System::ResultStatus System::RunLoop(int tight_loop) {
+System::ResultStatus System::RunLoop(bool tight_loop) {
     status = ResultStatus::Success;
     if (!cpu_core) {
         return ResultStatus::ErrorNotInitialized;
@@ -40,7 +40,7 @@ System::ResultStatus System::RunLoop(int tight_loop) {
         if (GDBStub::GetCpuHaltFlag()) {
             if (GDBStub::GetCpuStepFlag()) {
                 GDBStub::SetCpuStepFlag(false);
-                tight_loop = 1;
+                tight_loop = false;
             } else {
                 return ResultStatus::Success;
             }
@@ -56,7 +56,11 @@ System::ResultStatus System::RunLoop(int tight_loop) {
         PrepareReschedule();
     } else {
         CoreTiming::Advance();
-        cpu_core->Run(tight_loop);
+        if (tight_loop) {
+            cpu_core->Run();
+        } else {
+            cpu_core->Step();
+        }
     }
 
     HW::Update();
@@ -66,7 +70,7 @@ System::ResultStatus System::RunLoop(int tight_loop) {
 }
 
 System::ResultStatus System::SingleStep() {
-    return RunLoop(1);
+    return RunLoop(false);
 }
 
 System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {

+ 2 - 2
src/core/core.h

@@ -51,10 +51,10 @@ public:
      * is not required to do a full dispatch with each instruction. NOTE: the number of instructions
      * requested is not guaranteed to run, as this will be interrupted preemptively if a hardware
      * update is requested (e.g. on a thread switch).
-     * @param tight_loop Number of instructions to execute.
+     * @param tight_loop If false, the CPU single-steps.
      * @return Result status, indicating whether or not the operation succeeded.
      */
-    ResultStatus RunLoop(int tight_loop = 100000);
+    ResultStatus RunLoop(bool tight_loop = true);
 
     /**
      * Step the CPU one instruction