summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_cp15.cpp80
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_cp15.h152
3 files changed, 234 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 54be7dc0c..df1e62d4f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -597,6 +597,8 @@ if (ARCHITECTURE_x86_64)
target_sources(core PRIVATE
arm/dynarmic/arm_dynarmic.cpp
arm/dynarmic/arm_dynarmic.h
+ arm/dynarmic/arm_dynarmic_cp15.cpp
+ arm/dynarmic/arm_dynarmic_cp15.h
)
target_link_libraries(core PRIVATE dynarmic)
endif()
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
new file mode 100644
index 000000000..3fdcdebde
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
@@ -0,0 +1,80 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
+
+using Callback = Dynarmic::A32::Coprocessor::Callback;
+using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord;
+using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords;
+
+std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1,
+ CoprocReg CRd, CoprocReg CRn,
+ CoprocReg CRm, unsigned opc2) {
+ return {};
+}
+
+CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
+ CoprocReg CRm, unsigned opc2) {
+ // TODO(merry): Privileged CP15 registers
+
+ if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C5 && opc2 == 4) {
+ // This is a dummy write, we ignore the value written here.
+ return &CP15[static_cast<std::size_t>(CP15Register::CP15_FLUSH_PREFETCH_BUFFER)];
+ }
+
+ if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C10) {
+ switch (opc2) {
+ case 4:
+ // This is a dummy write, we ignore the value written here.
+ return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_SYNC_BARRIER)];
+ case 5:
+ // This is a dummy write, we ignore the value written here.
+ return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_MEMORY_BARRIER)];
+ default:
+ return {};
+ }
+ }
+
+ if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0 && opc2 == 2) {
+ return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)];
+ }
+
+ return {};
+}
+
+CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) {
+ return {};
+}
+
+CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn,
+ CoprocReg CRm, unsigned opc2) {
+ // TODO(merry): Privileged CP15 registers
+
+ if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0) {
+ switch (opc2) {
+ case 2:
+ return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)];
+ case 3:
+ return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)];
+ default:
+ return {};
+ }
+ }
+
+ return {};
+}
+
+CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) {
+ return {};
+}
+
+std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,
+ std::optional<u8> option) {
+ return {};
+}
+
+std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
+ std::optional<u8> option) {
+ return {};
+}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
new file mode 100644
index 000000000..07bcde5f9
--- /dev/null
+++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
@@ -0,0 +1,152 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+#include <optional>
+
+#include <dynarmic/A32/coprocessor.h>
+#include "common/common_types.h"
+
+enum class CP15Register {
+ // c0 - Information registers
+ CP15_MAIN_ID,
+ CP15_CACHE_TYPE,
+ CP15_TCM_STATUS,
+ CP15_TLB_TYPE,
+ CP15_CPU_ID,
+ CP15_PROCESSOR_FEATURE_0,
+ CP15_PROCESSOR_FEATURE_1,
+ CP15_DEBUG_FEATURE_0,
+ CP15_AUXILIARY_FEATURE_0,
+ CP15_MEMORY_MODEL_FEATURE_0,
+ CP15_MEMORY_MODEL_FEATURE_1,
+ CP15_MEMORY_MODEL_FEATURE_2,
+ CP15_MEMORY_MODEL_FEATURE_3,
+ CP15_ISA_FEATURE_0,
+ CP15_ISA_FEATURE_1,
+ CP15_ISA_FEATURE_2,
+ CP15_ISA_FEATURE_3,
+ CP15_ISA_FEATURE_4,
+
+ // c1 - Control registers
+ CP15_CONTROL,
+ CP15_AUXILIARY_CONTROL,
+ CP15_COPROCESSOR_ACCESS_CONTROL,
+
+ // c2 - Translation table registers
+ CP15_TRANSLATION_BASE_TABLE_0,
+ CP15_TRANSLATION_BASE_TABLE_1,
+ CP15_TRANSLATION_BASE_CONTROL,
+ CP15_DOMAIN_ACCESS_CONTROL,
+ CP15_RESERVED,
+
+ // c5 - Fault status registers
+ CP15_FAULT_STATUS,
+ CP15_INSTR_FAULT_STATUS,
+ CP15_COMBINED_DATA_FSR = CP15_FAULT_STATUS,
+ CP15_INST_FSR,
+
+ // c6 - Fault Address registers
+ CP15_FAULT_ADDRESS,
+ CP15_COMBINED_DATA_FAR = CP15_FAULT_ADDRESS,
+ CP15_WFAR,
+ CP15_IFAR,
+
+ // c7 - Cache operation registers
+ CP15_WAIT_FOR_INTERRUPT,
+ CP15_PHYS_ADDRESS,
+ CP15_INVALIDATE_INSTR_CACHE,
+ CP15_INVALIDATE_INSTR_CACHE_USING_MVA,
+ CP15_INVALIDATE_INSTR_CACHE_USING_INDEX,
+ CP15_FLUSH_PREFETCH_BUFFER,
+ CP15_FLUSH_BRANCH_TARGET_CACHE,
+ CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY,
+ CP15_INVALIDATE_DATA_CACHE,
+ CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
+ CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
+ CP15_INVALIDATE_DATA_AND_INSTR_CACHE,
+ CP15_CLEAN_DATA_CACHE,
+ CP15_CLEAN_DATA_CACHE_LINE_USING_MVA,
+ CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX,
+ CP15_DATA_SYNC_BARRIER,
+ CP15_DATA_MEMORY_BARRIER,
+ CP15_CLEAN_AND_INVALIDATE_DATA_CACHE,
+ CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA,
+ CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX,
+
+ // c8 - TLB operations
+ CP15_INVALIDATE_ITLB,
+ CP15_INVALIDATE_ITLB_SINGLE_ENTRY,
+ CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH,
+ CP15_INVALIDATE_ITLB_ENTRY_ON_MVA,
+ CP15_INVALIDATE_DTLB,
+ CP15_INVALIDATE_DTLB_SINGLE_ENTRY,
+ CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH,
+ CP15_INVALIDATE_DTLB_ENTRY_ON_MVA,
+ CP15_INVALIDATE_UTLB,
+ CP15_INVALIDATE_UTLB_SINGLE_ENTRY,
+ CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH,
+ CP15_INVALIDATE_UTLB_ENTRY_ON_MVA,
+
+ // c9 - Data cache lockdown register
+ CP15_DATA_CACHE_LOCKDOWN,
+
+ // c10 - TLB/Memory map registers
+ CP15_TLB_LOCKDOWN,
+ CP15_PRIMARY_REGION_REMAP,
+ CP15_NORMAL_REGION_REMAP,
+
+ // c13 - Thread related registers
+ CP15_PID,
+ CP15_CONTEXT_ID,
+ CP15_THREAD_UPRW, // Thread ID register - User/Privileged Read/Write
+ CP15_THREAD_URO, // Thread ID register - User Read Only (Privileged R/W)
+ CP15_THREAD_PRW, // Thread ID register - Privileged R/W only.
+
+ // c15 - Performance and TLB lockdown registers
+ CP15_PERFORMANCE_MONITOR_CONTROL,
+ CP15_CYCLE_COUNTER,
+ CP15_COUNT_0,
+ CP15_COUNT_1,
+ CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY,
+ CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY,
+ CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS,
+ CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS,
+ CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE,
+ CP15_TLB_DEBUG_CONTROL,
+
+ // Skyeye defined
+ CP15_TLB_FAULT_ADDR,
+ CP15_TLB_FAULT_STATUS,
+
+ // Not an actual register.
+ // All registers should be defined above this.
+ CP15_REGISTER_COUNT,
+};
+
+class DynarmicCP15 final : public Dynarmic::A32::Coprocessor {
+public:
+ using CoprocReg = Dynarmic::A32::CoprocReg;
+
+ explicit DynarmicCP15(u32* cp15) : CP15(cp15){};
+
+ std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd,
+ CoprocReg CRn, CoprocReg CRm,
+ unsigned opc2) override;
+ CallbackOrAccessOneWord CompileSendOneWord(bool two, unsigned opc1, CoprocReg CRn,
+ CoprocReg CRm, unsigned opc2) override;
+ CallbackOrAccessTwoWords CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
+ CallbackOrAccessOneWord CompileGetOneWord(bool two, unsigned opc1, CoprocReg CRn, CoprocReg CRm,
+ unsigned opc2) override;
+ CallbackOrAccessTwoWords CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) override;
+ std::optional<Callback> CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,
+ std::optional<u8> option) override;
+ std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,
+ std::optional<u8> option) override;
+
+private:
+ u32* CP15{};
+};