mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-11-03 23:28:48 +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
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue