diff options
| author | 2020-03-28 15:23:28 -0400 | |
|---|---|---|
| committer | 2020-06-27 11:36:01 -0400 | |
| commit | f5e32935ca9d1727624c86ca78aff91027caf819 (patch) | |
| tree | a041186cd47fcea90880b300af3351a56fb819aa /src/core/arm | |
| parent | Scheduler: Correct Reload/Unload (diff) | |
| download | yuzu-f5e32935ca9d1727624c86ca78aff91027caf819.tar.gz yuzu-f5e32935ca9d1727624c86ca78aff91027caf819.tar.xz yuzu-f5e32935ca9d1727624c86ca78aff91027caf819.zip | |
SingleCore: Use Cycle Timing instead of Host Timing.
Diffstat (limited to 'src/core/arm')
| -rw-r--r-- | src/core/arm/arm_interface.h | 6 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 37 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.h | 2 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 39 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.h | 2 | ||||
| -rw-r--r-- | src/core/arm/unicorn/arm_unicorn.cpp | 6 | ||||
| -rw-r--r-- | src/core/arm/unicorn/arm_unicorn.h | 4 |
7 files changed, 62 insertions, 34 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index e5c484336..fbdce4134 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h | |||
| @@ -26,8 +26,9 @@ using CPUInterrupts = std::array<CPUInterruptHandler, Core::Hardware::NUM_CPU_CO | |||
| 26 | /// Generic ARMv8 CPU interface | 26 | /// Generic ARMv8 CPU interface |
| 27 | class ARM_Interface : NonCopyable { | 27 | class ARM_Interface : NonCopyable { |
| 28 | public: | 28 | public: |
| 29 | explicit ARM_Interface(System& system_, CPUInterrupts& interrupt_handlers) | 29 | explicit ARM_Interface(System& system_, CPUInterrupts& interrupt_handlers, bool uses_wall_clock) |
| 30 | : system{system_}, interrupt_handlers{interrupt_handlers} {} | 30 | : system{system_}, interrupt_handlers{interrupt_handlers}, uses_wall_clock{ |
| 31 | uses_wall_clock} {} | ||
| 31 | virtual ~ARM_Interface() = default; | 32 | virtual ~ARM_Interface() = default; |
| 32 | 33 | ||
| 33 | struct ThreadContext32 { | 34 | struct ThreadContext32 { |
| @@ -186,6 +187,7 @@ protected: | |||
| 186 | /// System context that this ARM interface is running under. | 187 | /// System context that this ARM interface is running under. |
| 187 | System& system; | 188 | System& system; |
| 188 | CPUInterrupts& interrupt_handlers; | 189 | CPUInterrupts& interrupt_handlers; |
| 190 | bool uses_wall_clock; | ||
| 189 | }; | 191 | }; |
| 190 | 192 | ||
| 191 | } // namespace Core | 193 | } // namespace Core |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 9c47c133c..c4aeedef9 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -72,23 +72,35 @@ public: | |||
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | void AddTicks(u64 ticks) override { | 74 | void AddTicks(u64 ticks) override { |
| 75 | this->ticks -= ticks; | 75 | if (parent.uses_wall_clock) { |
| 76 | return; | ||
| 77 | } | ||
| 78 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a | ||
| 79 | // rough approximation of the amount of executed ticks in the system, it may be thrown off | ||
| 80 | // if not all cores are doing a similar amount of work. Instead of doing this, we should | ||
| 81 | // device a way so that timing is consistent across all cores without increasing the ticks 4 | ||
| 82 | // times. | ||
| 83 | u64 amortized_ticks = | ||
| 84 | (ticks - num_interpreted_instructions) / Core::Hardware::NUM_CPU_CORES; | ||
| 85 | // Always execute at least one tick. | ||
| 86 | amortized_ticks = std::max<u64>(amortized_ticks, 1); | ||
| 87 | |||
| 88 | parent.system.CoreTiming().AddTicks(amortized_ticks); | ||
| 89 | num_interpreted_instructions = 0; | ||
| 76 | } | 90 | } |
| 77 | 91 | ||
| 78 | u64 GetTicksRemaining() override { | 92 | u64 GetTicksRemaining() override { |
| 79 | if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) { | 93 | if (parent.uses_wall_clock) { |
| 80 | return std::max<s64>(ticks, 0); | 94 | if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) { |
| 95 | return std::max<s64>(1000U, 0); | ||
| 96 | } | ||
| 97 | return 0ULL; | ||
| 81 | } | 98 | } |
| 82 | return 0ULL; | 99 | return std::max(parent.system.CoreTiming().GetDowncount(), 0LL); |
| 83 | } | ||
| 84 | |||
| 85 | void ResetTicks() { | ||
| 86 | ticks = 1000LL; | ||
| 87 | } | 100 | } |
| 88 | 101 | ||
| 89 | ARM_Dynarmic_32& parent; | 102 | ARM_Dynarmic_32& parent; |
| 90 | std::size_t num_interpreted_instructions{}; | 103 | std::size_t num_interpreted_instructions{}; |
| 91 | s64 ticks{}; | ||
| 92 | }; | 104 | }; |
| 93 | 105 | ||
| 94 | std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table, | 106 | std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& page_table, |
| @@ -103,7 +115,6 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable& | |||
| 103 | } | 115 | } |
| 104 | 116 | ||
| 105 | void ARM_Dynarmic_32::Run() { | 117 | void ARM_Dynarmic_32::Run() { |
| 106 | cb->ResetTicks(); | ||
| 107 | jit->Run(); | 118 | jit->Run(); |
| 108 | } | 119 | } |
| 109 | 120 | ||
| @@ -112,8 +123,10 @@ void ARM_Dynarmic_32::Step() { | |||
| 112 | } | 123 | } |
| 113 | 124 | ||
| 114 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, CPUInterrupts& interrupt_handlers, | 125 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, CPUInterrupts& interrupt_handlers, |
| 115 | ExclusiveMonitor& exclusive_monitor, std::size_t core_index) | 126 | bool uses_wall_clock, ExclusiveMonitor& exclusive_monitor, |
| 116 | : ARM_Interface{system, interrupt_handlers}, cb(std::make_unique<DynarmicCallbacks32>(*this)), | 127 | std::size_t core_index) |
| 128 | : ARM_Interface{system, interrupt_handlers, uses_wall_clock}, | ||
| 129 | cb(std::make_unique<DynarmicCallbacks32>(*this)), | ||
| 117 | cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index}, | 130 | cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index}, |
| 118 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} | 131 | exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} |
| 119 | 132 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index bea4933c8..8afd15c8b 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h | |||
| @@ -29,7 +29,7 @@ class System; | |||
| 29 | 29 | ||
| 30 | class ARM_Dynarmic_32 final : public ARM_Interface { | 30 | class ARM_Dynarmic_32 final : public ARM_Interface { |
| 31 | public: | 31 | public: |
| 32 | ARM_Dynarmic_32(System& system, CPUInterrupts& interrupt_handlers, | 32 | ARM_Dynarmic_32(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock, |
| 33 | ExclusiveMonitor& exclusive_monitor, std::size_t core_index); | 33 | ExclusiveMonitor& exclusive_monitor, std::size_t core_index); |
| 34 | ~ARM_Dynarmic_32() override; | 34 | ~ARM_Dynarmic_32() override; |
| 35 | 35 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 03b3313cf..a518733b6 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -124,29 +124,41 @@ public: | |||
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | void AddTicks(u64 ticks) override { | 126 | void AddTicks(u64 ticks) override { |
| 127 | this->ticks -= ticks; | 127 | if (parent.uses_wall_clock) { |
| 128 | return; | ||
| 129 | } | ||
| 130 | // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a | ||
| 131 | // rough approximation of the amount of executed ticks in the system, it may be thrown off | ||
| 132 | // if not all cores are doing a similar amount of work. Instead of doing this, we should | ||
| 133 | // device a way so that timing is consistent across all cores without increasing the ticks 4 | ||
| 134 | // times. | ||
| 135 | u64 amortized_ticks = | ||
| 136 | (ticks - num_interpreted_instructions) / Core::Hardware::NUM_CPU_CORES; | ||
| 137 | // Always execute at least one tick. | ||
| 138 | amortized_ticks = std::max<u64>(amortized_ticks, 1); | ||
| 139 | |||
| 140 | parent.system.CoreTiming().AddTicks(amortized_ticks); | ||
| 141 | num_interpreted_instructions = 0; | ||
| 128 | } | 142 | } |
| 129 | 143 | ||
| 130 | u64 GetTicksRemaining() override { | 144 | u64 GetTicksRemaining() override { |
| 131 | if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) { | 145 | if (parent.uses_wall_clock) { |
| 132 | return std::max<s64>(ticks, 0); | 146 | if (!parent.interrupt_handlers[parent.core_index].IsInterrupted()) { |
| 147 | return std::max<s64>(1000U, 0); | ||
| 148 | } | ||
| 149 | return 0ULL; | ||
| 133 | } | 150 | } |
| 134 | return 0ULL; | 151 | return std::max(parent.system.CoreTiming().GetDowncount(), 0LL); |
| 135 | } | 152 | } |
| 136 | 153 | ||
| 137 | u64 GetCNTPCT() override { | 154 | u64 GetCNTPCT() override { |
| 138 | return parent.system.CoreTiming().GetClockTicks(); | 155 | return parent.system.CoreTiming().GetClockTicks(); |
| 139 | } | 156 | } |
| 140 | 157 | ||
| 141 | void ResetTicks() { | ||
| 142 | ticks = 1000LL; | ||
| 143 | } | ||
| 144 | |||
| 145 | ARM_Dynarmic_64& parent; | 158 | ARM_Dynarmic_64& parent; |
| 146 | std::size_t num_interpreted_instructions = 0; | 159 | std::size_t num_interpreted_instructions = 0; |
| 147 | u64 tpidrro_el0 = 0; | 160 | u64 tpidrro_el0 = 0; |
| 148 | u64 tpidr_el0 = 0; | 161 | u64 tpidr_el0 = 0; |
| 149 | s64 ticks{}; | ||
| 150 | }; | 162 | }; |
| 151 | 163 | ||
| 152 | std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table, | 164 | std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table, |
| @@ -185,13 +197,12 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& | |||
| 185 | } | 197 | } |
| 186 | 198 | ||
| 187 | // CNTPCT uses wall clock. | 199 | // CNTPCT uses wall clock. |
| 188 | config.wall_clock_cntpct = true; | 200 | config.wall_clock_cntpct = uses_wall_clock; |
| 189 | 201 | ||
| 190 | return std::make_shared<Dynarmic::A64::Jit>(config); | 202 | return std::make_shared<Dynarmic::A64::Jit>(config); |
| 191 | } | 203 | } |
| 192 | 204 | ||
| 193 | void ARM_Dynarmic_64::Run() { | 205 | void ARM_Dynarmic_64::Run() { |
| 194 | cb->ResetTicks(); | ||
| 195 | jit->Run(); | 206 | jit->Run(); |
| 196 | } | 207 | } |
| 197 | 208 | ||
| @@ -200,9 +211,11 @@ void ARM_Dynarmic_64::Step() { | |||
| 200 | } | 211 | } |
| 201 | 212 | ||
| 202 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handlers, | 213 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handlers, |
| 203 | ExclusiveMonitor& exclusive_monitor, std::size_t core_index) | 214 | bool uses_wall_clock, ExclusiveMonitor& exclusive_monitor, |
| 204 | : ARM_Interface{system, interrupt_handler}, | 215 | std::size_t core_index) |
| 216 | : ARM_Interface{system, interrupt_handler, uses_wall_clock}, | ||
| 205 | cb(std::make_unique<DynarmicCallbacks64>(*this)), inner_unicorn{system, interrupt_handler, | 217 | cb(std::make_unique<DynarmicCallbacks64>(*this)), inner_unicorn{system, interrupt_handler, |
| 218 | uses_wall_clock, | ||
| 206 | ARM_Unicorn::Arch::AArch64, | 219 | ARM_Unicorn::Arch::AArch64, |
| 207 | core_index}, | 220 | core_index}, |
| 208 | core_index{core_index}, exclusive_monitor{ | 221 | core_index{core_index}, exclusive_monitor{ |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index c26b47249..31ec16521 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h | |||
| @@ -28,7 +28,7 @@ class System; | |||
| 28 | 28 | ||
| 29 | class ARM_Dynarmic_64 final : public ARM_Interface { | 29 | class ARM_Dynarmic_64 final : public ARM_Interface { |
| 30 | public: | 30 | public: |
| 31 | ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handlers, | 31 | ARM_Dynarmic_64(System& system, CPUInterrupts& interrupt_handlers, bool uses_wall_clock, |
| 32 | ExclusiveMonitor& exclusive_monitor, std::size_t core_index); | 32 | ExclusiveMonitor& exclusive_monitor, std::size_t core_index); |
| 33 | ~ARM_Dynarmic_64() override; | 33 | ~ARM_Dynarmic_64() override; |
| 34 | 34 | ||
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index 099229c8d..1cb71942b 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp | |||
| @@ -63,9 +63,9 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si | |||
| 63 | return false; | 63 | return false; |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | ARM_Unicorn::ARM_Unicorn(System& system, CPUInterruptHandler& interrupt_handler, Arch architecture, | 66 | ARM_Unicorn::ARM_Unicorn(System& system, CPUInterruptHandler& interrupt_handler, |
| 67 | std::size_t core_index) | 67 | bool uses_wall_clock, Arch architecture, std::size_t core_index) |
| 68 | : ARM_Interface{system, interrupt_handler}, core_index{core_index} { | 68 | : ARM_Interface{system, interrupt_handler, uses_wall_clock}, core_index{core_index} { |
| 69 | const auto arch = architecture == Arch::AArch32 ? UC_ARCH_ARM : UC_ARCH_ARM64; | 69 | const auto arch = architecture == Arch::AArch32 ? UC_ARCH_ARM : UC_ARCH_ARM64; |
| 70 | CHECKED(uc_open(arch, UC_MODE_ARM, &uc)); | 70 | CHECKED(uc_open(arch, UC_MODE_ARM, &uc)); |
| 71 | 71 | ||
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h index f09b24a85..a01751e65 100644 --- a/src/core/arm/unicorn/arm_unicorn.h +++ b/src/core/arm/unicorn/arm_unicorn.h | |||
| @@ -20,8 +20,8 @@ public: | |||
| 20 | AArch64, // 64-bit ARM | 20 | AArch64, // 64-bit ARM |
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | explicit ARM_Unicorn(System& system, CPUInterruptHandler& interrupt_handler, Arch architecture, | 23 | explicit ARM_Unicorn(System& system, CPUInterruptHandler& interrupt_handler, |
| 24 | std::size_t core_index); | 24 | bool uses_wall_clock, Arch architecture, std::size_t core_index); |
| 25 | ~ARM_Unicorn() override; | 25 | ~ARM_Unicorn() override; |
| 26 | 26 | ||
| 27 | void SetPC(u64 pc) override; | 27 | void SetPC(u64 pc) override; |