mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Implements citra-emu/citra#3184
This commit is contained in:
		
							parent
							
								
									b65c096be5
								
							
						
					
					
						commit
						bc88cae0c7
					
				@ -25,19 +25,11 @@ public:
 | 
				
			|||||||
        VAddr tls_address;
 | 
					        VAddr tls_address;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /// Runs the CPU until an event happens
 | 
				
			||||||
     * Runs the CPU for the given number of instructions
 | 
					    virtual void Run() = 0;
 | 
				
			||||||
     * @param num_instructions Number of instructions to run
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    void Run(int num_instructions) {
 | 
					 | 
				
			||||||
        ExecuteInstructions(num_instructions);
 | 
					 | 
				
			||||||
        this->num_instructions += num_instructions;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Step CPU by one instruction
 | 
					    /// Step CPU by one instruction
 | 
				
			||||||
    void Step() {
 | 
					    virtual void Step() = 0;
 | 
				
			||||||
        Run(1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual void MapBackingMemory(VAddr address, size_t size, u8* memory,
 | 
					    virtual void MapBackingMemory(VAddr address, size_t size, u8* memory,
 | 
				
			||||||
                                  Kernel::VMAPermission perms) {}
 | 
					                                  Kernel::VMAPermission perms) {}
 | 
				
			||||||
@ -122,19 +114,4 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Prepare core for thread reschedule (if needed to correctly handle state)
 | 
					    /// Prepare core for thread reschedule (if needed to correctly handle state)
 | 
				
			||||||
    virtual void PrepareReschedule() = 0;
 | 
					    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
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -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);
 | 
					    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()
 | 
					ARM_Dynarmic::ARM_Dynarmic()
 | 
				
			||||||
    : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), jit(MakeJit(cb)) {
 | 
					    : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), jit(MakeJit(cb)) {
 | 
				
			||||||
    ARM_Interface::ThreadContext ctx;
 | 
					    ARM_Interface::ThreadContext ctx;
 | 
				
			||||||
    inner_unicorn.SaveContext(ctx);
 | 
					    inner_unicorn.SaveContext(ctx);
 | 
				
			||||||
    LoadContext(ctx);
 | 
					    LoadContext(ctx);
 | 
				
			||||||
 | 
					    PageTableChanged();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ARM_Dynarmic::~ARM_Dynarmic() = default;
 | 
					ARM_Dynarmic::~ARM_Dynarmic() = default;
 | 
				
			||||||
@ -164,13 +175,6 @@ void ARM_Dynarmic::SetTlsAddress(u64 address) {
 | 
				
			|||||||
    cb->tpidrro_el0 = 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) {
 | 
					void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
 | 
				
			||||||
    ctx.cpu_registers = jit->GetRegisters();
 | 
					    ctx.cpu_registers = jit->GetRegisters();
 | 
				
			||||||
    ctx.sp = jit->GetSP();
 | 
					    ctx.sp = jit->GetSP();
 | 
				
			||||||
@ -203,4 +207,5 @@ void ARM_Dynarmic::ClearInstructionCache() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void ARM_Dynarmic::PageTableChanged() {
 | 
					void ARM_Dynarmic::PageTableChanged() {
 | 
				
			||||||
    jit = MakeJit(cb);
 | 
					    jit = MakeJit(cb);
 | 
				
			||||||
 | 
					    current_page_table = Memory::GetCurrentPageTable();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,8 @@ public:
 | 
				
			|||||||
    u32 GetVFPReg(int index) const override;
 | 
					    u32 GetVFPReg(int index) const override;
 | 
				
			||||||
    void SetVFPReg(int index, u32 value) override;
 | 
					    void SetVFPReg(int index, u32 value) override;
 | 
				
			||||||
    u32 GetCPSR() const override;
 | 
					    u32 GetCPSR() const override;
 | 
				
			||||||
 | 
					    void Run() override;
 | 
				
			||||||
 | 
					    void Step() override;
 | 
				
			||||||
    void SetCPSR(u32 cpsr) override;
 | 
					    void SetCPSR(u32 cpsr) override;
 | 
				
			||||||
    VAddr GetTlsAddress() const override;
 | 
					    VAddr GetTlsAddress() const override;
 | 
				
			||||||
    void SetTlsAddress(VAddr address) override;
 | 
					    void SetTlsAddress(VAddr address) override;
 | 
				
			||||||
@ -37,7 +39,6 @@ public:
 | 
				
			|||||||
    void LoadContext(const ThreadContext& ctx) override;
 | 
					    void LoadContext(const ThreadContext& ctx) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void PrepareReschedule() override;
 | 
					    void PrepareReschedule() override;
 | 
				
			||||||
    void ExecuteInstructions(int num_instructions) override;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void ClearInstructionCache() override;
 | 
					    void ClearInstructionCache() override;
 | 
				
			||||||
    void PageTableChanged() override;
 | 
					    void PageTableChanged() override;
 | 
				
			||||||
@ -47,4 +48,6 @@ private:
 | 
				
			|||||||
    std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
 | 
					    std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
 | 
				
			||||||
    std::unique_ptr<Dynarmic::A64::Jit> jit;
 | 
					    std::unique_ptr<Dynarmic::A64::Jit> jit;
 | 
				
			||||||
    ARM_Unicorn inner_unicorn;
 | 
					    ARM_Unicorn inner_unicorn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Memory::PageTable* current_page_table = nullptr;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
// Licensed under GPLv2 or any later version
 | 
					// Licensed under GPLv2 or any later version
 | 
				
			||||||
// Refer to the license.txt file included.
 | 
					// Refer to the license.txt file included.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
#include <unicorn/arm64.h>
 | 
					#include <unicorn/arm64.h>
 | 
				
			||||||
#include "common/assert.h"
 | 
					#include "common/assert.h"
 | 
				
			||||||
#include "common/microprofile.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));
 | 
					    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));
 | 
					MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
 | 
					void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,9 @@ public:
 | 
				
			|||||||
    void SaveContext(ThreadContext& ctx) override;
 | 
					    void SaveContext(ThreadContext& ctx) override;
 | 
				
			||||||
    void LoadContext(const ThreadContext& ctx) override;
 | 
					    void LoadContext(const ThreadContext& ctx) override;
 | 
				
			||||||
    void PrepareReschedule() 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 ClearInstructionCache() override;
 | 
				
			||||||
    void PageTableChanged() override{};
 | 
					    void PageTableChanged() override{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@ namespace Core {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/*static*/ System System::s_instance;
 | 
					/*static*/ System System::s_instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
System::ResultStatus System::RunLoop(int tight_loop) {
 | 
					System::ResultStatus System::RunLoop(bool tight_loop) {
 | 
				
			||||||
    status = ResultStatus::Success;
 | 
					    status = ResultStatus::Success;
 | 
				
			||||||
    if (!cpu_core) {
 | 
					    if (!cpu_core) {
 | 
				
			||||||
        return ResultStatus::ErrorNotInitialized;
 | 
					        return ResultStatus::ErrorNotInitialized;
 | 
				
			||||||
@ -40,7 +40,7 @@ System::ResultStatus System::RunLoop(int tight_loop) {
 | 
				
			|||||||
        if (GDBStub::GetCpuHaltFlag()) {
 | 
					        if (GDBStub::GetCpuHaltFlag()) {
 | 
				
			||||||
            if (GDBStub::GetCpuStepFlag()) {
 | 
					            if (GDBStub::GetCpuStepFlag()) {
 | 
				
			||||||
                GDBStub::SetCpuStepFlag(false);
 | 
					                GDBStub::SetCpuStepFlag(false);
 | 
				
			||||||
                tight_loop = 1;
 | 
					                tight_loop = false;
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                return ResultStatus::Success;
 | 
					                return ResultStatus::Success;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -56,7 +56,11 @@ System::ResultStatus System::RunLoop(int tight_loop) {
 | 
				
			|||||||
        PrepareReschedule();
 | 
					        PrepareReschedule();
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        CoreTiming::Advance();
 | 
					        CoreTiming::Advance();
 | 
				
			||||||
        cpu_core->Run(tight_loop);
 | 
					        if (tight_loop) {
 | 
				
			||||||
 | 
					            cpu_core->Run();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            cpu_core->Step();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    HW::Update();
 | 
					    HW::Update();
 | 
				
			||||||
@ -66,7 +70,7 @@ System::ResultStatus System::RunLoop(int tight_loop) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
System::ResultStatus System::SingleStep() {
 | 
					System::ResultStatus System::SingleStep() {
 | 
				
			||||||
    return RunLoop(1);
 | 
					    return RunLoop(false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
 | 
					System::ResultStatus System::Load(EmuWindow* emu_window, const std::string& filepath) {
 | 
				
			||||||
 | 
				
			|||||||
@ -51,10 +51,10 @@ public:
 | 
				
			|||||||
     * is not required to do a full dispatch with each instruction. NOTE: the number of instructions
 | 
					     * 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
 | 
					     * requested is not guaranteed to run, as this will be interrupted preemptively if a hardware
 | 
				
			||||||
     * update is requested (e.g. on a thread switch).
 | 
					     * 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.
 | 
					     * @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
 | 
					     * Step the CPU one instruction
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user