diff options
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 21 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.h | 5 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_cp15.cpp | 81 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_cp15.h | 126 |
4 files changed, 89 insertions, 144 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 9bc86e3b9..e7456a8c3 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -50,7 +50,8 @@ public: | |||
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | void InterpreterFallback(u32 pc, std::size_t num_instructions) override { | 52 | void InterpreterFallback(u32 pc, std::size_t num_instructions) override { |
| 53 | UNIMPLEMENTED(); | 53 | UNIMPLEMENTED_MSG("This should never happen, pc = {:08X}, code = {:08X}", pc, |
| 54 | MemoryReadCode(pc)); | ||
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { | 57 | void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { |
| @@ -89,8 +90,6 @@ public: | |||
| 89 | 90 | ||
| 90 | ARM_Dynarmic_32& parent; | 91 | ARM_Dynarmic_32& parent; |
| 91 | std::size_t num_interpreted_instructions{}; | 92 | std::size_t num_interpreted_instructions{}; |
| 92 | u64 tpidrro_el0{}; | ||
| 93 | u64 tpidr_el0{}; | ||
| 94 | }; | 93 | }; |
| 95 | 94 | ||
| 96 | std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table, | 95 | std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table, |
| @@ -99,7 +98,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& | |||
| 99 | config.callbacks = cb.get(); | 98 | config.callbacks = cb.get(); |
| 100 | // TODO(bunnei): Implement page table for 32-bit | 99 | // TODO(bunnei): Implement page table for 32-bit |
| 101 | // config.page_table = &page_table.pointers; | 100 | // config.page_table = &page_table.pointers; |
| 102 | config.coprocessors[15] = std::make_shared<DynarmicCP15>((u32*)&CP15_regs[0]); | 101 | config.coprocessors[15] = cp15; |
| 103 | config.define_unpredictable_behaviour = true; | 102 | config.define_unpredictable_behaviour = true; |
| 104 | return std::make_unique<Dynarmic::A32::Jit>(config); | 103 | return std::make_unique<Dynarmic::A32::Jit>(config); |
| 105 | } | 104 | } |
| @@ -112,13 +111,13 @@ void ARM_Dynarmic_32::Run() { | |||
| 112 | } | 111 | } |
| 113 | 112 | ||
| 114 | void ARM_Dynarmic_32::Step() { | 113 | void ARM_Dynarmic_32::Step() { |
| 115 | cb->InterpreterFallback(jit->Regs()[15], 1); | 114 | jit->Step(); |
| 116 | } | 115 | } |
| 117 | 116 | ||
| 118 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor, | 117 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor, |
| 119 | std::size_t core_index) | 118 | std::size_t core_index) |
| 120 | : ARM_Interface{system}, | 119 | : ARM_Interface{system}, cb(std::make_unique<DynarmicCallbacks32>(*this)), |
| 121 | cb(std::make_unique<DynarmicCallbacks32>(*this)), core_index{core_index}, | 120 | cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index}, |
| 122 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} | 121 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} |
| 123 | 122 | ||
| 124 | ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; | 123 | ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; |
| @@ -154,19 +153,19 @@ void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) { | |||
| 154 | } | 153 | } |
| 155 | 154 | ||
| 156 | u64 ARM_Dynarmic_32::GetTlsAddress() const { | 155 | u64 ARM_Dynarmic_32::GetTlsAddress() const { |
| 157 | return CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)]; | 156 | return cp15->uro; |
| 158 | } | 157 | } |
| 159 | 158 | ||
| 160 | void ARM_Dynarmic_32::SetTlsAddress(VAddr address) { | 159 | void ARM_Dynarmic_32::SetTlsAddress(VAddr address) { |
| 161 | CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)] = static_cast<u32>(address); | 160 | cp15->uro = static_cast<u32>(address); |
| 162 | } | 161 | } |
| 163 | 162 | ||
| 164 | u64 ARM_Dynarmic_32::GetTPIDR_EL0() const { | 163 | u64 ARM_Dynarmic_32::GetTPIDR_EL0() const { |
| 165 | return cb->tpidr_el0; | 164 | return cp15->uprw; |
| 166 | } | 165 | } |
| 167 | 166 | ||
| 168 | void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) { | 167 | void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) { |
| 169 | cb->tpidr_el0 = value; | 168 | cp15->uprw = value; |
| 170 | } | 169 | } |
| 171 | 170 | ||
| 172 | void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { | 171 | void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index 8ba9cea8f..e5b92d7bb 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -22,6 +22,7 @@ class Memory; | |||
| 22 | namespace Core { | 22 | namespace Core { |
| 23 | 23 | ||
| 24 | class DynarmicCallbacks32; | 24 | class DynarmicCallbacks32; |
| 25 | class DynarmicCP15; | ||
| 25 | class DynarmicExclusiveMonitor; | 26 | class DynarmicExclusiveMonitor; |
| 26 | class System; | 27 | class System; |
| 27 | 28 | ||
| @@ -66,12 +67,14 @@ private: | |||
| 66 | std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>; | 67 | std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>; |
| 67 | 68 | ||
| 68 | friend class DynarmicCallbacks32; | 69 | friend class DynarmicCallbacks32; |
| 70 | friend class DynarmicCP15; | ||
| 71 | |||
| 69 | std::unique_ptr<DynarmicCallbacks32> cb; | 72 | std::unique_ptr<DynarmicCallbacks32> cb; |
| 70 | JitCacheType jit_cache; | 73 | JitCacheType jit_cache; |
| 71 | std::shared_ptr<Dynarmic::A32::Jit> jit; | 74 | std::shared_ptr<Dynarmic::A32::Jit> jit; |
| 75 | std::shared_ptr<DynarmicCP15> cp15; | ||
| 72 | std::size_t core_index; | 76 | std::size_t core_index; |
| 73 | DynarmicExclusiveMonitor& exclusive_monitor; | 77 | DynarmicExclusiveMonitor& exclusive_monitor; |
| 74 | std::array<u32, 84> CP15_regs{}; | ||
| 75 | }; | 78 | }; |
| 76 | 79 | ||
| 77 | } // namespace Core | 80 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp index 3fdcdebde..d43e4dd70 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp | |||
| @@ -2,79 +2,132 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <fmt/format.h> | ||
| 6 | #include "common/logging/log.h" | ||
| 7 | #include "core/arm/dynarmic/arm_dynarmic_32.h" | ||
| 5 | #include "core/arm/dynarmic/arm_dynarmic_cp15.h" | 8 | #include "core/arm/dynarmic/arm_dynarmic_cp15.h" |
| 9 | #include "core/core.h" | ||
| 10 | #include "core/core_timing.h" | ||
| 11 | #include "core/core_timing_util.h" | ||
| 6 | 12 | ||
| 7 | using Callback = Dynarmic::A32::Coprocessor::Callback; | 13 | using Callback = Dynarmic::A32::Coprocessor::Callback; |
| 8 | using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord; | 14 | using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord; |
| 9 | using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords; | 15 | using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords; |
| 10 | 16 | ||
| 17 | template <> | ||
| 18 | struct fmt::formatter<Dynarmic::A32::CoprocReg> { | ||
| 19 | constexpr auto parse(format_parse_context& ctx) { | ||
| 20 | return ctx.begin(); | ||
| 21 | } | ||
| 22 | template <typename FormatContext> | ||
| 23 | auto format(const Dynarmic::A32::CoprocReg& reg, FormatContext& ctx) { | ||
| 24 | return format_to(ctx.out(), "cp{}", static_cast<size_t>(reg)); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | |||
| 28 | namespace Core { | ||
| 29 | |||
| 30 | static u32 dummy_value; | ||
| 31 | |||
| 11 | std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1, | 32 | std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1, |
| 12 | CoprocReg CRd, CoprocReg CRn, | 33 | CoprocReg CRd, CoprocReg CRn, |
| 13 | CoprocReg CRm, unsigned opc2) { | 34 | CoprocReg CRm, unsigned opc2) { |
| 35 | LOG_CRITICAL(Core_ARM, "CP15: cdp{} p15, {}, {}, {}, {}, {}", two ? "2" : "", opc1, CRd, CRn, | ||
| 36 | CRm, opc2); | ||
| 14 | return {}; | 37 | return {}; |
| 15 | } | 38 | } |
| 16 | 39 | ||
| 17 | CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn, | 40 | CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn, |
| 18 | CoprocReg CRm, unsigned opc2) { | 41 | CoprocReg CRm, unsigned opc2) { |
| 19 | // TODO(merry): Privileged CP15 registers | ||
| 20 | |||
| 21 | if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C5 && opc2 == 4) { | 42 | if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C5 && opc2 == 4) { |
| 43 | // CP15_FLUSH_PREFETCH_BUFFER | ||
| 22 | // This is a dummy write, we ignore the value written here. | 44 | // This is a dummy write, we ignore the value written here. |
| 23 | return &CP15[static_cast<std::size_t>(CP15Register::CP15_FLUSH_PREFETCH_BUFFER)]; | 45 | return &dummy_value; |
| 24 | } | 46 | } |
| 25 | 47 | ||
| 26 | if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C10) { | 48 | if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C10) { |
| 27 | switch (opc2) { | 49 | switch (opc2) { |
| 28 | case 4: | 50 | case 4: |
| 51 | // CP15_DATA_SYNC_BARRIER | ||
| 29 | // This is a dummy write, we ignore the value written here. | 52 | // This is a dummy write, we ignore the value written here. |
| 30 | return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_SYNC_BARRIER)]; | 53 | return &dummy_value; |
| 31 | case 5: | 54 | case 5: |
| 55 | // CP15_DATA_MEMORY_BARRIER | ||
| 32 | // This is a dummy write, we ignore the value written here. | 56 | // This is a dummy write, we ignore the value written here. |
| 33 | return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_MEMORY_BARRIER)]; | 57 | return &dummy_value; |
| 34 | default: | ||
| 35 | return {}; | ||
| 36 | } | 58 | } |
| 37 | } | 59 | } |
| 38 | 60 | ||
| 39 | if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0 && opc2 == 2) { | 61 | if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0 && opc2 == 2) { |
| 40 | return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)]; | 62 | // CP15_THREAD_UPRW |
| 63 | return &uprw; | ||
| 41 | } | 64 | } |
| 42 | 65 | ||
| 66 | LOG_CRITICAL(Core_ARM, "CP15: mcr{} p15, {}, <Rt>, {}, {}, {}", two ? "2" : "", opc1, CRn, CRm, | ||
| 67 | opc2); | ||
| 43 | return {}; | 68 | return {}; |
| 44 | } | 69 | } |
| 45 | 70 | ||
| 46 | CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) { | 71 | CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) { |
| 72 | LOG_CRITICAL(Core_ARM, "CP15: mcrr{} p15, {}, <Rt>, <Rt2>, {}", two ? "2" : "", opc, CRm); | ||
| 47 | return {}; | 73 | return {}; |
| 48 | } | 74 | } |
| 49 | 75 | ||
| 50 | CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn, | 76 | CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn, |
| 51 | CoprocReg CRm, unsigned opc2) { | 77 | CoprocReg CRm, unsigned opc2) { |
| 52 | // TODO(merry): Privileged CP15 registers | ||
| 53 | |||
| 54 | if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0) { | 78 | if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0) { |
| 55 | switch (opc2) { | 79 | switch (opc2) { |
| 56 | case 2: | 80 | case 2: |
| 57 | return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)]; | 81 | // CP15_THREAD_UPRW |
| 82 | return &uprw; | ||
| 58 | case 3: | 83 | case 3: |
| 59 | return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)]; | 84 | // CP15_THREAD_URO |
| 60 | default: | 85 | return &uro; |
| 61 | return {}; | ||
| 62 | } | 86 | } |
| 63 | } | 87 | } |
| 64 | 88 | ||
| 89 | LOG_CRITICAL(Core_ARM, "CP15: mrc{} p15, {}, <Rt>, {}, {}, {}", two ? "2" : "", opc1, CRn, CRm, | ||
| 90 | opc2); | ||
| 65 | return {}; | 91 | return {}; |
| 66 | } | 92 | } |
| 67 | 93 | ||
| 68 | CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) { | 94 | CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) { |
| 95 | if (!two && opc == 0 && CRm == CoprocReg::C14) { | ||
| 96 | // CNTPCT | ||
| 97 | const auto callback = static_cast<u64 (*)(Dynarmic::A32::Jit*, void*, u32, u32)>( | ||
| 98 | [](Dynarmic::A32::Jit*, void* arg, u32, u32) -> u64 { | ||
| 99 | ARM_Dynarmic_32& parent = *(ARM_Dynarmic_32*)arg; | ||
| 100 | return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks()); | ||
| 101 | }); | ||
| 102 | return Dynarmic::A32::Coprocessor::Callback{callback, (void*)&parent}; | ||
| 103 | } | ||
| 104 | |||
| 105 | LOG_CRITICAL(Core_ARM, "CP15: mrrc{} p15, {}, <Rt>, <Rt2>, {}", two ? "2" : "", opc, CRm); | ||
| 69 | return {}; | 106 | return {}; |
| 70 | } | 107 | } |
| 71 | 108 | ||
| 72 | std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd, | 109 | std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd, |
| 73 | std::optional<u8> option) { | 110 | std::optional<u8> option) { |
| 111 | if (option) { | ||
| 112 | LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...], {}", two ? "2" : "", | ||
| 113 | long_transfer ? "l" : "", CRd, *option); | ||
| 114 | } else { | ||
| 115 | LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...]", two ? "2" : "", | ||
| 116 | long_transfer ? "l" : "", CRd); | ||
| 117 | } | ||
| 74 | return {}; | 118 | return {}; |
| 75 | } | 119 | } |
| 76 | 120 | ||
| 77 | std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd, | 121 | std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd, |
| 78 | std::optional<u8> option) { | 122 | std::optional<u8> option) { |
| 123 | if (option) { | ||
| 124 | LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...], {}", two ? "2" : "", | ||
| 125 | long_transfer ? "l" : "", CRd, *option); | ||
| 126 | } else { | ||
| 127 | LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...]", two ? "2" : "", | ||
| 128 | long_transfer ? "l" : "", CRd); | ||
| 129 | } | ||
| 79 | return {}; | 130 | return {}; |
| 80 | } | 131 | } |
| 132 | |||
| 133 | } // namespace Core | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h index 07bcde5f9..7356d252e 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h +++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h | |||
| @@ -10,128 +10,15 @@ | |||
| 10 | #include <dynarmic/A32/coprocessor.h> | 10 | #include <dynarmic/A32/coprocessor.h> |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | 12 | ||
| 13 | enum class CP15Register { | 13 | namespace Core { |
| 14 | // c0 - Information registers | ||
| 15 | CP15_MAIN_ID, | ||
| 16 | CP15_CACHE_TYPE, | ||
| 17 | CP15_TCM_STATUS, | ||
| 18 | CP15_TLB_TYPE, | ||
| 19 | CP15_CPU_ID, | ||
| 20 | CP15_PROCESSOR_FEATURE_0, | ||
| 21 | CP15_PROCESSOR_FEATURE_1, | ||
| 22 | CP15_DEBUG_FEATURE_0, | ||
| 23 | CP15_AUXILIARY_FEATURE_0, | ||
| 24 | CP15_MEMORY_MODEL_FEATURE_0, | ||
| 25 | CP15_MEMORY_MODEL_FEATURE_1, | ||
| 26 | CP15_MEMORY_MODEL_FEATURE_2, | ||
| 27 | CP15_MEMORY_MODEL_FEATURE_3, | ||
| 28 | CP15_ISA_FEATURE_0, | ||
| 29 | CP15_ISA_FEATURE_1, | ||
| 30 | CP15_ISA_FEATURE_2, | ||
| 31 | CP15_ISA_FEATURE_3, | ||
| 32 | CP15_ISA_FEATURE_4, | ||
| 33 | 14 | ||
| 34 | // c1 - Control registers | 15 | class ARM_Dynarmic_32; |
| 35 | CP15_CONTROL, | ||
| 36 | CP15_AUXILIARY_CONTROL, | ||
| 37 | CP15_COPROCESSOR_ACCESS_CONTROL, | ||
| 38 | |||
| 39 | // c2 - Translation table registers | ||
| 40 | CP15_TRANSLATION_BASE_TABLE_0, | ||
| 41 | CP15_TRANSLATION_BASE_TABLE_1, | ||
| 42 | CP15_TRANSLATION_BASE_CONTROL, | ||
| 43 | CP15_DOMAIN_ACCESS_CONTROL, | ||
| 44 | CP15_RESERVED, | ||
| 45 | |||
| 46 | // c5 - Fault status registers | ||
| 47 | CP15_FAULT_STATUS, | ||
| 48 | CP15_INSTR_FAULT_STATUS, | ||
| 49 | CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS, | ||
| 50 | CP15_INST_FSR, | ||
| 51 | |||
| 52 | // c6 - Fault Address registers | ||
| 53 | CP15_FAULT_ADDRESS, | ||
| 54 | CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS, | ||
| 55 | CP15_WFAR, | ||
| 56 | CP15_IFAR, | ||
| 57 | |||
| 58 | // c7 - Cache operation registers | ||
| 59 | CP15_WAIT_FOR_INTERRUPT, | ||
| 60 | CP15_PHYS_ADDRESS, | ||
| 61 | CP15_INVALIDATE_INSTR_CACHE, | ||
| 62 | CP15_INVALIDATE_INSTR_CACHE_USING_MVA, | ||
| 63 | CP15_INVALIDATE_INSTR_CACHE_USING_INDEX, | ||
| 64 | CP15_FLUSH_PREFETCH_BUFFER, | ||
| 65 | CP15_FLUSH_BRANCH_TARGET_CACHE, | ||
| 66 | CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY, | ||
| 67 | CP15_INVALIDATE_DATA_CACHE, | ||
| 68 | CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA, | ||
| 69 | CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX, | ||
| 70 | CP15_INVALIDATE_DATA_AND_INSTR_CACHE, | ||
| 71 | CP15_CLEAN_DATA_CACHE, | ||
| 72 | CP15_CLEAN_DATA_CACHE_LINE_USING_MVA, | ||
| 73 | CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX, | ||
| 74 | CP15_DATA_SYNC_BARRIER, | ||
| 75 | CP15_DATA_MEMORY_BARRIER, | ||
| 76 | CP15_CLEAN_AND_INVALIDATE_DATA_CACHE, | ||
| 77 | CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA, | ||
| 78 | CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX, | ||
| 79 | |||
| 80 | // c8 - TLB operations | ||
| 81 | CP15_INVALIDATE_ITLB, | ||
| 82 | CP15_INVALIDATE_ITLB_SINGLE_ENTRY, | ||
| 83 | CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH, | ||
| 84 | CP15_INVALIDATE_ITLB_ENTRY_ON_MVA, | ||
| 85 | CP15_INVALIDATE_DTLB, | ||
| 86 | CP15_INVALIDATE_DTLB_SINGLE_ENTRY, | ||
| 87 | CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH, | ||
| 88 | CP15_INVALIDATE_DTLB_ENTRY_ON_MVA, | ||
| 89 | CP15_INVALIDATE_UTLB, | ||
| 90 | CP15_INVALIDATE_UTLB_SINGLE_ENTRY, | ||
| 91 | CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH, | ||
| 92 | CP15_INVALIDATE_UTLB_ENTRY_ON_MVA, | ||
| 93 | |||
| 94 | // c9 - Data cache lockdown register | ||
| 95 | CP15_DATA_CACHE_LOCKDOWN, | ||
| 96 | |||
| 97 | // c10 - TLB/Memory map registers | ||
| 98 | CP15_TLB_LOCKDOWN, | ||
| 99 | CP15_PRIMARY_REGION_REMAP, | ||
| 100 | CP15_NORMAL_REGION_REMAP, | ||
| 101 | |||
| 102 | // c13 - Thread related registers | ||
| 103 | CP15_PID, | ||
| 104 | CP15_CONTEXT_ID, | ||
| 105 | CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write | ||
| 106 | CP15_THREAD_URO, // Thread ID register - User Read Only (Privileged R/W) | ||
| 107 | CP15_THREAD_PRW, // Thread ID register - Privileged R/W only. | ||
| 108 | |||
| 109 | // c15 - Performance and TLB lockdown registers | ||
| 110 | CP15_PERFORMANCE_MONITOR_CONTROL, | ||
| 111 | CP15_CYCLE_COUNTER, | ||
| 112 | CP15_COUNT_0, | ||
| 113 | CP15_COUNT_1, | ||
| 114 | CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY, | ||
| 115 | CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY, | ||
| 116 | CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS, | ||
| 117 | CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS, | ||
| 118 | CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE, | ||
| 119 | CP15_TLB_DEBUG_CONTROL, | ||
| 120 | |||
| 121 | // Skyeye defined | ||
| 122 | CP15_TLB_FAULT_ADDR, | ||
| 123 | CP15_TLB_FAULT_STATUS, | ||
| 124 | |||
| 125 | // Not an actual register. | ||
| 126 | // All registers should be defined above this. | ||
| 127 | CP15_REGISTER_COUNT, | ||
| 128 | }; | ||
| 129 | 16 | ||
| 130 | class DynarmicCP15 final : public Dynarmic::A32::Coprocessor { | 17 | class DynarmicCP15 final : public Dynarmic::A32::Coprocessor { |
| 131 | public: | 18 | public: |
| 132 | using CoprocReg = Dynarmic::A32::CoprocReg; | 19 | using CoprocReg = Dynarmic::A32::CoprocReg; |
| 133 | 20 | ||
| 134 | explicit DynarmicCP15(u32* cp15) : CP15(cp15){}; | 21 | explicit DynarmicCP15(ARM_Dynarmic_32& parent) : parent(parent) {} |
| 135 | 22 | ||
| 136 | std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd, | 23 | std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd, |
| 137 | CoprocReg CRn, CoprocReg CRm, | 24 | CoprocReg CRn, CoprocReg CRm, |
| @@ -147,6 +34,9 @@ public: | |||
| 147 | std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd, | 34 | std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd, |
| 148 | std::optional<u8> option) override; | 35 | std::optional<u8> option) override; |
| 149 | 36 | ||
| 150 | private: | 37 | ARM_Dynarmic_32& parent; |
| 151 | u32* CP15{}; | 38 | u32 uprw; |
| 39 | u32 uro; | ||
| 152 | }; | 40 | }; |
| 41 | |||
| 42 | } // namespace Core | ||