From f5bfce657c90219cebe933978c91f2d1e3d0d1e6 Mon Sep 17 00:00:00 2001
From: EmptyChaos <EmptyChaos@users.noreply.github.com>
Date: Thu, 8 Sep 2016 06:42:43 +0000
Subject: [PATCH] CachedInterpreter: Fix CoreTiming contract

Call CoreTiming::Advance() before executing the slice, not after.
---
 .../Core/Core/PowerPC/CachedInterpreter.cpp   | 66 +++++++++++--------
 Source/Core/Core/PowerPC/CachedInterpreter.h  |  3 +-
 2 files changed, 39 insertions(+), 30 deletions(-)

diff --git a/Source/Core/Core/PowerPC/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter.cpp
index 5a560d9d24..de7aa218ae 100644
--- a/Source/Core/Core/PowerPC/CachedInterpreter.cpp
+++ b/Source/Core/Core/PowerPC/CachedInterpreter.cpp
@@ -32,49 +32,57 @@ void CachedInterpreter::Shutdown()
   JitBaseBlockCache::Shutdown();
 }
 
+void CachedInterpreter::ExecuteOneBlock()
+{
+  const u8* normal_entry = JitBaseBlockCache::Dispatch();
+  const Instruction* code = reinterpret_cast<const Instruction*>(normal_entry);
+
+  for (; code->type != Instruction::INSTRUCTION_ABORT; ++code)
+  {
+    switch (code->type)
+    {
+    case Instruction::INSTRUCTION_TYPE_COMMON:
+      code->common_callback(UGeckoInstruction(code->data));
+      break;
+
+    case Instruction::INSTRUCTION_TYPE_CONDITIONAL:
+      if (code->conditional_callback(code->data))
+        return;
+      break;
+
+    default:
+      ERROR_LOG(POWERPC, "Unknown CachedInterpreter Instruction: %d", code->type);
+      break;
+    }
+  }
+}
+
 void CachedInterpreter::Run()
 {
-  while (!CPU::GetState())
+  while (CPU::GetState() == CPU::CPU_RUNNING)
   {
-    SingleStep();
+    // Start new timing slice
+    // NOTE: Exceptions may change PC
+    CoreTiming::Advance();
+
+    do
+    {
+      ExecuteOneBlock();
+    } while (PowerPC::ppcState.downcount > 0);
   }
 }
 
 void CachedInterpreter::SingleStep()
 {
-  const u8* normalEntry = jit->GetBlockCache()->Dispatch();
-  const Instruction* code = reinterpret_cast<const Instruction*>(normalEntry);
-
-  while (true)
-  {
-    switch (code->type)
-    {
-    case Instruction::INSTRUCTION_ABORT:
-      return;
-
-    case Instruction::INSTRUCTION_TYPE_COMMON:
-      code->common_callback(UGeckoInstruction(code->data));
-      code++;
-      break;
-
-    case Instruction::INSTRUCTION_TYPE_CONDITIONAL:
-      bool ret = code->conditional_callback(code->data);
-      code++;
-      if (ret)
-        return;
-      break;
-    }
-  }
+  // Enter new timing slice
+  CoreTiming::Advance();
+  ExecuteOneBlock();
 }
 
 static void EndBlock(UGeckoInstruction data)
 {
   PC = NPC;
   PowerPC::ppcState.downcount -= data.hex;
-  if (PowerPC::ppcState.downcount <= 0)
-  {
-    CoreTiming::Advance();
-  }
 }
 
 static void WritePC(UGeckoInstruction data)
diff --git a/Source/Core/Core/PowerPC/CachedInterpreter.h b/Source/Core/Core/PowerPC/CachedInterpreter.h
index f91322eb4d..3b2423e9ee 100644
--- a/Source/Core/Core/PowerPC/CachedInterpreter.h
+++ b/Source/Core/Core/PowerPC/CachedInterpreter.h
@@ -56,7 +56,8 @@ private:
   };
 
   const u8* GetCodePtr() { return (u8*)(m_code.data() + m_code.size()); }
-  std::vector<Instruction> m_code;
+  void ExecuteOneBlock();
 
+  std::vector<Instruction> m_code;
   PPCAnalyst::CodeBuffer code_buffer;
 };