PowerPC: Track registers used in memory break point conditions
This commit is contained in:
parent
c528a70e64
commit
8247882d0b
|
@ -306,9 +306,13 @@ void MemChecks::Add(TMemCheck memory_check)
|
|||
{
|
||||
m_mem_checks.emplace_back(std::move(memory_check));
|
||||
}
|
||||
// If this is the first one, clear the JIT cache so it can switch to
|
||||
// watchpoint-compatible code.
|
||||
if (!had_any)
|
||||
|
||||
const bool registers_changed = UpdateRegistersUsedInConditions();
|
||||
|
||||
// If this is the first memcheck, clear the JIT cache so it can switch to watchpoint-compatible
|
||||
// code. Or, if the memcheck's condition wants to read from a new register,
|
||||
// clear the JIT cache to make the slow memory access code flush that register.
|
||||
if (!had_any || registers_changed)
|
||||
m_system.GetJitInterface().ClearCache(guard);
|
||||
m_system.GetMMU().DBATUpdated();
|
||||
}
|
||||
|
@ -336,7 +340,10 @@ bool MemChecks::Remove(u32 address)
|
|||
|
||||
const Core::CPUThreadGuard guard(m_system);
|
||||
m_mem_checks.erase(iter);
|
||||
if (!HasAny())
|
||||
|
||||
const bool registers_changed = UpdateRegistersUsedInConditions();
|
||||
|
||||
if (registers_changed || !HasAny())
|
||||
m_system.GetJitInterface().ClearCache(guard);
|
||||
m_system.GetMMU().DBATUpdated();
|
||||
return true;
|
||||
|
@ -379,6 +386,27 @@ bool MemChecks::OverlapsMemcheck(u32 address, u32 length) const
|
|||
});
|
||||
}
|
||||
|
||||
bool MemChecks::UpdateRegistersUsedInConditions()
|
||||
{
|
||||
BitSet32 gprs_used, fprs_used;
|
||||
for (TMemCheck& mem_check : m_mem_checks)
|
||||
{
|
||||
if (mem_check.condition)
|
||||
{
|
||||
gprs_used |= mem_check.condition->GetGPRsUsed();
|
||||
fprs_used |= mem_check.condition->GetFPRsUsed();
|
||||
}
|
||||
}
|
||||
|
||||
const bool registers_changed =
|
||||
gprs_used != m_gprs_used_in_conditions || fprs_used != m_fprs_used_in_conditions;
|
||||
|
||||
m_gprs_used_in_conditions = gprs_used;
|
||||
m_fprs_used_in_conditions = fprs_used;
|
||||
|
||||
return registers_changed;
|
||||
}
|
||||
|
||||
bool TMemCheck::Action(Core::System& system, u64 value, u32 addr, bool write, size_t size, u32 pc)
|
||||
{
|
||||
if (!is_enabled)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/BitSet.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/PowerPC/Expression.h"
|
||||
|
||||
|
@ -127,7 +128,15 @@ public:
|
|||
void Clear();
|
||||
bool HasAny() const { return !m_mem_checks.empty(); }
|
||||
|
||||
BitSet32 GetGPRsUsedInConditions() { return m_gprs_used_in_conditions; }
|
||||
BitSet32 GetFPRsUsedInConditions() { return m_fprs_used_in_conditions; }
|
||||
|
||||
private:
|
||||
// Returns whether any change was made
|
||||
bool UpdateRegistersUsedInConditions();
|
||||
|
||||
TMemChecks m_mem_checks;
|
||||
Core::System& m_system;
|
||||
BitSet32 m_gprs_used_in_conditions;
|
||||
BitSet32 m_fprs_used_in_conditions;
|
||||
};
|
||||
|
|
|
@ -495,3 +495,22 @@ std::string Expression::GetText() const
|
|||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
void Expression::ComputeRegistersUsed()
|
||||
{
|
||||
if (m_has_computed_registers_used)
|
||||
return;
|
||||
|
||||
for (const VarBinding& bind : m_binds)
|
||||
{
|
||||
switch (bind.type)
|
||||
{
|
||||
case VarBindingType::GPR:
|
||||
m_gprs_used[bind.index] = true;
|
||||
break;
|
||||
case VarBindingType::FPR:
|
||||
m_fprs_used[bind.index] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/BitSet.h"
|
||||
|
||||
struct expr;
|
||||
struct expr_var_list;
|
||||
|
||||
|
@ -41,6 +43,18 @@ public:
|
|||
|
||||
std::string GetText() const;
|
||||
|
||||
BitSet32 GetGPRsUsed()
|
||||
{
|
||||
ComputeRegistersUsed();
|
||||
return m_gprs_used;
|
||||
}
|
||||
|
||||
BitSet32 GetFPRsUsed()
|
||||
{
|
||||
ComputeRegistersUsed();
|
||||
return m_fprs_used;
|
||||
}
|
||||
|
||||
private:
|
||||
enum class SynchronizeDirection
|
||||
{
|
||||
|
@ -69,10 +83,16 @@ private:
|
|||
void SynchronizeBindings(Core::System& system, SynchronizeDirection dir) const;
|
||||
void Reporting(const double result) const;
|
||||
|
||||
void ComputeRegistersUsed();
|
||||
|
||||
std::string m_text;
|
||||
ExprPointer m_expr;
|
||||
ExprVarListPointer m_vars;
|
||||
std::vector<VarBinding> m_binds;
|
||||
|
||||
BitSet32 m_gprs_used;
|
||||
BitSet32 m_fprs_used;
|
||||
bool m_has_computed_registers_used = false;
|
||||
};
|
||||
|
||||
inline bool EvaluateCondition(Core::System& system, const std::optional<Expression>& condition)
|
||||
|
|
Loading…
Reference in New Issue