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<unsigned>(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<int>(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<void(u64 userdata, int cycles_late)> 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 <catch.hpp>
 
 #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);