summaryrefslogtreecommitdiffstats
path: root/src/core/arm/dynarmic/arm_dynarmic.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm/dynarmic/arm_dynarmic.cpp')
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp67
1 files changed, 60 insertions, 7 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 5d7efc9b6..83c09db2b 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -102,18 +102,28 @@ public:
u64 tpidr_el0 = 0;
};
-std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_Callbacks>& cb) {
+std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() {
const auto page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data();
Dynarmic::A64::UserConfig config;
+
+ // Callbacks
config.callbacks = cb.get();
+
+ // Memory
+ config.page_table = reinterpret_cast<void**>(page_table);
+ config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
+ config.silently_mirror_page_table = false;
+
+ // Multi-process state
+ config.processor_id = core_index;
+ config.global_monitor = &exclusive_monitor->monitor;
+
+ // System registers
config.tpidrro_el0 = &cb->tpidrro_el0;
config.tpidr_el0 = &cb->tpidr_el0;
config.dczid_el0 = 4;
config.ctr_el0 = 0x8444c004;
- config.page_table = reinterpret_cast<void**>(page_table);
- config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
- config.silently_mirror_page_table = false;
return std::make_unique<Dynarmic::A64::Jit>(config);
}
@@ -128,8 +138,11 @@ 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_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index)
+ : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)),
+ jit(MakeJit()), exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>(
+ exclusive_monitor)},
+ core_index{core_index} {
ARM_Interface::ThreadContext ctx;
inner_unicorn.SaveContext(ctx);
LoadContext(ctx);
@@ -237,6 +250,46 @@ void ARM_Dynarmic::ClearExclusiveState() {
}
void ARM_Dynarmic::PageTableChanged() {
- jit = MakeJit(cb);
+ jit = MakeJit();
current_page_table = Memory::GetCurrentPageTable();
}
+
+DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(size_t core_count) : monitor(core_count) {}
+DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
+
+void DynarmicExclusiveMonitor::SetExclusive(size_t core_index, u64 addr) {
+ // Size doesn't actually matter.
+ monitor.Mark(core_index, addr, 16);
+}
+
+void DynarmicExclusiveMonitor::ClearExclusive() {
+ monitor.Clear();
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 1,
+ [&] { Memory::Write8(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 2,
+ [&] { Memory::Write16(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 4,
+ [&] { Memory::Write32(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 8,
+ [&] { Memory::Write64(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite128(size_t core_index, u64 vaddr,
+ std::array<std::uint64_t, 2> value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] {
+ Memory::Write64(vaddr, value[0]);
+ Memory::Write64(vaddr, value[1]);
+ });
+}