mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Core: Port Exclusive memory impl from yuzu
core\arm\dynarmic\arm_dynarmic.cpp: fix build core\arm\dynarmic\arm_dynarmic.cpp: Fixes CPP 20
This commit is contained in:
		
							parent
							
								
									98d3b9c776
								
							
						
					
					
						commit
						fbe06234b1
					
				
					 19 changed files with 470 additions and 22 deletions
				
			
		|  | @ -122,6 +122,9 @@ public: | |||
|      */ | ||||
|     virtual void InvalidateCacheRange(u32 start_address, std::size_t length) = 0; | ||||
| 
 | ||||
|     /// Clears the exclusive monitor's state.
 | ||||
|     virtual void ClearExclusiveState() = 0; | ||||
| 
 | ||||
|     /// Notify CPU emulation that page tables have changed
 | ||||
|     virtual void SetPageTable(const std::shared_ptr<Memory::PageTable>& page_table) = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,12 +3,14 @@ | |||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <cstring> | ||||
| #include <dynarmic/A32/a32.h> | ||||
| #include <dynarmic/A32/context.h> | ||||
| #include <dynarmic/interface/A32/a32.h> | ||||
| #include <dynarmic/interface/A32/context.h> | ||||
| #include <dynarmic/interface/optimization_flags.h> | ||||
| #include "common/assert.h" | ||||
| #include "common/microprofile.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_cp15.h" | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/gdbstub/gdbstub.h" | ||||
|  | @ -100,10 +102,23 @@ public: | |||
|         memory.Write64(vaddr, value); | ||||
|     } | ||||
| 
 | ||||
|     bool MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) override { | ||||
|         return memory.WriteExclusive8(vaddr, value, expected); | ||||
|     } | ||||
|     bool MemoryWriteExclusive16(u32 vaddr, u16 value, u16 expected) override { | ||||
|         return memory.WriteExclusive16(vaddr, value, expected); | ||||
|     } | ||||
|     bool MemoryWriteExclusive32(u32 vaddr, u32 value, u32 expected) override { | ||||
|         return memory.WriteExclusive32(vaddr, value, expected); | ||||
|     } | ||||
|     bool MemoryWriteExclusive64(u32 vaddr, u64 value, u64 expected) override { | ||||
|         return memory.WriteExclusive64(vaddr, value, expected); | ||||
|     } | ||||
| 
 | ||||
|     void InterpreterFallback(VAddr pc, std::size_t num_instructions) override { | ||||
|         // Should never happen.
 | ||||
|         UNREACHABLE_MSG("InterpeterFallback reached with pc = 0x{:08x}, code = 0x{:08x}, num = {}", | ||||
|                         pc, MemoryReadCode(pc), num_instructions); | ||||
|                         pc, MemoryReadCode(pc).value(), num_instructions); | ||||
|     } | ||||
| 
 | ||||
|     void CallSVC(std::uint32_t swi) override { | ||||
|  | @ -114,6 +129,8 @@ public: | |||
|         switch (exception) { | ||||
|         case Dynarmic::A32::Exception::UndefinedInstruction: | ||||
|         case Dynarmic::A32::Exception::UnpredictableInstruction: | ||||
|         case Dynarmic::A32::Exception::DecodeError: | ||||
|         case Dynarmic::A32::Exception::NoExecuteFault: | ||||
|             break; | ||||
|         case Dynarmic::A32::Exception::Breakpoint: | ||||
|             if (GDBStub::IsConnected()) { | ||||
|  | @ -130,10 +147,11 @@ public: | |||
|         case Dynarmic::A32::Exception::Yield: | ||||
|         case Dynarmic::A32::Exception::PreloadData: | ||||
|         case Dynarmic::A32::Exception::PreloadDataWithIntentToWrite: | ||||
|         case Dynarmic::A32::Exception::PreloadInstruction: | ||||
|             return; | ||||
|         } | ||||
|         ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", exception, | ||||
|                    pc, MemoryReadCode(pc)); | ||||
|                    pc, MemoryReadCode(pc).value()); | ||||
|     } | ||||
| 
 | ||||
|     void AddTicks(std::uint64_t ticks) override { | ||||
|  | @ -149,10 +167,12 @@ public: | |||
|     Memory::MemorySystem& memory; | ||||
| }; | ||||
| 
 | ||||
