diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 2aa017a54..ba528403c 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -124,12 +124,6 @@ public: */ virtual void SetCP15Register(CP15Register reg, u32 value) = 0; - /** - * Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time) - * @param ticks Number of ticks to advance the CPU core - */ - virtual void AddTicks(u64 ticks) = 0; - /** * Saves the current CPU context * @param ctx Thread context to save @@ -150,9 +144,6 @@ public: return num_instructions; } - s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, - /// decreased by the cpu run loop - protected: /** * Executes the given number of instructions diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 42ae93ae8..2cb56d12f 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -124,13 +124,6 @@ void ARM_Dynarmic::SetCP15Register(CP15Register reg, u32 value) { interpreter_state->CP15[reg] = value; } -void ARM_Dynarmic::AddTicks(u64 ticks) { - down_count -= ticks; - if (down_count < 0) { - CoreTiming::Advance(); - } -} - MICROPROFILE_DEFINE(ARM_Jit, "ARM JIT", "ARM JIT", MP_RGB(255, 64, 64)); void ARM_Dynarmic::ExecuteInstructions(int num_instructions) { @@ -139,7 +132,7 @@ void ARM_Dynarmic::ExecuteInstructions(int num_instructions) { std::size_t ticks_executed = jit->Run(static_cast(num_instructions)); - AddTicks(ticks_executed); + CoreTiming::AddTicks(ticks_executed); } void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) { diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 96148a1a5..0b00158a5 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -32,8 +32,6 @@ public: u32 GetCP15Register(CP15Register reg) override; void SetCP15Register(CP15Register reg, u32 value) override; - void AddTicks(u64 ticks) override; - void SaveContext(ThreadContext& ctx) override; void LoadContext(const ThreadContext& ctx) override; diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index da955c9b9..4d72aef77 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -77,12 +77,6 @@ void ARM_DynCom::SetCP15Register(CP15Register reg, u32 value) { state->CP15[reg] = value; } -void ARM_DynCom::AddTicks(u64 ticks) { - down_count -= ticks; - if (down_count < 0) - CoreTiming::Advance(); -} - void ARM_DynCom::ExecuteInstructions(int num_instructions) { state->NumInstrsToExecute = num_instructions; @@ -90,7 +84,7 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) { // executing one instruction at a time. Otherwise, if a block is being executed, more // instructions may actually be executed than specified. unsigned ticks_executed = InterpreterMainLoop(state.get()); - AddTicks(ticks_executed); + CoreTiming::AddTicks(ticks_executed); } void ARM_DynCom::SaveContext(ThreadContext& ctx) { diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 0ae535671..fc1ffed6a 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -31,8 +31,6 @@ public: u32 GetCP15Register(CP15Register reg) override; void SetCP15Register(CP15Register reg, u32 value) override; - void AddTicks(u64 ticks) override; - void SaveContext(ThreadContext& ctx) override; void LoadContext(const ThreadContext& ctx) override; diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 276ecfdf6..5e2a5d00f 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -57,6 +57,9 @@ static s64 idled_cycles; static s64 last_global_time_ticks; static s64 last_global_time_us; +static s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, + /// decreased by the cpu run loop + static std::recursive_mutex external_event_section; // Warning: not included in save state. @@ -146,7 +149,7 @@ void UnregisterAllEvents() { } void Init() { - Core::CPU().down_count = INITIAL_SLICE_LENGTH; + down_count = INITIAL_SLICE_LENGTH; g_slice_length = INITIAL_SLICE_LENGTH; global_timer = 0; idled_cycles = 0; @@ -185,8 +188,15 @@ void Shutdown() { } } +void AddTicks(u64 ticks) { + down_count -= ticks; + if (down_count < 0) { + Advance(); + } +} + u64 GetTicks() { - return (u64)global_timer + g_slice_length - Core::CPU().down_count; + return (u64)global_timer + g_slice_length - down_count; } u64 GetIdleTicks() { @@ -460,18 +470,18 @@ void MoveEvents() { } void ForceCheck() { - s64 cycles_executed = g_slice_length - Core::CPU().down_count; + s64 cycles_executed = g_slice_length - down_count; global_timer += cycles_executed; // This will cause us to check for new events immediately. - Core::CPU().down_count = 0; + down_count = 0; // But let's not eat a bunch more time in Advance() because of this. g_slice_length = 0; } void Advance() { - s64 cycles_executed = g_slice_length - Core::CPU().down_count; + s64 cycles_executed = g_slice_length - down_count; global_timer += cycles_executed; - Core::CPU().down_count = g_slice_length; + down_count = g_slice_length; if (has_ts_events) MoveEvents(); @@ -480,7 +490,7 @@ void Advance() { if (!first) { if (g_slice_length < 10000) { g_slice_length += 10000; - Core::CPU().down_count += g_slice_length; + down_count += g_slice_length; } } else { // Note that events can eat cycles as well. @@ -490,7 +500,7 @@ void Advance() { const int diff = target - g_slice_length; g_slice_length += diff; - Core::CPU().down_count += diff; + down_count += diff; } if (advance_callback) advance_callback(static_cast(cycles_executed)); @@ -506,12 +516,12 @@ void LogPendingEvents() { } void Idle(int max_idle) { - s64 cycles_down = Core::CPU().down_count; + s64 cycles_down = down_count; if (max_idle != 0 && cycles_down > max_idle) cycles_down = max_idle; if (first && cycles_down > 0) { - s64 cycles_executed = g_slice_length - Core::CPU().down_count; + s64 cycles_executed = g_slice_length - down_count; s64 cycles_next_event = first->time - global_timer; if (cycles_next_event < cycles_executed + cycles_down) { @@ -526,9 +536,9 @@ void Idle(int max_idle) { cycles_down / (float)(g_clock_rate_arm11 * 0.001f)); idled_cycles += cycles_down; - Core::CPU().down_count -= cycles_down; - if (Core::CPU().down_count == 0) - Core::CPU().down_count = -1; + down_count -= cycles_down; + if (down_count == 0) + down_count = -1; } std::string GetScheduledEventsSummary() { diff --git a/src/core/core_timing.h b/src/core/core_timing.h index d2f85cd4d..897350801 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h @@ -67,6 +67,12 @@ void Shutdown(); typedef void (*MHzChangeCallback)(); typedef std::function TimedCallback; +/** +* Advance the CPU core by the specified number of ticks (e.g. to simulate CPU execution time) +* @param ticks Number of ticks to advance the CPU core +*/ +void AddTicks(u64 ticks); + u64 GetTicks(); u64 GetIdleTicks(); u64 GetGlobalTimeUs(); diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index fefd50805..6be5db13f 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -1039,7 +1039,7 @@ static void SleepThread(s64 nanoseconds) { static s64 GetSystemTick() { s64 result = CoreTiming::GetTicks(); // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end. - Core::CPU().AddTicks(150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b + CoreTiming::AddTicks(150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b return result; } diff --git a/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp b/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp index 86de41773..83719a58e 100644 --- a/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp +++ b/src/tests/core/arm/dyncom/arm_dyncom_vfp_tests.cpp @@ -5,6 +5,7 @@ #include #include "core/arm/dyncom/arm_dyncom.h" +#include "core/core_timing.h" #include "tests/core/arm/arm_test_common.h" namespace ArmTests { @@ -29,7 +30,6 @@ TEST_CASE("ARM_DynCom (vfp): vadd", "[arm_dyncom]") { }}; for (const auto& test_case : test_cases) { - dyncom.down_count = 1000; // Ensure that CoreTimeing will not be called. dyncom.SetPC(0); dyncom.SetVFPSystemReg(VFP_FPSCR, test_case.initial_fpscr); dyncom.SetVFPReg(4, test_case.a);