diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 533067d4f..70462b407 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -148,6 +148,9 @@ public: s64 down_count = 0; ///< A decreasing counter of remaining cycles before the next event, decreased by the cpu run loop + /// Clears any cached state. Call when instructions in memory change to avoid executing stale cached instructions (e.g.: CROs). + virtual void ClearCache() = 0; + protected: /** diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index 947f5094b..60deba5a4 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -18,6 +18,7 @@ ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) { state = std::make_unique(initial_mode); + ClearCache(); } ARM_DynCom::~ARM_DynCom() { @@ -125,3 +126,8 @@ void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { void ARM_DynCom::PrepareReschedule() { state->NumInstrsToExecute = 0; } + +void ARM_DynCom::ClearCache() { + state->instruction_cache.clear(); + InterpreterClearCache(); +} diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 3664fd728..c4a66202d 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -43,6 +43,8 @@ public: void PrepareReschedule() override; void ExecuteInstructions(int num_instructions) override; + void ClearCache() override; + private: std::unique_ptr state; }; diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 9ed61947e..0b661e1d7 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -1144,6 +1144,10 @@ static inline void *AllocBuffer(unsigned int size) { return (void *)&inst_buf[start]; } +void InterpreterClearCache() { + top = 0; +} + static shtop_fp_t get_shtop(unsigned int inst) { if (BIT(inst, 25)) { return DPO(Immediate); diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.h b/src/core/arm/dyncom/arm_dyncom_interpreter.h index 7a46dcc94..5d5b2d52b 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.h +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.h @@ -7,3 +7,4 @@ struct ARMul_State; unsigned InterpreterMainLoop(ARMul_State* state); +void InterpreterClearCache();