| ARM_Dynarmic::ARM_Dynarmic(Core::System* system, Memory::MemorySystem& memory, u32 id, | ||||
|                            std::shared_ptr<Core::Timing::Timer> timer) | ||||
|     : ARM_Interface(id, timer), system(*system), memory(memory), | ||||
|       cb(std::make_unique<DynarmicUserCallbacks>(*this)) { | ||||
| ARM_Dynarmic::ARM_Dynarmic(Core::System* system_, Memory::MemorySystem& memory_, u32 core_id_, | ||||
|                            std::shared_ptr<Core::Timing::Timer> timer_, | ||||
|                            Core::ExclusiveMonitor& exclusive_monitor_) | ||||
|     : ARM_Interface(core_id_, timer_), system(*system_), memory(memory_), | ||||
|       cb(std::make_unique<DynarmicUserCallbacks>(*this)), | ||||
|       exclusive_monitor{dynamic_cast<Core::DynarmicExclusiveMonitor&>(exclusive_monitor_)} { | ||||
|     SetPageTable(memory.GetCurrentPageTable()); | ||||
| } | ||||
| 
 | ||||
|  | @ -208,6 +228,7 @@ u32 ARM_Dynarmic::GetVFPSystemReg(VFPSystemRegister reg) const { | |||
|     default: | ||||
|         UNREACHABLE_MSG("Unknown VFP system register: {}", reg); | ||||
|     } | ||||
|     return UINT_MAX; | ||||
| } | ||||
| 
 | ||||
