diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj
index 56bcaf38..eec53650 100644
--- a/src/common/common.vcxproj
+++ b/src/common/common.vcxproj
@@ -27,6 +27,7 @@
+
@@ -36,6 +37,7 @@
+
diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters
index dd934f65..ce7b7d01 100644
--- a/src/common/common.vcxproj.filters
+++ b/src/common/common.vcxproj.filters
@@ -36,6 +36,9 @@
Header Files
+
+ Header Files
+
@@ -56,5 +59,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file
diff --git a/src/common/maths.cpp b/src/common/maths.cpp
new file mode 100644
index 00000000..a33f6f58
--- /dev/null
+++ b/src/common/maths.cpp
@@ -0,0 +1,171 @@
+#include "maths.h"
+#include
+
+uint32_t clz32(uint32_t val)
+{
+#if defined(__GNUC__)
+ return val ? __builtin_clz(val) : 32;
+#else
+ /* Binary search for the leading one bit. */
+ int cnt = 0;
+
+ if ((val & 0xFFFF0000U) == 0)
+ {
+ cnt += 16;
+ val <<= 16;
+ }
+ if ((val & 0xFF000000U) == 0)
+ {
+ cnt += 8;
+ val <<= 8;
+ }
+ if ((val & 0xF0000000U) == 0)
+ {
+ cnt += 4;
+ val <<= 4;
+ }
+ if ((val & 0xC0000000U) == 0)
+ {
+ cnt += 2;
+ val <<= 2;
+ }
+ if ((val & 0x80000000U) == 0)
+ {
+ cnt++;
+ val <<= 1;
+ }
+ if ((val & 0x80000000U) == 0)
+ {
+ cnt++;
+ }
+ return cnt;
+#endif
+}
+
+uint32_t clz64(uint64_t val)
+{
+#if defined(__GNUC__)
+ return val ? __builtin_clzll(val) : 64;
+#else
+ int cnt = 0;
+
+ if ((val >> 32) == 0)
+ {
+ cnt += 32;
+ }
+ else
+ {
+ val >>= 32;
+ }
+
+ return cnt + clz32((uint32_t)val);
+#endif
+}
+
+uint64_t mull128_u64(uint64_t multiplier, uint64_t multiplicand, uint64_t * high)
+{
+#if defined(_MSC_VER)
+ return _umul128(multiplier, multiplicand, high);
+#else
+ // multiplier = ab = a * 2^32 + b
+ // multiplicand = cd = c * 2^32 + d
+ // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
+ uint64_t a = multiplier >> 32;
+ uint64_t b = (uint32_t)multiplier; // & 0xFFFFFFFF;
+ uint64_t c = multiplicand >> 32;
+ uint64_t d = (uint32_t)multiplicand; // & 0xFFFFFFFF;
+
+ uint64_t ad = __emulu(a, d);
+ uint64_t bd = __emulu(b, d);
+
+ uint64_t adbc = ad + __emulu(b, c);
+ uint64_t adbc_carry = (adbc < ad); // ? 1 : 0;
+
+ // multiplier * multiplicand = product_hi * 2^64 + product_lo
+ uint64_t product_lo = bd + (adbc << 32);
+ uint64_t product_lo_carry = (product_lo < bd); // ? 1 : 0;
+ *high = __emulu(a, c) + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
+
+ return product_lo;
+#endif
+}
+
+uint64_t div128_to_64(uint64_t u1, uint64_t u0, uint64_t v, uint64_t * r)
+{
+ const uint64_t b = (1ULL << 32); // Number base (32 bits)
+ uint64_t un1, un0; // Norm. dividend LSD's
+ uint64_t vn1, vn0; // Norm. divisor digits
+ uint64_t q1, q0; // Quotient digits
+ uint64_t un64, un21, un10; // Dividend digit pairs
+ uint64_t rhat; // A remainder
+ int32_t s; // Shift amount for norm
+
+ // If overflow, set rem. to an impossible value,
+ // and return the largest possible quotient
+ if (u1 >= v)
+ {
+ *r = (uint64_t)-1;
+ return (uint64_t)-1;
+ }
+
+ // count leading zeros
+ s = clz64(v);
+ if (s > 0)
+ {
+ // Normalize divisor
+ v = v << s;
+ un64 = (u1 << s) | (u0 >> (64 - s));
+ un10 = u0 << s; // Shift dividend left
+ }
+ else
+ {
+ // Avoid undefined behavior of (u0 >> 64).
+ // The behavior is undefined if the right operand is
+ // negative, or greater than or equal to the length
+ // in bits of the promoted left operand.
+ un64 = u1;
+ un10 = u0;
+ }
+
+ // Break divisor up into two 32-bit digits
+ vn1 = v >> 32;
+ vn0 = v & 0xFFFFFFFF;
+
+ // Break right half of dividend into two digits
+ un1 = un10 >> 32;
+ un0 = un10 & 0xFFFFFFFF;
+
+ // Compute the first quotient digit, q1
+ q1 = un64 / vn1;
+ rhat = un64 - q1 * vn1;
+
+ while (q1 >= b || q1 * vn0 > b * rhat + un1)
+ {
+ q1 = q1 - 1;
+ rhat = rhat + vn1;
+ if (rhat >= b)
+ {
+ break;
+ }
+ }
+
+ // Multiply and subtract
+ un21 = un64 * b + un1 - q1 * v;
+
+ // Compute the second quotient digit
+ q0 = un21 / vn1;
+ rhat = un21 - q0 * vn1;
+
+ while (q0 >= b || q0 * vn0 > b * rhat + un0)
+ {
+ q0 = q0 - 1;
+ rhat = rhat + vn1;
+ if (rhat >= b)
+ {
+ break;
+ }
+ }
+
+ *r = (un21 * b + un0 - q0 * v) >> s;
+ return q1 * b + q0;
+}
diff --git a/src/common/maths.h b/src/common/maths.h
new file mode 100644
index 00000000..a6339d92
--- /dev/null
+++ b/src/common/maths.h
@@ -0,0 +1,5 @@
+#pragma once
+#include
+
+uint64_t mull128_u64(uint64_t x, uint64_t y, uint64_t * high);
+uint64_t div128_to_64(uint64_t u1, uint64_t u0, uint64_t v, uint64_t * r);
diff --git a/src/nxemu-core/file_format/nro.cpp b/src/nxemu-core/file_format/nro.cpp
index cda2b618..ea9b4c95 100644
--- a/src/nxemu-core/file_format/nro.cpp
+++ b/src/nxemu-core/file_format/nro.cpp
@@ -260,7 +260,7 @@ constexpr uint32_t Nro::PageAlignSize(uint32_t size)
{
pageBits = 12,
pageSize = 1ULL << pageBits,
- pageMask = pageSize,
+ pageMask = pageSize - 1,
};
return ((size + pageMask) & ~pageMask);
}
diff --git a/src/nxemu-cpu/arm64_registers.cpp b/src/nxemu-cpu/arm64_registers.cpp
new file mode 100644
index 00000000..35ab43cc
--- /dev/null
+++ b/src/nxemu-cpu/arm64_registers.cpp
@@ -0,0 +1,158 @@
+#include "arm64_registers.h"
+#include "dynarmic/interface/A64/a64.h"
+
+extern IModuleNotification * g_notify;
+
+A64Registers::A64Registers() :
+ m_tpidr_el0(0),
+ m_tpidrro_el0(0),
+ m_jit(nullptr)
+{
+}
+
+uint32_t A64Registers::Get32(IArm64Reg::Reg reg)
+{
+ if (reg >= IArm64Reg::Reg::W0 && reg <= IArm64Reg::Reg::W30)
+ {
+ return (uint32_t)m_jit->GetRegister((uint32_t)reg - (uint32_t)IArm64Reg::Reg::W0);
+ }
+ if (reg == IArm64Reg::Reg::WZR)
+ {
+ return 0;
+ }
+ if (reg >= IArm64Reg::Reg::PSTATE)
+ {
+ return m_jit->GetPstate();
+ }
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ return 0;
+}
+
+uint64_t A64Registers::Get64(IArm64Reg::Reg reg)
+{
+ if (reg >= IArm64Reg::Reg::X0 && reg <= IArm64Reg::Reg::X30)
+ {
+ return m_jit->GetRegister((uint32_t)reg - (uint32_t)IArm64Reg::Reg::X0);
+ }
+ if (reg == IArm64Reg::Reg::SP)
+ {
+ return m_jit->GetSP();
+ }
+ if (reg == IArm64Reg::Reg::XZR)
+ {
+ return 0;
+ }
+ if (reg == IArm64Reg::Reg::PC)
+ {
+ return m_jit->GetPC();
+ }
+ if (reg == IArm64Reg::Reg::TPIDR_EL0)
+ {
+ return m_tpidr_el0;
+ }
+ if (reg == IArm64Reg::Reg::TPIDRRO_EL0)
+ {
+ return m_tpidrro_el0;
+ }
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ return 0;
+}
+
+void A64Registers::Get128(IArm64Reg::Reg reg, uint64_t & hiValue, uint64_t & loValue)
+{
+ if (reg >= IArm64Reg::Reg::Q0 && reg <= IArm64Reg::Reg::Q31)
+ {
+ Dynarmic::A64::Vector v = m_jit->GetVector(((uint32_t)reg - (uint32_t)IArm64Reg::Reg::Q0));
+ hiValue = v[0];
+ loValue = v[1];
+ }
+ else
+ {
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ }
+}
+
+void A64Registers::Set32(IArm64Reg::Reg reg, uint32_t value)
+{
+ if (reg >= IArm64Reg::Reg::W0 && reg <= IArm64Reg::Reg::W30)
+ {
+ m_jit->SetRegister((uint32_t)reg - (uint32_t)IArm64Reg::Reg::W0, value);
+ }
+ else if (reg == IArm64Reg::Reg::PSTATE)
+ {
+ m_jit->SetPstate(value);
+ }
+ else
+ {
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ }
+}
+
+void A64Registers::Set64(IArm64Reg::Reg reg, uint64_t value)
+{
+ if (reg >= IArm64Reg::Reg::X0 && reg <= IArm64Reg::Reg::X30)
+ {
+ m_jit->SetRegister((uint32_t)reg - (uint32_t)IArm64Reg::Reg::X0, value);
+ }
+ else if (reg == IArm64Reg::Reg::SP)
+ {
+ m_jit->SetSP(value);
+ }
+ else if (reg == IArm64Reg::Reg::PC)
+ {
+ m_jit->SetPC(value);
+ }
+ else if (reg == IArm64Reg::Reg::TPIDRRO_EL0)
+ {
+ m_tpidrro_el0 = value;
+ }
+ else if (reg == IArm64Reg::Reg::TPIDR_EL0)
+ {
+ m_tpidr_el0 = value;
+ }
+ else
+ {
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ }
+}
+
+void A64Registers::Set128(IArm64Reg::Reg reg, uint64_t hiValue, uint64_t loValue)
+{
+ if (reg >= IArm64Reg::Reg::Q0 && reg <= IArm64Reg::Reg::Q31)
+ {
+ m_jit->SetVector(((uint32_t)reg - (uint32_t)IArm64Reg::Reg::Q0), {hiValue, loValue});
+ }
+ else if (reg >= IArm64Reg::Reg::V0 && reg <= IArm64Reg::Reg::V31)
+ {
+ m_jit->SetVector(((uint32_t)reg - (uint32_t)IArm64Reg::Reg::V0), {hiValue, loValue});
+ }
+ else
+ {
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ }
+}
+
+void A64Registers::SetFPCR(uint32_t value)
+{
+ m_jit->SetFpcr(value);
+}
+
+void A64Registers::SetFPSR(uint32_t value)
+{
+ m_jit->SetFpsr(value);
+}
+
+uint32_t A64Registers::GetFPCR() const
+{
+ return m_jit->GetFpcr();
+}
+
+uint32_t A64Registers::GetFPSR() const
+{
+ return m_jit->GetFpsr();
+}
+
+void A64Registers::SetJit(Dynarmic::A64::Jit * jit)
+{
+ m_jit = jit;
+}
diff --git a/src/nxemu-cpu/arm64_registers.h b/src/nxemu-cpu/arm64_registers.h
new file mode 100644
index 00000000..f6e00fee
--- /dev/null
+++ b/src/nxemu-cpu/arm64_registers.h
@@ -0,0 +1,43 @@
+#pragma once
+#include
+
+
+class ArmDynarmic64;
+
+namespace Dynarmic::A64
+{
+class Jit;
+}
+
+class A64Registers :
+ public IArm64Reg
+{
+ friend ArmDynarmic64;
+
+public:
+ A64Registers();
+
+ uint32_t Get32(IArm64Reg::Reg reg);
+ uint64_t Get64(IArm64Reg::Reg reg);
+ void Get128(IArm64Reg::Reg reg, uint64_t & hiValue, uint64_t & loValue);
+ uint32_t GetFPCR() const;
+ uint32_t GetFPSR() const;
+
+ void Set32(IArm64Reg::Reg reg, uint32_t value);
+ void Set64(IArm64Reg::Reg reg, uint64_t value);
+ void Set128(IArm64Reg::Reg reg, uint64_t hiValue, uint64_t loValue);
+ void SetFPCR(uint32_t value);
+ void SetFPSR(uint32_t value);
+
+ void SetJit(Dynarmic::A64::Jit * jit);
+
+private:
+ A64Registers(const A64Registers&) = delete;
+ A64Registers& operator=(const A64Registers&) = delete;
+
+ Dynarmic::A64::Jit * m_jit;
+
+ //CP15
+ uint64_t m_tpidr_el0; /* User RW Thread register. */
+ uint64_t m_tpidrro_el0; /* User RO Thread register. */
+};
diff --git a/src/nxemu-cpu/arm_dynarmic_64.cpp b/src/nxemu-cpu/arm_dynarmic_64.cpp
new file mode 100644
index 00000000..c3f2d1a2
--- /dev/null
+++ b/src/nxemu-cpu/arm_dynarmic_64.cpp
@@ -0,0 +1,246 @@
+#include "arm_dynarmic_64.h"
+#include "dynarmic/interface/exclusive_monitor.h"
+#include
+
+extern IModuleNotification * g_notify;
+
+ArmDynarmic64::ArmDynarmic64(Dynarmic::ExclusiveMonitor * monitor, ISwitchSystem & System, ICpuInfo & CpuInfo, uint32_t coreIndex) :
+ m_jit(nullptr),
+ m_system(System),
+ m_CpuInfo(CpuInfo),
+ m_OperatingSystem(System.OperatingSystem()),
+ m_monitor(monitor),
+ m_coreIndex(coreIndex)
+{
+ m_jit = MakeJit(monitor);
+ m_reg.SetJit(m_jit.get());
+}
+
+IArm64Executor::HaltReason ArmDynarmic64::Execute()
+{
+ m_jit->ClearExclusiveState();
+ Dynarmic::HaltReason Reason = m_jit->Run();
+ switch (Reason)
+ {
+ case Dynarmic::HaltReason::UserDefined3: return IArm64Executor::HaltReason::SupervisorCall;
+ }
+
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ return HaltReason::Stopped;
+}
+
+void ArmDynarmic64::InvalidateCacheRange(uint64_t addr, uint64_t size)
+{
+ m_jit->InvalidateCacheRange(addr, size);
+}
+
+void ArmDynarmic64::HaltExecution(HaltReason hr)
+{
+ switch (hr)
+ {
+ case HaltReason::SupervisorCall: m_jit->HaltExecution(Dynarmic::HaltReason::UserDefined3); break;
+ default:
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ }
+}
+
+std::unique_ptr ArmDynarmic64::MakeJit(Dynarmic::ExclusiveMonitor * monitor)
+{
+ Dynarmic::A64::UserConfig config;
+ config.callbacks = this;
+ config.page_table = nullptr; // reinterpret_cast(page_table->pointers.data());
+ config.page_table_address_space_bits = 27; //address_space_bits;
+ config.page_table_pointer_mask_bits = 2; // Common::PageTable::ATTRIBUTE_BITS;
+ config.silently_mirror_page_table = false;
+ config.absolute_offset_page_table = true;
+ config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
+ config.only_detect_misalignment_via_page_table_on_page_boundary = true;
+
+ config.fastmem_pointer = nullptr; //page_table->fastmem_arena;
+ config.fastmem_address_space_bits = 27; //address_space_bits;
+ config.silently_mirror_fastmem = false;
+
+ config.fastmem_exclusive_access = config.fastmem_pointer != nullptr;
+ config.recompile_on_exclusive_fastmem_failure = true;
+ config.processor_id = m_coreIndex;
+ config.global_monitor = monitor;
+
+ // System registers
+ config.tpidrro_el0 = &m_reg.m_tpidrro_el0;
+ config.tpidr_el0 = &m_reg.m_tpidr_el0;
+ config.dczid_el0 = 4;
+ config.ctr_el0 = 0x8444c004;
+ config.cntfrq_el0 = 0x124f800; //Hardware::CNTFREQ;
+
+ // Unpredictable instructions
+ config.define_unpredictable_behaviour = true;
+
+ // Timing
+ config.wall_clock_cntpct = true; //m_uses_wall_clock;
+ config.enable_cycle_counting = false; //!m_uses_wall_clock;
+
+ // Code cache size
+ config.code_cache_size = 0x20000000;
+ return std::make_unique(config);
+}
+
+std::uint8_t ArmDynarmic64::MemoryRead8(std::uint64_t vaddr)
+{
+ uint8_t Value;
+ if (m_CpuInfo.ReadMemory(vaddr, (uint8_t *)&Value, sizeof(Value)))
+ {
+ return Value;
+ }
+ return 0;
+}
+
+std::uint16_t ArmDynarmic64::MemoryRead16(std::uint64_t vaddr)
+{
+ uint16_t Value;
+ if (m_CpuInfo.ReadMemory(vaddr, (uint8_t *)&Value, sizeof(Value)))
+ {
+ return Value;
+ }
+ return 0;
+}
+
+std::uint32_t ArmDynarmic64::MemoryRead32(std::uint64_t vaddr)
+{
+ uint32_t Value;
+ if (m_CpuInfo.ReadMemory(vaddr, (uint8_t *)&Value, sizeof(Value)))
+ {
+ return Value;
+ }
+ return 0;
+}
+
+std::uint64_t ArmDynarmic64::MemoryRead64(std::uint64_t vaddr)
+{
+ uint64_t Value;
+ if (m_CpuInfo.ReadMemory(vaddr, (uint8_t *)&Value, sizeof(Value)))
+ {
+ return Value;
+ }
+ return 0;
+}
+
+Dynarmic::A64::Vector ArmDynarmic64::MemoryRead128(std::uint64_t vaddr)
+{
+ Dynarmic::A64::Vector Value;
+ if (m_CpuInfo.ReadMemory(vaddr, (uint8_t *)&Value, sizeof(Value)))
+ {
+ return Value;
+ }
+ return {0, 0};
+}
+
+void ArmDynarmic64::MemoryWrite8(std::uint64_t vaddr, std::uint8_t value)
+{
+ m_CpuInfo.WriteMemory(vaddr, &value, sizeof(value));
+}
+
+void ArmDynarmic64::MemoryWrite16(std::uint64_t vaddr, std::uint16_t value)
+{
+ m_CpuInfo.WriteMemory(vaddr, (const uint8_t *)&value, sizeof(value));
+}
+
+void ArmDynarmic64::MemoryWrite32(std::uint64_t vaddr, std::uint32_t value)
+{
+ m_CpuInfo.WriteMemory(vaddr, (const uint8_t *)&value, sizeof(value));
+}
+
+void ArmDynarmic64::MemoryWrite64(std::uint64_t vaddr, std::uint64_t value)
+{
+ m_CpuInfo.WriteMemory(vaddr, (const uint8_t *)&value, sizeof(value));
+}
+
+void ArmDynarmic64::MemoryWrite128(std::uint64_t vaddr, Dynarmic::A64::Vector value)
+{
+ m_CpuInfo.WriteMemory(vaddr, (const uint8_t *)&value, sizeof(value));
+}
+
+bool ArmDynarmic64::MemoryWriteExclusive8(std::uint64_t /*vaddr*/, std::uint8_t /*value*/, std::uint8_t /*expected*/)
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ return false;
+}
+
+bool ArmDynarmic64::MemoryWriteExclusive16(std::uint64_t /*vaddr*/, std::uint16_t /*value*/, std::uint16_t /*expected*/)
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ return false;
+}
+
+bool ArmDynarmic64::MemoryWriteExclusive32(std::uint64_t vaddr, std::uint32_t value, std::uint32_t /*expected*/)
+{
+ return m_CpuInfo.WriteMemory(vaddr, (const uint8_t *)&value, sizeof(value));
+}
+
+bool ArmDynarmic64::MemoryWriteExclusive64(std::uint64_t vaddr, std::uint64_t value, std::uint64_t /*expected*/)
+{
+ return m_CpuInfo.WriteMemory(vaddr, (const uint8_t *)&value, sizeof(value));
+}
+
+bool ArmDynarmic64::MemoryWriteExclusive128(std::uint64_t /*vaddr*/, Dynarmic::A64::Vector /*value*/, Dynarmic::A64::Vector /*expected*/)
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ return false;
+}
+
+bool ArmDynarmic64::IsReadOnlyMemory(std::uint64_t /*vaddr*/)
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ return false;
+}
+
+void ArmDynarmic64::InterpreterFallback(std::uint64_t /*pc*/, size_t /*num_instructions*/)
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+}
+
+void ArmDynarmic64::CallSVC(std::uint32_t swi)
+{
+ m_CpuInfo.ServiceCall(swi);
+}
+
+void ArmDynarmic64::ExceptionRaised(std::uint64_t /*pc*/, Dynarmic::A64::Exception /*exception*/)
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+}
+
+void ArmDynarmic64::DataCacheOperationRaised(Dynarmic::A64::DataCacheOperation /*op*/, std::uint64_t /*value*/)
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+}
+
+void ArmDynarmic64::InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation /*op*/, std::uint64_t /*value*/)
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+}
+
+void ArmDynarmic64::InstructionSynchronizationBarrierRaised()
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+}
+
+void ArmDynarmic64::AddTicks(std::uint64_t /*ticks*/)
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+}
+
+std::uint64_t ArmDynarmic64::GetTicksRemaining()
+{
+ g_notify->BreakPoint(__FILE__, __LINE__);
+ return 0;
+}
+
+std::uint64_t ArmDynarmic64::GetCNTPCT()
+{
+ const uint64_t BASE_CLOCK_RATE = 1019215872; // Switch clock speed - 1020MHz
+ const uint64_t COUNT_FREQ = 19200000;
+
+ uint64_t ticks = m_CpuInfo.CpuTicks();
+ uint64_t hi, rem;
+ uint64_t lo = mull128_u64(ticks, COUNT_FREQ, &hi);
+ return div128_to_64(hi, lo, BASE_CLOCK_RATE, &rem);
+}
diff --git a/src/nxemu-cpu/arm_dynarmic_64.h b/src/nxemu-cpu/arm_dynarmic_64.h
new file mode 100644
index 00000000..0755ff3c
--- /dev/null
+++ b/src/nxemu-cpu/arm_dynarmic_64.h
@@ -0,0 +1,61 @@
+#pragma once
+#include "dynarmic/interface/A64/a64.h"
+#include "arm64_registers.h"
+#include "cpu_manager.h"
+
+class ArmDynarmic64 :
+ public IArm64Executor,
+ private Dynarmic::A64::UserCallbacks
+{
+public:
+ ArmDynarmic64(Dynarmic::ExclusiveMonitor * monitor, ISwitchSystem & System, ICpuInfo & CpuInfo, uint32_t coreIndex);
+
+ IArm64Reg & Reg(void) { return m_reg; }
+
+ //IArm64Executor
+ HaltReason Execute(void);
+ void InvalidateCacheRange(uint64_t addr, uint64_t size);
+ void HaltExecution(HaltReason hr);
+
+private:
+ ArmDynarmic64() = delete;
+ ArmDynarmic64(const ArmDynarmic64 &) = delete;
+ ArmDynarmic64 & operator=(const ArmDynarmic64 &) = delete;
+
+ std::unique_ptr MakeJit(Dynarmic::ExclusiveMonitor * monitor);
+
+ //Dynarmic::A64::UserCallbacks
+ std::uint8_t MemoryRead8(std::uint64_t vaddr);
+ std::uint16_t MemoryRead16(std::uint64_t vaddr);
+ std::uint32_t MemoryRead32(std::uint64_t vaddr);
+ std::uint64_t MemoryRead64(std::uint64_t vaddr);
+ Dynarmic::A64::Vector MemoryRead128(std::uint64_t vaddr);
+ void MemoryWrite8(std::uint64_t vaddr, std::uint8_t value);
+ void MemoryWrite16(std::uint64_t vaddr, std::uint16_t value);
+ void MemoryWrite32(std::uint64_t vaddr, std::uint32_t value);
+ void MemoryWrite64(std::uint64_t vaddr, std::uint64_t value);
+ void MemoryWrite128(std::uint64_t vaddr, Dynarmic::A64::Vector value);
+ bool MemoryWriteExclusive8(std::uint64_t /*vaddr*/, std::uint8_t /*value*/, std::uint8_t /*expected*/);
+ bool MemoryWriteExclusive16(std::uint64_t /*vaddr*/, std::uint16_t /*value*/, std::uint16_t /*expected*/);
+ bool MemoryWriteExclusive32(std::uint64_t /*vaddr*/, std::uint32_t /*value*/, std::uint32_t /*expected*/);
+ bool MemoryWriteExclusive64(std::uint64_t /*vaddr*/, std::uint64_t /*value*/, std::uint64_t /*expected*/);
+ bool MemoryWriteExclusive128(std::uint64_t /*vaddr*/, Dynarmic::A64::Vector /*value*/, Dynarmic::A64::Vector /*expected*/);
+ bool IsReadOnlyMemory(std::uint64_t /*vaddr*/);
+ void InterpreterFallback(std::uint64_t pc, size_t num_instructions);
+ void CallSVC(std::uint32_t swi);
+ void ExceptionRaised(std::uint64_t pc, Dynarmic::A64::Exception exception);
+ void DataCacheOperationRaised(Dynarmic::A64::DataCacheOperation /*op*/, std::uint64_t /*value*/);
+ void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation /*op*/, std::uint64_t /*value*/);
+ void InstructionSynchronizationBarrierRaised();
+ void AddTicks(std::uint64_t ticks);
+ std::uint64_t GetTicksRemaining();
+ std::uint64_t GetCNTPCT();
+
+ std::unique_ptr m_jit{};
+ ISwitchSystem & m_system;
+ ICpuInfo & m_CpuInfo;
+ IOperatingSystem & m_OperatingSystem;
+ Dynarmic::ExclusiveMonitor * m_monitor;
+ A64Registers m_reg;
+ uint32_t m_coreIndex;
+};
diff --git a/src/nxemu-cpu/cpu_manager.cpp b/src/nxemu-cpu/cpu_manager.cpp
index eb19a186..b79143ad 100644
--- a/src/nxemu-cpu/cpu_manager.cpp
+++ b/src/nxemu-cpu/cpu_manager.cpp
@@ -1,4 +1,6 @@
#include "cpu_manager.h"
+#include "arm_dynarmic_64.h"
+#include "exclusive_monitor_interface.h"
CpuManager::CpuManager(ISwitchSystem & system) :
m_system(system)
@@ -14,20 +16,30 @@ bool CpuManager::Initialize(void)
return true;
}
-IExclusiveMonitor * CpuManager::CreateExclusiveMonitor(IMemory & /*memory*/, uint32_t /*processorCount*/)
+IExclusiveMonitor * CpuManager::CreateExclusiveMonitor(IMemory & memory, uint32_t processorCount)
{
- return nullptr;
+ if (m_exclusiveMonitor.get() != nullptr)
+ {
+ return nullptr;
+ }
+ m_exclusiveMonitor.reset(std::make_unique(memory, processorCount).release());
+ return m_exclusiveMonitor.get();
};
-void CpuManager::DestroyExclusiveMonitor(IExclusiveMonitor * /*monitor*/)
+void CpuManager::DestroyExclusiveMonitor(IExclusiveMonitor * monitor)
{
+ if (m_exclusiveMonitor.get() == monitor)
+ {
+ m_exclusiveMonitor.reset(nullptr);
+ }
}
IArm64Executor * CpuManager::CreateArm64Executor(IExclusiveMonitor * monitor, ICpuInfo & info, uint32_t coreIndex)
{
- return nullptr;
+ return new ArmDynarmic64(monitor == m_exclusiveMonitor.get() ? m_exclusiveMonitor.get() : nullptr, m_system, info, coreIndex);
}
void CpuManager::DestroyArm64Executor(IArm64Executor * executor)
{
+ delete (ArmDynarmic64 *)executor;
}
diff --git a/src/nxemu-cpu/cpu_manager.h b/src/nxemu-cpu/cpu_manager.h
index 8051a7de..c347a603 100644
--- a/src/nxemu-cpu/cpu_manager.h
+++ b/src/nxemu-cpu/cpu_manager.h
@@ -23,5 +23,6 @@ private:
CpuManager(const CpuManager &) = delete;
CpuManager & operator=(const CpuManager &) = delete;
+ std::unique_ptr m_exclusiveMonitor;
ISwitchSystem & m_system;
};
diff --git a/src/nxemu-cpu/dynarmic/backend/exception_handler_windows.cpp b/src/nxemu-cpu/dynarmic/backend/exception_handler_windows.cpp
index 719c0075..5131f32c 100644
--- a/src/nxemu-cpu/dynarmic/backend/exception_handler_windows.cpp
+++ b/src/nxemu-cpu/dynarmic/backend/exception_handler_windows.cpp
@@ -6,7 +6,7 @@
#include
#if defined(MCL_ARCHITECTURE_X86_64)
-# include "dynarmic/backend/x64/exception_handler_windows.cpp"
+# include "dynarmic/backend/x64/exception_handler_windows_x64.cpp"
#elif defined(MCL_ARCHITECTURE_ARM64)
# include "dynarmic/backend/exception_handler_generic.cpp"
#else
diff --git a/src/nxemu-cpu/dynarmic/backend/x64/exception_handler_windows.cpp b/src/nxemu-cpu/dynarmic/backend/x64/exception_handler_windows_x64.cpp
similarity index 99%
rename from src/nxemu-cpu/dynarmic/backend/x64/exception_handler_windows.cpp
rename to src/nxemu-cpu/dynarmic/backend/x64/exception_handler_windows_x64.cpp
index a7f96433..d207bbf1 100644
--- a/src/nxemu-cpu/dynarmic/backend/x64/exception_handler_windows.cpp
+++ b/src/nxemu-cpu/dynarmic/backend/x64/exception_handler_windows_x64.cpp
@@ -3,7 +3,6 @@
* SPDX-License-Identifier: 0BSD
*/
-#define WIN32_LEAN_AND_MEAN
#include
#include
diff --git a/src/nxemu-cpu/dynarmic/interface/exclusive_monitor.h b/src/nxemu-cpu/dynarmic/interface/exclusive_monitor.h
index 48136758..b8d3ed7b 100644
--- a/src/nxemu-cpu/dynarmic/interface/exclusive_monitor.h
+++ b/src/nxemu-cpu/dynarmic/interface/exclusive_monitor.h
@@ -12,7 +12,7 @@
#include
#include
-#include
+#include "dynarmic/common/spin_lock.h"
namespace Dynarmic {
diff --git a/src/nxemu-cpu/exclusive_monitor_interface.cpp b/src/nxemu-cpu/exclusive_monitor_interface.cpp
new file mode 100644
index 00000000..b52afbd4
--- /dev/null
+++ b/src/nxemu-cpu/exclusive_monitor_interface.cpp
@@ -0,0 +1,59 @@
+#include "exclusive_monitor_interface.h"
+
+ExclusiveMonitor::ExclusiveMonitor(IMemory & /*memory*/, uint32_t processorCount) :
+ Dynarmic::ExclusiveMonitor(processorCount)
+{
+}
+
+uint8_t ExclusiveMonitor::ExclusiveRead8(uint32_t /*coreIndex*/, uint64_t /*addr*/)
+{
+ __debugbreak();
+ return 0;
+}
+
+uint16_t ExclusiveMonitor::ExclusiveRead16(uint32_t /*coreIndex*/, uint64_t /*addr*/)
+{
+ __debugbreak();
+ return 0;
+}
+
+uint32_t ExclusiveMonitor::ExclusiveRead32(uint32_t /*coreIndex*/, uint64_t /*addr*/)
+{
+ __debugbreak();
+ return 0;
+}
+
+uint64_t ExclusiveMonitor::ExclusiveRead64(uint32_t /*coreIndex*/, uint64_t /*addr*/)
+{
+ __debugbreak();
+ return 0;
+}
+
+void ExclusiveMonitor::ClearExclusive(uint32_t /*coreIndex*/)
+{
+ __debugbreak();
+}
+
+bool ExclusiveMonitor::ExclusiveWrite8(uint32_t /*coreIndex*/, uint64_t /*addr*/, uint8_t /*value*/)
+{
+ __debugbreak();
+ return false;
+}
+
+bool ExclusiveMonitor::ExclusiveWrite16(uint32_t /*coreIndex*/, uint64_t /*addr*/, uint16_t /*value*/)
+{
+ __debugbreak();
+ return false;
+}
+
+bool ExclusiveMonitor::ExclusiveWrite32(uint32_t /*coreIndex*/, uint64_t /*addr*/, uint32_t /*value*/)
+{
+ __debugbreak();
+ return false;
+}
+
+bool ExclusiveMonitor::ExclusiveWrite64(uint32_t /*coreIndex*/, uint64_t /*addr*/, uint64_t /*value*/)
+{
+ __debugbreak();
+ return false;
+}
\ No newline at end of file
diff --git a/src/nxemu-cpu/exclusive_monitor_interface.h b/src/nxemu-cpu/exclusive_monitor_interface.h
new file mode 100644
index 00000000..c58a6122
--- /dev/null
+++ b/src/nxemu-cpu/exclusive_monitor_interface.h
@@ -0,0 +1,30 @@
+#pragma once
+#include
+#include "dynarmic/interface/exclusive_monitor.h"
+
+__interface IMemory;
+
+class ExclusiveMonitor :
+ public Dynarmic::ExclusiveMonitor,
+ public IExclusiveMonitor
+{
+public:
+ ExclusiveMonitor(IMemory & memory, uint32_t processorCount);
+
+ // IExclusiveMonitor
+ uint8_t ExclusiveRead8(uint32_t coreIndex, uint64_t addr);
+ uint16_t ExclusiveRead16(uint32_t coreIndex, uint64_t addr);
+ uint32_t ExclusiveRead32(uint32_t coreIndex, uint64_t addr);
+ uint64_t ExclusiveRead64(uint32_t coreIndex, uint64_t addr);
+ void ClearExclusive(uint32_t coreIndex);
+
+ bool ExclusiveWrite8(uint32_t coreIndex, uint64_t vaddr, uint8_t value);
+ bool ExclusiveWrite16(uint32_t coreIndex, uint64_t vaddr, uint16_t value);
+ bool ExclusiveWrite32(uint32_t coreIndex, uint64_t vaddr, uint32_t value);
+ bool ExclusiveWrite64(uint32_t coreIndex, uint64_t vaddr, uint64_t value);
+
+private:
+ ExclusiveMonitor() = delete;
+ ExclusiveMonitor(const ExclusiveMonitor &) = delete;
+ ExclusiveMonitor & operator=(const ExclusiveMonitor &) = delete;
+};
\ No newline at end of file
diff --git a/src/nxemu-cpu/nxemu-cpu.vcxproj b/src/nxemu-cpu/nxemu-cpu.vcxproj
index bed4b639..192d9838 100644
--- a/src/nxemu-cpu/nxemu-cpu.vcxproj
+++ b/src/nxemu-cpu/nxemu-cpu.vcxproj
@@ -28,16 +28,358 @@
$(SolutionDir)modules\$(Platform)\cpu\
+
+ $(SolutionDir)src\3rd_party\SoftFloat-3e\source\include;$(SolutionDir)external\boost;$(SolutionDir)external\mcl\include;$(SolutionDir)external\fmt\include;$(SolutionDir)external\robin-map\include;$(SolutionDir)external\xbyak;$(SolutionDir)external\zydis\include;$(SolutionDir)external\oaknut\include;$(SolutionDir)external\zycore\include;%(AdditionalIncludeDirectories)
+ NOMINMAX;DYNARMIC_ENABLE_CPU_FEATURE_DETECTION=1;MCL_IGNORE_ASSERTS=1;FMT_STATIC_LINK;FMT_USE_WINDOWS_H=0;FMT_USE_USER_DEFINED_LITERALS=1;ARCHITECTURE_x86_64=1;BOOST_ASIO_DISABLE_CONCEPTS;_HAS_DEPRECATED_RESULT_OF;_WIN32_WINNT=0x0A00;WINVER=0x0A00;BOOST_ALL_NO_LIB;ZYDIS_STATIC_BUILD;ZYCORE_STATIC_BUILD;%(PreprocessorDefinitions)
+ /bigobj %(AdditionalOptions)
+
- "$(SolutionDir)src\script\update_version.cmd" "$(Configuration)" "$(Platform)" "$(SolutionDir)src\nxemu-cpu\Version.h.in" "$(SolutionDir)src\nxemu-cpu\Version.h"
+ "$(SolutionDir)src\script\update_version.cmd" "$(Configuration)" "$(Platform)" "$(SolutionDir)src\nxemu-cpu\version.h.in" "$(SolutionDir)src\nxemu-cpu\version.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+ {d58bdfc6-1f1e-4c55-9296-1c2411b0fda7}
+
+
+ {a059b52a-fb13-4060-ac89-128570938d5d}
+
+
+ {9dec236b-f924-4166-a1b1-002f3bf8f0ec}
+
+
+ {ec81be93-8316-4db6-8a26-b13fb5b13848}
+
diff --git a/src/nxemu-cpu/nxemu-cpu.vcxproj.filters b/src/nxemu-cpu/nxemu-cpu.vcxproj.filters
index 10704acb..9c3ebaf5 100644
--- a/src/nxemu-cpu/nxemu-cpu.vcxproj.filters
+++ b/src/nxemu-cpu/nxemu-cpu.vcxproj.filters
@@ -13,18 +13,1094 @@
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+ {6fe1b415-8781-4421-9dfe-d48957319e49}
+
+
+ {c88dfe24-2d70-47de-a7b5-2c6a2e0cace5}
+
+
+ {4b8a631a-24ce-4963-aa84-a7e67d1ef227}
+
+
+ {977f2883-ae10-4774-9854-1e19465d5b5c}
+
+
+ {92ef4596-d0aa-4a7c-a010-bc788dceceed}
+
+
+ {00f75cc0-5e43-4c9d-842a-b43865698947}
+
+
+ {6b94035a-c04d-4885-ba9d-db6a9782926d}
+
+
+ {413de2b6-6bb7-4f97-866b-6b3f2d85b6d7}
+
+
+ {48f30bc7-3e27-4783-8cfe-ce35dd58127a}
+
+
+ {eb5deac5-dc82-49c8-8aef-bea30d9d10b4}
+
+
+ {cafc2941-2502-436c-8f43-9f66753dfe0f}
+
+
+ {9ae49ef6-f5e7-4587-9e5c-337185fa6fd8}
+
+
+ {52ed0f4b-0a53-406c-997f-2cffbf437b0a}
+
+
+ {6b1f2272-e81c-47ef-b98e-9ffbbf409f1a}
+
+
+ {516ad251-3d13-48ec-ae4c-5f8e01eff255}
+
+
+ {90bbb1e3-f28b-475e-b842-647f0fa5c2d1}
+
+
+ {6d828a1a-63c8-4407-a779-72cc58b82095}
+
+
+ {b34354f2-f201-4400-80df-10731b447c56}
+
+
+ {9ce1f9ad-463e-40ec-a145-f4a49608f544}
+
+
+ {ad3fec48-f4b5-4381-b05f-e3f54e610bd1}
+
+
+ {0cff058d-98b1-4db6-bebc-dadbd4f35b61}
+
+
+ {e41648d6-3929-41ff-8451-ce9822a22314}
+
+
+ {ec436750-23bf-4a7e-9346-4591e66488af}
+
+
+ {c58f04b2-b28e-45eb-a14b-b20e5c9ec21e}
+
+
+ {8bc227c2-8dda-4c11-ab16-e51a483c744f}
+
+
+ {590b91e7-d597-4144-8f90-34899a731f18}
+
+
+ {b7462fcf-5894-4ab2-a2c2-a284b0bb4659}
+
+
+ {01b8c635-e1d3-4700-9b8f-ccf67aabc1d9}
+
+
+ {de907679-0e9f-4797-b19b-4d1d5599d3a1}
+
+
+ {f21f9727-c7f5-4f42-b5c8-3ea9db64a403}
+
+
+ {3172edaa-db89-4774-bd79-57f957c02631}
+
+
+ {ca01dfd5-4930-427d-a511-eea5d21e2065}
+
+
+ {95c8b57d-a9de-4c18-8232-43ed586e652a}
+
+
+ {aa0ac488-1996-44bb-9d37-fa751c58aa85}
+
+
+ {adba25c9-791e-4946-b426-1e8b1b519150}
+
+
+ {c62d15c2-1f39-432c-86a0-bc174b6c205e}
+
+
+ {6398325c-1e07-4096-9bad-96f8ff57185d}
+
+
+ Plugin Spec
+
+
+ Plugin Spec
+
+
+ Header Files
+
+
+ Header Files\interface\A64
+
+
+ Header Files\interface\A64
+
+
+ Header Files\interface
+
+
+ Header Files\interface
+
+
+ Header Files\backend
+
+
+ Header Files\backend
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\arm64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\backend\x64
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common
+
+
+ Header Files\common\crypto
+
+
+ Header Files\common\crypto
+
+
+ Header Files\common\crypto
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\common\fp\op
+
+
+ Header Files\frontend
+
+
+ Header Files\frontend\A32
+
+
+ Header Files\frontend\A32
+
+
+ Header Files\frontend\A32
+
+
+ Header Files\frontend\A32
+
+
+ Header Files\frontend\A32
+
+
+ Header Files\frontend\A32
+
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A32\translate
+
+
+ Header Files\frontend\A32\translate
+
+
+ Header Files\frontend\A32\translate
+
+
+ Header Files\frontend\A64
+
+
+ Header Files\frontend\A64
+
+
+ Header Files\frontend\A64
+
+
+ Header Files\frontend\A64\decoder
+
+
+ Header Files\frontend\A64\translate
+
+
+ Header Files\frontend\A64\translate\impl
+
+
+ Header Files\frontend\decoder
+
+
+ Header Files\frontend\decoder
+
+
+ Header Files\interface
+
+
+ Header Files\interface\A32
+
+
+ Header Files\interface\A32
+
+
+ Header Files\interface\A32
+
+
+ Header Files\interface\A32
+
+
+ Header Files\interface\A32
+
+
+ Header Files\ir
+
+
+ Header Files\ir
+
+
+ Header Files\ir
+
+
+ Header Files\ir
+
+
+ Header Files\ir
+
+
+ Header Files\ir
+
+
+ Header Files\ir
+
+
+ Header Files\ir
+
+
+ Header Files\ir
+
+
+ Header Files\ir
+
+
+ Header Files\ir\opt
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
Source Files
Source Files
+
+ Source Files\dynarmic\backend
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\dynarmic\backend\x64
+
+
+ Source Files\common
+
+
+ Source Files\common
+
+
+ Source Files\common
+
+
+ Source Files\common
+
+
+ Source Files\common
+
+
+ Source Files\common\crypto
+
+
+ Source Files\common\crypto
+
+
+ Source Files\common\crypto
+
+
+ Source Files\common\fp
+
+
+ Source Files\common\fp
+
+
+ Source Files\common\fp
+
+
+ Source Files\common\fp
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\common\fp\op
+
+
+ Source Files\frontend
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate\impl
+
+
+ Source Files\frontend\A32\translate
+
+
+ Source Files\frontend\A32\translate
+
+
+ Source Files\frontend\A32\translate
+
+
+ Source Files\frontend\A32\translate
+
+
+ Source Files\frontend\A32
+
+
+ Source Files\frontend\A32
+
+
+ Source Files\frontend\A32
+
+
+ Source Files\frontend\A64
+
+
+ Source Files\frontend\A64
+
+
+ Source Files\frontend\A64
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ Source Files\frontend\A64\translate
+
+
+ ir
+
+
+ ir
+
+
+ ir
+
+
+ ir
+
+
+ ir
+
+
+ ir
+
+
+ ir
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ ir\opt
+
+
+ Source Files
+
+
+ Source Files
+
-
- Header Files
-
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A32\decoder
+
+
+ Header Files\frontend\A64\decoder
+
+
+ Source Files\dynarmic\backend\x64
+
\ No newline at end of file
diff --git a/src/nxemu-cpu/Version.h.in b/src/nxemu-cpu/version.h.in
similarity index 100%
rename from src/nxemu-cpu/Version.h.in
rename to src/nxemu-cpu/version.h.in
diff --git a/src/nxemu-module-spec/cpu.h b/src/nxemu-module-spec/cpu.h
index 88016fef..e9d6211c 100644
--- a/src/nxemu-module-spec/cpu.h
+++ b/src/nxemu-module-spec/cpu.h
@@ -1,6 +1,42 @@
#pragma once
#include "base.h"
+__interface IArm64Reg
+{
+ // clang-format off
+ enum class Reg
+ {
+ INVALID,
+ W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, W16, W17, W18, W19, W20, W21, W22, W23, W24, W25, W26, W27, W28, W29, W30, WZR,
+ X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, XZR,
+ V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31,
+ B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15, B16, B17, B18, B19, B20, B21, B22, B23, B24, B25, B26, B27, B28, B29, B30, B31,
+ H0, H1, H2, H3, H4, H5, H6, H7, H8, H9, H10, H11, H12, H13, H14, H15, H16, H17, H18, H19, H20, H21, H22, H23, H24, H25, H26, H27, H28, H29, H30, H31,
+ S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31,
+ D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, Q16, Q17, Q18, Q19, Q20, Q21, Q22, Q23, Q24, Q25, Q26, Q27, Q28, Q29, Q30, Q31,
+ WSP, SP, PC, PSTATE, TPIDR_EL0, TPIDRRO_EL0,
+
+ //Alias
+ FP = X29,
+ LR = X30,
+ };
+ // clang-format on
+
+ uint32_t Get32(Reg reg) = 0;
+ uint64_t Get64(Reg reg) = 0;
+ void Get128(Reg reg, uint64_t & hiValue, uint64_t & loValue) = 0;
+ uint32_t GetFPCR() const = 0;
+ uint32_t GetFPSR() const = 0;
+
+ void Set32(Reg reg, uint32_t value) = 0;
+ void Set64(Reg reg, uint64_t value) = 0;
+ void Set128(Reg reg, uint64_t hiValue, uint64_t loValue) = 0;
+
+ void SetFPCR(uint32_t value) = 0;
+ void SetFPSR(uint32_t value) = 0;
+};
+
__interface IArm64Executor
{
enum class HaltReason
@@ -9,7 +45,10 @@ __interface IArm64Executor
SupervisorCall,
};
+ IArm64Reg & Reg(void) = 0;
HaltReason Execute(void) = 0;
+ void InvalidateCacheRange(uint64_t addr, uint64_t size) = 0;
+ void HaltExecution(HaltReason hr) = 0;
};
__interface IMemory
@@ -18,6 +57,10 @@ __interface IMemory
__interface ICpuInfo
{
+ uint64_t & CpuTicks() = 0;
+ void ServiceCall(uint32_t index) = 0;
+ bool ReadMemory(uint64_t addr, uint8_t * buffer, uint32_t len) = 0;
+ bool WriteMemory(uint64_t addr, const uint8_t * buffer, uint32_t len) = 0;
};
__interface IExclusiveMonitor
@@ -28,10 +71,10 @@ __interface IExclusiveMonitor
uint64_t ExclusiveRead64(uint32_t coreIndex, uint64_t addr) = 0;
void ClearExclusive(uint32_t coreIndex) = 0;
- bool ExclusiveWrite8(uint32_t coreIndex, uint64_t vaddr, uint8_t value) = 0;
- bool ExclusiveWrite16(uint32_t coreIndex, uint64_t vaddr, uint16_t value) = 0;
- bool ExclusiveWrite32(uint32_t coreIndex, uint64_t vaddr, uint32_t value) = 0;
- bool ExclusiveWrite64(uint32_t coreIndex, uint64_t vaddr, uint64_t value) = 0;
+ bool ExclusiveWrite8(uint32_t coreIndex, uint64_t addr, uint8_t value) = 0;
+ bool ExclusiveWrite16(uint32_t coreIndex, uint64_t addr, uint16_t value) = 0;
+ bool ExclusiveWrite32(uint32_t coreIndex, uint64_t addr, uint32_t value) = 0;
+ bool ExclusiveWrite64(uint32_t coreIndex, uint64_t addr, uint64_t value) = 0;
};
__interface ICpu
diff --git a/src/nxemu-os/core/arm/cpu_module.cpp b/src/nxemu-os/core/arm/cpu_module.cpp
index 99f58214..c26524e7 100644
--- a/src/nxemu-os/core/arm/cpu_module.cpp
+++ b/src/nxemu-os/core/arm/cpu_module.cpp
@@ -16,6 +16,33 @@ public:
{
}
+ uint32_t svn()
+ {
+ return m_svn;
+ }
+
+ uint64_t & CpuTicks()
+ {
+ UNIMPLEMENTED();
+ static uint64_t ticks = 0;
+ return ticks;
+ }
+
+ void ServiceCall(uint32_t index)
+ {
+ m_svn = index;
+ m_arm64Executor->HaltExecution(IArm64Executor::HaltReason::SupervisorCall);
+ }
+
+ bool ReadMemory(uint64_t addr, uint8_t * Buffer, uint32_t Len)
+ {
+ return m_memory.ReadBlock(addr, Buffer, Len);
+ }
+
+ bool WriteMemory(uint64_t addr, const uint8_t * buffer, uint32_t len)
+ {
+ return m_memory.WriteBlock(addr, buffer, len);
+ }
IArm64Executor *& m_arm64Executor;
Kernel::KProcess * m_process{};
@@ -73,36 +100,98 @@ HaltReason ArmCpuModule::StepThread(Kernel::KThread * thread)
void ArmCpuModule::GetContext(Kernel::Svc::ThreadContext & ctx) const
{
- UNIMPLEMENTED();
+ if (m_arm64Executor != nullptr)
+ {
+ IArm64Reg & reg = m_arm64Executor->Reg();
+ for (size_t i = 0; i < 29; i++)
+ {
+ ctx.r[i] = reg.Get64((IArm64Reg::Reg)(((uint32_t)IArm64Reg::Reg::X0) + i));
+ }
+ ctx.fp = reg.Get64(IArm64Reg::Reg::FP);
+ ctx.lr = reg.Get64(IArm64Reg::Reg::LR);
+
+ ctx.sp = reg.Get64(IArm64Reg::Reg::SP);
+ ctx.pc = reg.Get64(IArm64Reg::Reg::PC);
+ ctx.pstate = reg.Get32(IArm64Reg::Reg::PSTATE);
+ for (size_t i = 0; i < 32; i++)
+ {
+ reg.Get128((IArm64Reg::Reg)(((uint32_t)IArm64Reg::Reg::Q0) + i), ctx.v[i][1], ctx.v[i][0]);
+ }
+ ctx.fpcr = reg.GetFPCR();
+ ctx.fpsr = reg.GetFPSR();
+ ctx.tpidr = reg.Get64(IArm64Reg::Reg::TPIDR_EL0);
+ }
+ else
+ {
+ UNIMPLEMENTED();
+ }
}
void ArmCpuModule::SetContext(const Kernel::Svc::ThreadContext & ctx)
{
- UNIMPLEMENTED();
+ if (m_arm64Executor != nullptr)
+ {
+ IArm64Reg & reg = m_arm64Executor->Reg();
+ for (size_t i = 0; i < 29; i++)
+ {
+ reg.Set64((IArm64Reg::Reg)(((uint32_t)IArm64Reg::Reg::X0) + i), ctx.r[i]);
+ }
+ reg.Set64(IArm64Reg::Reg::FP, ctx.fp);
+ reg.Set64(IArm64Reg::Reg::LR, ctx.lr);
+ reg.Set64(IArm64Reg::Reg::SP, ctx.sp);
+ reg.Set64(IArm64Reg::Reg::PC, ctx.pc);
+ reg.Set32(IArm64Reg::Reg::PSTATE, ctx.pstate);
+ for (size_t i = 0; i < 32; i++)
+ {
+ reg.Set128((IArm64Reg::Reg)(((uint32_t)IArm64Reg::Reg::Q0) + i), ctx.v[i][1], ctx.v[i][0]);
+ }
+ reg.SetFPCR(ctx.fpcr);
+ reg.SetFPSR(ctx.fpsr);
+ reg.Set64(IArm64Reg::Reg::TPIDR_EL0, ctx.tpidr);
+ }
+ else
+ {
+ UNIMPLEMENTED();
+ }
}
void ArmCpuModule::SetTpidrroEl0(u64 value)
{
- UNIMPLEMENTED();
+ if (m_arm64Executor != nullptr)
+ {
+ IArm64Reg & reg = m_arm64Executor->Reg();
+ reg.Set64(IArm64Reg::Reg::TPIDRRO_EL0, value);
+ }
+ else
+ {
+ UNIMPLEMENTED();
+ }
}
void ArmCpuModule::GetSvcArguments(std::span args) const
{
- UNIMPLEMENTED();
+ IArm64Reg & reg = m_arm64Executor->Reg();
+ for (size_t i = 0; i < 8; i++)
+ {
+ args[i] = reg.Get64((IArm64Reg::Reg)(((uint32_t)IArm64Reg::Reg::X0) + i));
+ }
}
void ArmCpuModule::SetSvcArguments(std::span args)
{
- UNIMPLEMENTED();
+ IArm64Reg & reg = m_arm64Executor->Reg();
+ for (size_t i = 0; i < 8; i++)
+ {
+ reg.Set64((IArm64Reg::Reg)(((uint32_t)IArm64Reg::Reg::X0) + i), args[i]);
+ }
}
u32 ArmCpuModule::GetSvcNumber() const
{
- UNIMPLEMENTED();
- return 0;
+ return m_cb->svn();
}
-void ArmCpuModule::SignalInterrupt(Kernel::KThread* thread)
+void ArmCpuModule::SignalInterrupt(Kernel::KThread * thread)
{
UNIMPLEMENTED();
}
@@ -114,7 +203,14 @@ void ArmCpuModule::ClearInstructionCache()
void ArmCpuModule::InvalidateCacheRange(u64 addr, std::size_t size)
{
- UNIMPLEMENTED();
+ if (m_arm64Executor != nullptr)
+ {
+ m_arm64Executor->InvalidateCacheRange(addr, size);
+ }
+ else
+ {
+ UNIMPLEMENTED();
+ }
}
const Kernel::DebugWatchpoint * ArmCpuModule::HaltedWatchpoint() const
diff --git a/src/nxemu-os/core/hle/service/am/frontend/applets.cpp b/src/nxemu-os/core/hle/service/am/frontend/applets.cpp
index e7d244e9..28044b30 100644
--- a/src/nxemu-os/core/hle/service/am/frontend/applets.cpp
+++ b/src/nxemu-os/core/hle/service/am/frontend/applets.cpp
@@ -99,7 +99,6 @@ void FrontendAppletHolder::SetCurrentAppletId(AppletId applet_id) {
}
void FrontendAppletHolder::SetDefaultAppletsIfMissing() {
- UNIMPLEMENTED();
}
void FrontendAppletHolder::ClearAll() {