diff options
Diffstat (limited to 'src/core/arm')
| -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:      }      void InterpreterFallback(u32 pc, std::size_t num_instructions) override { -        UNIMPLEMENTED(); +        UNIMPLEMENTED_MSG("This should never happen, pc = {:08X}, code = {:08X}", pc, +                          MemoryReadCode(pc));      }      void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { @@ -89,8 +90,6 @@ public:      ARM_Dynarmic_32& parent;      std::size_t num_interpreted_instructions{}; -    u64 tpidrro_el0{}; -    u64 tpidr_el0{};  };  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&      config.callbacks = cb.get();      // TODO(bunnei): Implement page table for 32-bit      // config.page_table = &page_table.pointers; -    config.coprocessors[15] = std::make_shared<DynarmicCP15>((u32*)&CP15_regs[0]); +    config.coprocessors[15] = cp15;      config.define_unpredictable_behaviour = true;      return std::make_unique<Dynarmic::A32::Jit>(config);  } @@ -112,13 +111,13 @@ void ARM_Dynarmic_32::Run() {  }  void ARM_Dynarmic_32::Step() { -    cb->InterpreterFallback(jit->Regs()[15], 1); +    jit->Step();  }  ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor,                                   std::size_t core_index) -    : ARM_Interface{system}, -      cb(std::make_unique<DynarmicCallbacks32>(*this)), core_index{core_index}, +    : ARM_Interface{system}, cb(std::make_unique<DynarmicCallbacks32>(*this)), +      cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index},        exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}  ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; @@ -154,19 +153,19 @@ void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) {  }  u64 ARM_Dynarmic_32::GetTlsAddress() const { -    return CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)]; +    return cp15->uro;  }  void ARM_Dynarmic_32::SetTlsAddress(VAddr address) { -    CP15_regs[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)] = static_cast<u32>(address); +    cp15->uro = static_cast<u32>(address);  }  u64 ARM_Dynarmic_32::GetTPIDR_EL0() const { -    return cb->tpidr_el0; +    return cp15->uprw;  }  void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) { -    cb->tpidr_el0 = value; +    cp15->uprw = value;  }  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;  namespace Core {  class DynarmicCallbacks32; +class DynarmicCP15;  class DynarmicExclusiveMonitor;  class System; @@ -66,12 +67,14 @@ private:          std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A32::Jit>, Common::PairHash>;      friend class DynarmicCallbacks32; +    friend class DynarmicCP15; +      std::unique_ptr<DynarmicCallbacks32> cb;      JitCacheType jit_cache;      std::shared_ptr<Dynarmic::A32::Jit> jit; +    std::shared_ptr<DynarmicCP15> cp15;      std::size_t core_index;      DynarmicExclusiveMonitor& exclusive_monitor; -    std::array<u32, 84> CP15_regs{};  };  } // 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 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <fmt/format.h> +#include "common/logging/log.h" +#include "core/arm/dynarmic/arm_dynarmic_32.h"  #include "core/arm/dynarmic/arm_dynarmic_cp15.h" +#include "core/core.h" +#include "core/core_timing.h" +#include "core/core_timing_util.h"  using Callback = Dynarmic::A32::Coprocessor::Callback;  using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord;  using CallbackOrAccessTwoWords = Dynarmic::A32::Coprocessor::CallbackOrAccessTwoWords; +template <> +struct fmt::formatter<Dynarmic::A32::CoprocReg> { +    constexpr auto parse(format_parse_context& ctx) { +        return ctx.begin(); +    } +    template <typename FormatContext> +    auto format(const Dynarmic::A32::CoprocReg& reg, FormatContext& ctx) { +        return format_to(ctx.out(), "cp{}", static_cast<size_t>(reg)); +    } +}; + +namespace Core { + +static u32 dummy_value; +  std::optional<Callback> DynarmicCP15::CompileInternalOperation(bool two, unsigned opc1,                                                                 CoprocReg CRd, CoprocReg CRn,                                                                 CoprocReg CRm, unsigned opc2) { +    LOG_CRITICAL(Core_ARM, "CP15: cdp{} p15, {}, {}, {}, {}, {}", two ? "2" : "", opc1, CRd, CRn, +                 CRm, 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) { +        // CP15_FLUSH_PREFETCH_BUFFER          // This is a dummy write, we ignore the value written here. -        return &CP15[static_cast<std::size_t>(CP15Register::CP15_FLUSH_PREFETCH_BUFFER)]; +        return &dummy_value;      }      if (!two && CRn == CoprocReg::C7 && opc1 == 0 && CRm == CoprocReg::C10) {          switch (opc2) {          case 4: +            // CP15_DATA_SYNC_BARRIER              // This is a dummy write, we ignore the value written here. -            return &CP15[static_cast<std::size_t>(CP15Register::CP15_DATA_SYNC_BARRIER)]; +            return &dummy_value;          case 5: +            // CP15_DATA_MEMORY_BARRIER              // 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 {}; +            return &dummy_value;          }      }      if (!two && CRn == CoprocReg::C13 && opc1 == 0 && CRm == CoprocReg::C0 && opc2 == 2) { -        return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_UPRW)]; +        // CP15_THREAD_UPRW +        return &uprw;      } +    LOG_CRITICAL(Core_ARM, "CP15: mcr{} p15, {}, <Rt>, {}, {}, {}", two ? "2" : "", opc1, CRn, CRm, +                 opc2);      return {};  }  CallbackOrAccessTwoWords DynarmicCP15::CompileSendTwoWords(bool two, unsigned opc, CoprocReg CRm) { +    LOG_CRITICAL(Core_ARM, "CP15: mcrr{} p15, {}, <Rt>, <Rt2>, {}", two ? "2" : "", opc, 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)]; +            // CP15_THREAD_UPRW +            return &uprw;          case 3: -            return &CP15[static_cast<std::size_t>(CP15Register::CP15_THREAD_URO)]; -        default: -            return {}; +            // CP15_THREAD_URO +            return &uro;          }      } +    LOG_CRITICAL(Core_ARM, "CP15: mrc{} p15, {}, <Rt>, {}, {}, {}", two ? "2" : "", opc1, CRn, CRm, +                 opc2);      return {};  }  CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) { +    if (!two && opc == 0 && CRm == CoprocReg::C14) { +        // CNTPCT +        const auto callback = static_cast<u64 (*)(Dynarmic::A32::Jit*, void*, u32, u32)>( +            [](Dynarmic::A32::Jit*, void* arg, u32, u32) -> u64 { +                ARM_Dynarmic_32& parent = *(ARM_Dynarmic_32*)arg; +                return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks()); +            }); +        return Dynarmic::A32::Coprocessor::Callback{callback, (void*)&parent}; +    } + +    LOG_CRITICAL(Core_ARM, "CP15: mrrc{} p15, {}, <Rt>, <Rt2>, {}", two ? "2" : "", opc, CRm);      return {};  }  std::optional<Callback> DynarmicCP15::CompileLoadWords(bool two, bool long_transfer, CoprocReg CRd,                                                         std::optional<u8> option) { +    if (option) { +        LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...], {}", two ? "2" : "", +                     long_transfer ? "l" : "", CRd, *option); +    } else { +        LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...]", two ? "2" : "", +                     long_transfer ? "l" : "", CRd); +    }      return {};  }  std::optional<Callback> DynarmicCP15::CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,                                                          std::optional<u8> option) { +    if (option) { +        LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...], {}", two ? "2" : "", +                     long_transfer ? "l" : "", CRd, *option); +    } else { +        LOG_CRITICAL(Core_ARM, "CP15: mrrc{}{} p15, {}, [...]", two ? "2" : "", +                     long_transfer ? "l" : "", CRd); +    }      return {};  } + +} // 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 @@  #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, +namespace Core { -    // 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 ARM_Dynarmic_32;  class DynarmicCP15 final : public Dynarmic::A32::Coprocessor {  public:      using CoprocReg = Dynarmic::A32::CoprocReg; -    explicit DynarmicCP15(u32* cp15) : CP15(cp15){}; +    explicit DynarmicCP15(ARM_Dynarmic_32& parent) : parent(parent) {}      std::optional<Callback> CompileInternalOperation(bool two, unsigned opc1, CoprocReg CRd,                                                       CoprocReg CRn, CoprocReg CRm, @@ -147,6 +34,9 @@ public:      std::optional<Callback> CompileStoreWords(bool two, bool long_transfer, CoprocReg CRd,                                                std::optional<u8> option) override; -private: -    u32* CP15{}; +    ARM_Dynarmic_32& parent; +    u32 uprw; +    u32 uro;  }; + +} // namespace Core  | 