| void ARM_Dynarmic::SetVFPSystemReg(VFPSystemRegister reg, u32 value) { | ||||
|  | @ -291,6 +312,10 @@ void ARM_Dynarmic::InvalidateCacheRange(u32 start_address, std::size_t length) { | |||
|     jit->InvalidateCacheRange(start_address, length); | ||||
| } | ||||
| 
 | ||||
| void ARM_Dynarmic::ClearExclusiveState() { | ||||
|     jit->ClearExclusiveState(); | ||||
| } | ||||
| 
 | ||||
| std::shared_ptr<Memory::PageTable> ARM_Dynarmic::GetPageTable() const { | ||||
|     return current_page_table; | ||||
| } | ||||
|  | @ -328,6 +353,11 @@ std::unique_ptr<Dynarmic::A32::Jit> ARM_Dynarmic::MakeJit() { | |||
|     config.page_table = ¤t_page_table->GetPointerArray(); | ||||
|     config.coprocessors[15] = std::make_shared<DynarmicCP15>(cp15_state); | ||||
|     config.define_unpredictable_behaviour = true; | ||||
| 
 | ||||
|     // Multi-process state
 | ||||
|     config.processor_id = GetID(); | ||||
|     config.global_monitor = &exclusive_monitor.monitor; | ||||
| 
 | ||||
|     return std::make_unique<Dynarmic::A32::Jit>(config); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| 
 | ||||
| #include <map> | ||||
| #include <memory> | ||||
| #include <dynarmic/A32/a32.h> | ||||
| #include <dynarmic/interface/A32/a32.h> | ||||
| #include "common/common_types.h" | ||||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_cp15.h" | ||||
|  | @ -17,6 +17,8 @@ class MemorySystem; | |||
| } // namespace Memory
 | ||||
| 
 | ||||
| namespace Core { | ||||
| class DynarmicExclusiveMonitor; | ||||
| class ExclusiveMonitor; | ||||
| class System; | ||||
| } | ||||
| 
 | ||||
|  | @ -24,8 +26,9 @@ class DynarmicUserCallbacks; | |||
| 
 | ||||
| class ARM_Dynarmic final : public ARM_Interface { | ||||
| public: | ||||
|     ARM_Dynarmic(Core::System* system, Memory::MemorySystem& memory, u32 id, | ||||
|                  std::shared_ptr<Core::Timing::Timer> timer); | ||||
|     explicit ARM_Dynarmic(Core::System* system_, Memory::MemorySystem& memory_, u32 core_id_, | ||||
|                            std::shared_ptr<Core::Timing::Timer> timer, | ||||
|                            Core::ExclusiveMonitor& exclusive_monitor_); | ||||
|     ~ARM_Dynarmic() override; | ||||
| 
 | ||||
|     void Run() override; | ||||
|  | @ -52,6 +55,7 @@ public: | |||
| 
 | ||||
|     void ClearInstructionCache() override; | ||||
|     void InvalidateCacheRange(u32 start_address, std::size_t length) override; | ||||
|     void ClearExclusiveState() override; | ||||
|     void SetPageTable(const std::shared_ptr<Memory::PageTable>& page_table) override; | ||||
|     void PurgeState() override; | ||||
| 
 | ||||
|  | @ -69,6 +73,7 @@ private: | |||
| 
 | ||||
|     u32 fpexc = 0; | ||||
|     CP15State cp15_state; | ||||
|     Core::DynarmicExclusiveMonitor& exclusive_monitor; | ||||
| 
 | ||||
|     Dynarmic::A32::Jit* jit = nullptr; | ||||
|     std::shared_ptr<Memory::PageTable> current_page_table = nullptr; | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <dynarmic/A32/coprocessor.h> | ||||
| #include <dynarmic/interface/A32/coprocessor.h> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| struct CP15State { | ||||
|  |  | |||
							
								
								
									
										58
									
								
								src/core/arm/dynarmic/arm_exclusive_monitor.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/core/arm/dynarmic/arm_exclusive_monitor.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::MemorySystem& memory_, std::size_t core_count_) | ||||
|     : monitor{core_count_}, memory{memory_} {} | ||||
| 
 | ||||
| DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; | ||||
| 
 | ||||
| u8 DynarmicExclusiveMonitor::ExclusiveRead8(std::size_t core_index, VAddr addr) { | ||||
|     return monitor.ReadAndMark<u8>(core_index, addr, [&]() -> u8 { return memory.Read8(addr); }); | ||||
| } | ||||
| 
 | ||||
| u16 DynarmicExclusiveMonitor::ExclusiveRead16(std::size_t core_index, VAddr addr) { | ||||
|     return monitor.ReadAndMark<u16>(core_index, addr, [&]() -> u16 { return memory.Read16(addr); }); | ||||
| } | ||||
| 
 | ||||
| u32 DynarmicExclusiveMonitor::ExclusiveRead32(std::size_t core_index, VAddr addr) { | ||||
|     return monitor.ReadAndMark<u32>(core_index, addr, [&]() -> u32 { return memory.Read32(addr); }); | ||||
| } | ||||
| 
 | ||||
| u64 DynarmicExclusiveMonitor::ExclusiveRead64(std::size_t core_index, VAddr addr) { | ||||
|     return monitor.ReadAndMark<u64>(core_index, addr, [&]() -> u64 { return memory.Read64(addr); }); | ||||
| } | ||||
| 
 | ||||
| void DynarmicExclusiveMonitor::ClearExclusive(std::size_t core_index) { | ||||
|     monitor.ClearProcessor(core_index); | ||||
| } | ||||
| 
 | ||||
| bool DynarmicExclusiveMonitor::ExclusiveWrite8(std::size_t core_index, VAddr vaddr, u8 value) { | ||||
|     return monitor.DoExclusiveOperation<u8>(core_index, vaddr, [&](u8 expected) -> bool { | ||||
|         return memory.WriteExclusive8(vaddr, value, expected); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| bool DynarmicExclusiveMonitor::ExclusiveWrite16(std::size_t core_index, VAddr vaddr, u16 value) { | ||||
|     return monitor.DoExclusiveOperation<u16>(core_index, vaddr, [&](u16 expected) -> bool { | ||||
|         return memory.WriteExclusive16(vaddr, value, expected); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| bool DynarmicExclusiveMonitor::ExclusiveWrite32(std::size_t core_index, VAddr vaddr, u32 value) { | ||||
|     return monitor.DoExclusiveOperation<u32>(core_index, vaddr, [&](u32 expected) -> bool { | ||||
|         return memory.WriteExclusive32(vaddr, value, expected); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| bool DynarmicExclusiveMonitor::ExclusiveWrite64(std::size_t core_index, VAddr vaddr, u64 value) { | ||||
|     return monitor.DoExclusiveOperation<u64>(core_index, vaddr, [&](u64 expected) -> bool { | ||||
|         return memory.WriteExclusive64(vaddr, value, expected); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| } // namespace Core
 | ||||
							
								
								
									
										40
									
								
								src/core/arm/dynarmic/arm_exclusive_monitor.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/core/arm/dynarmic/arm_exclusive_monitor.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | |||
| // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <dynarmic/interface/exclusive_monitor.h> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic.h" | ||||
| #include "core/arm/exclusive_monitor.h" | ||||
| 
 | ||||
| namespace Memory { | ||||
| class MemorySystem; | ||||
| } | ||||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| class DynarmicExclusiveMonitor final : public ExclusiveMonitor { | ||||
| public: | ||||
|     explicit DynarmicExclusiveMonitor( Memory::MemorySystem& memory_, std::size_t core_count_); | ||||
|     ~DynarmicExclusiveMonitor() override; | ||||
| 
 | ||||
|     u8 ExclusiveRead8(std::size_t core_index, VAddr addr) override; | ||||
|     u16 ExclusiveRead16(std::size_t core_index, VAddr addr) override; | ||||
|     u32 ExclusiveRead32(std::size_t core_index, VAddr addr) override; | ||||
|     u64 ExclusiveRead64(std::size_t core_index, VAddr addr) override; | ||||
|     void ClearExclusive(std::size_t core_index) override; | ||||
| 
 | ||||
|     bool ExclusiveWrite8(std::size_t core_index, VAddr vaddr, u8 value) override; | ||||
|     bool ExclusiveWrite16(std::size_t core_index, VAddr vaddr, u16 value) override; | ||||
|     bool ExclusiveWrite32(std::size_t core_index, VAddr vaddr, u32 value) override; | ||||
|     bool ExclusiveWrite64(std::size_t core_index, VAddr vaddr, u64 value) override; | ||||
| 
 | ||||
| private: | ||||
|     friend class ::ARM_Dynarmic; | ||||
|     Dynarmic::ExclusiveMonitor monitor; | ||||
|     Memory::MemorySystem& memory; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Core
 | ||||
|  | @ -30,6 +30,7 @@ public: | |||
| 
 | ||||
|     void ClearInstructionCache() override; | ||||
|     void InvalidateCacheRange(u32 start_address, std::size_t length) override; | ||||
|     void ClearExclusiveState() override {}; | ||||
| 
 | ||||
|     void SetPC(u32 pc) override; | ||||
|     u32 GetPC() const override; | ||||
|  |  | |||
							
								
								
									
										26
									
								
								src/core/arm/exclusive_monitor.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/core/arm/exclusive_monitor.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| #endif | ||||
| #include "core/arm/exclusive_monitor.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/settings.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| ExclusiveMonitor::~ExclusiveMonitor() = default; | ||||
| 
 | ||||
| std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::MemorySystem& memory, | ||||
|                                                              std::size_t num_cores) { | ||||
| #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | ||||
|     if (Settings::values.use_cpu_jit) { | ||||
|         return std::make_unique<Core::DynarmicExclusiveMonitor>(memory, num_cores); | ||||
|     } | ||||
| #endif | ||||
|     // TODO(merry): Passthrough exclusive monitor
 | ||||
|     return nullptr; | ||||
| } | ||||
| 
 | ||||
| } // namespace Core
 | ||||
							
								
								
									
										35
									
								
								src/core/arm/exclusive_monitor.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/core/arm/exclusive_monitor.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Memory { | ||||
| class MemorySystem; | ||||
| } | ||||
| 
 | ||||
| namespace Core { | ||||
| 
 | ||||
| class ExclusiveMonitor { | ||||
| public: | ||||
|     virtual ~ExclusiveMonitor(); | ||||
| 
 | ||||
|     virtual u8 ExclusiveRead8(std::size_t core_index, VAddr addr) = 0; | ||||
|     virtual u16 ExclusiveRead16(std::size_t core_index, VAddr addr) = 0; | ||||
|     virtual u32 ExclusiveRead32(std::size_t core_index, VAddr addr) = 0; | ||||
|     virtual u64 ExclusiveRead64(std::size_t core_index, VAddr addr) = 0; | ||||
|     virtual void ClearExclusive(std::size_t core_index) = 0; | ||||
| 
 | ||||
|     virtual bool ExclusiveWrite8(std::size_t core_index, VAddr vaddr, u8 value) = 0; | ||||
|     virtual bool ExclusiveWrite16(std::size_t core_index, VAddr vaddr, u16 value) = 0; | ||||
|     virtual bool ExclusiveWrite32(std::size_t core_index, VAddr vaddr, u32 value) = 0; | ||||
|     virtual bool ExclusiveWrite64(std::size_t core_index, VAddr vaddr, u64 value) = 0; | ||||
| }; | ||||
| 
 | ||||
| std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::MemorySystem& memory, | ||||
|                                                              std::size_t num_cores); | ||||
| 
 | ||||
| } // namespace Core
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue