Skip to content
Permalink
Browse files
Merge pull request #11717 from AdmiralCurtiss/ppcstate-rest
Replace most remaining global ppcState references.
  • Loading branch information
lioncash committed Apr 7, 2023
2 parents 74da389 + 62de9c5 commit 5686c61
Show file tree
Hide file tree
Showing 27 changed files with 289 additions and 258 deletions.
@@ -16,6 +16,7 @@
#include "Core/PowerPC/Expression.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

bool BreakPoints::IsAddressBreakPoint(u32 address) const
@@ -352,14 +353,14 @@ bool MemChecks::OverlapsMemcheck(u32 address, u32 length) const
});
}

bool TMemCheck::Action(Common::DebugInterface* debug_interface, u64 value, u32 addr, bool write,
size_t size, u32 pc)
bool TMemCheck::Action(Core::System& system, Common::DebugInterface* debug_interface, u64 value,
u32 addr, bool write, size_t size, u32 pc)
{
if (!is_enabled)
return false;

if (((write && is_break_on_write) || (!write && is_break_on_read)) &&
EvaluateCondition(this->condition))
EvaluateCondition(system, this->condition))
{
if (log_on_hit)
{
@@ -45,8 +45,8 @@ struct TMemCheck
std::optional<Expression> condition;

// returns whether to break
bool Action(Common::DebugInterface* debug_interface, u64 value, u32 addr, bool write, size_t size,
u32 pc);
bool Action(Core::System& system, Common::DebugInterface* debug_interface, u64 value, u32 addr,
bool write, size_t size, u32 pc);
};

// Code breakpoints.
@@ -267,21 +267,22 @@ std::optional<Expression> Expression::TryParse(std::string_view text)
return Expression{text, std::move(ex), std::move(vars)};
}

double Expression::Evaluate() const
double Expression::Evaluate(Core::System& system) const
{
SynchronizeBindings(SynchronizeDirection::From);
SynchronizeBindings(system, SynchronizeDirection::From);

double result = expr_eval(m_expr.get());

SynchronizeBindings(SynchronizeDirection::To);
SynchronizeBindings(system, SynchronizeDirection::To);

Reporting(result);

return result;
}

void Expression::SynchronizeBindings(SynchronizeDirection dir) const
void Expression::SynchronizeBindings(Core::System& system, SynchronizeDirection dir) const
{
auto& ppc_state = system.GetPPCState();
auto bind = m_binds.begin();
for (auto* v = m_vars->head; v != nullptr; v = v->next, ++bind)
{
@@ -293,25 +294,25 @@ void Expression::SynchronizeBindings(SynchronizeDirection dir) const
break;
case VarBindingType::GPR:
if (dir == SynchronizeDirection::From)
v->value = static_cast<double>(PowerPC::ppcState.gpr[bind->index]);
v->value = static_cast<double>(ppc_state.gpr[bind->index]);
else
PowerPC::ppcState.gpr[bind->index] = static_cast<u32>(static_cast<s64>(v->value));
ppc_state.gpr[bind->index] = static_cast<u32>(static_cast<s64>(v->value));
break;
case VarBindingType::FPR:
if (dir == SynchronizeDirection::From)
v->value = PowerPC::ppcState.ps[bind->index].PS0AsDouble();
v->value = ppc_state.ps[bind->index].PS0AsDouble();
else
PowerPC::ppcState.ps[bind->index].SetPS0(v->value);
ppc_state.ps[bind->index].SetPS0(v->value);
break;
case VarBindingType::SPR:
if (dir == SynchronizeDirection::From)
v->value = static_cast<double>(PowerPC::ppcState.spr[bind->index]);
v->value = static_cast<double>(ppc_state.spr[bind->index]);
else
PowerPC::ppcState.spr[bind->index] = static_cast<u32>(static_cast<s64>(v->value));
ppc_state.spr[bind->index] = static_cast<u32>(static_cast<s64>(v->value));
break;
case VarBindingType::PCtr:
if (dir == SynchronizeDirection::From)
v->value = static_cast<double>(PowerPC::ppcState.pc);
v->value = static_cast<double>(ppc_state.pc);
break;
}
}
@@ -15,7 +15,8 @@ struct expr_var_list;
namespace Core
{
class CPUThreadGuard;
}
class System;
} // namespace Core

struct ExprDeleter
{
@@ -36,7 +37,7 @@ class Expression
public:
static std::optional<Expression> TryParse(std::string_view text);

double Evaluate() const;
double Evaluate(Core::System& system) const;

std::string GetText() const;

@@ -64,7 +65,7 @@ class Expression

Expression(std::string_view text, ExprPointer ex, ExprVarListPointer vars);

void SynchronizeBindings(SynchronizeDirection dir) const;
void SynchronizeBindings(Core::System& system, SynchronizeDirection dir) const;
void Reporting(const double result) const;

std::string m_text;
@@ -73,7 +74,7 @@ class Expression
std::vector<VarBinding> m_binds;
};

inline bool EvaluateCondition(const std::optional<Expression>& condition)
inline bool EvaluateCondition(Core::System& system, const std::optional<Expression>& condition)
{
return !condition || condition->Evaluate() != 0.0;
return !condition || condition->Evaluate(system) != 0.0;
}
@@ -120,13 +120,13 @@ int Interpreter::SingleStepInner()
// TODO: Does it make sense to use m_prev_inst here?
// It seems like we should use the num_cycles for the instruction at PC instead
// (m_prev_inst has not yet been updated)
return PPCTables::GetOpInfo(m_prev_inst)->num_cycles;
return PPCTables::GetOpInfo(m_prev_inst, m_ppc_state.pc)->num_cycles;
}

m_ppc_state.npc = m_ppc_state.pc + sizeof(UGeckoInstruction);
m_prev_inst.hex = m_mmu.Read_Opcode(m_ppc_state.pc);

const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst);
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(m_prev_inst, m_ppc_state.pc);

// Uncomment to trace the interpreter
// if ((m_ppc_state.pc & 0x00FFFFFF) >= 0x000AB54C &&
@@ -32,7 +32,7 @@ struct PowerPCState;

// Use these to control the instruction selection
// #define INSTRUCTION_START FallBackToInterpreter(inst); return;
// #define INSTRUCTION_START PPCTables::CountInstruction(inst);
// #define INSTRUCTION_START PPCTables::CountInstruction(inst, m_ppc_state.pc);
#define INSTRUCTION_START

#define FALLBACK_IF(cond) \
@@ -163,14 +163,13 @@ JitInterface::GetHostCode(u32 address) const
return GetHostCodeError::NoJitActive;
}

JitBlock* block =
m_jit->GetBlockCache()->GetBlockFromStartAddress(address, PowerPC::ppcState.msr.Hex);
auto& ppc_state = m_system.GetPPCState();
JitBlock* block = m_jit->GetBlockCache()->GetBlockFromStartAddress(address, ppc_state.msr.Hex);
if (!block)
{
for (int i = 0; i < 500; i++)
{
block = m_jit->GetBlockCache()->GetBlockFromStartAddress(address - 4 * i,
PowerPC::ppcState.msr.Hex);
block = m_jit->GetBlockCache()->GetBlockFromStartAddress(address - 4 * i, ppc_state.msr.Hex);
if (block)
break;
}
@@ -287,25 +286,26 @@ void JitInterface::CompileExceptionCheck(ExceptionType type)
break;
}

if (PowerPC::ppcState.pc != 0 &&
(exception_addresses->find(PowerPC::ppcState.pc)) == (exception_addresses->end()))
auto& ppc_state = m_system.GetPPCState();
if (ppc_state.pc != 0 &&
(exception_addresses->find(ppc_state.pc)) == (exception_addresses->end()))
{
if (type == ExceptionType::FIFOWrite)
{
ASSERT(Core::IsCPUThread());
Core::CPUThreadGuard guard(Core::System::GetInstance());
Core::CPUThreadGuard guard(m_system);

// Check in case the code has been replaced since: do we need to do this?
const OpType optype =
PPCTables::GetOpInfo(PowerPC::MMU::HostRead_U32(guard, PowerPC::ppcState.pc))->type;
PPCTables::GetOpInfo(PowerPC::MMU::HostRead_U32(guard, ppc_state.pc), ppc_state.pc)->type;
if (optype != OpType::Store && optype != OpType::StoreFP && optype != OpType::StorePS)
return;
}
exception_addresses->insert(PowerPC::ppcState.pc);
exception_addresses->insert(ppc_state.pc);

// Invalidate the JIT block so that it gets recompiled with the external exception check
// included.
m_jit->GetBlockCache()->InvalidateICache(PowerPC::ppcState.pc, 4, true);
m_jit->GetBlockCache()->InvalidateICache(ppc_state.pc, 4, true);
}
}

@@ -545,7 +545,8 @@ void MMU::Memcheck(u32 address, u64 var, bool write, size_t size)

mc->num_hits++;

const bool pause = mc->Action(&debug_interface, var, address, write, size, m_ppc_state.pc);
const bool pause =
mc->Action(m_system, &debug_interface, var, address, write, size, m_ppc_state.pc);
if (!pause)
return;

@@ -114,7 +114,7 @@ bool AnalyzeFunction(const Core::CPUThreadGuard& guard, u32 startAddr, Common::S
}
const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr);
const UGeckoInstruction instr = read_result.hex;
if (read_result.valid && PPCTables::IsValidInstruction(instr))
if (read_result.valid && PPCTables::IsValidInstruction(instr, addr))
{
// BLR or RFI
// 4e800021 is blrl, not the end of a function
@@ -274,7 +274,7 @@ static void FindFunctionsFromBranches(const Core::CPUThreadGuard& guard, u32 sta
const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(addr);
const UGeckoInstruction instr = read_result.hex;

if (read_result.valid && PPCTables::IsValidInstruction(instr))
if (read_result.valid && PPCTables::IsValidInstruction(instr, addr))
{
switch (instr.OPCD)
{
@@ -323,7 +323,7 @@ static void FindFunctionsFromHandlers(const Core::CPUThreadGuard& guard, PPCSymb
for (const auto& entry : handlers)
{
const PowerPC::TryReadInstResult read_result = mmu.TryReadInstruction(entry.first);
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex))
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex, entry.first))
{
// Check if this function is already mapped
Common::Symbol* f = func_db->AddFunction(guard, entry.first);
@@ -357,7 +357,7 @@ static void FindFunctionsAfterReturnInstruction(const Core::CPUThreadGuard& guar
location += 4;
read_result = mmu.TryReadInstruction(location);
}
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex))
if (read_result.valid && PPCTables::IsValidInstruction(read_result.hex, location))
{
// check if this function is already mapped
Common::Symbol* f = func_db->AddFunction(guard, location);
@@ -778,7 +778,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer,
num_inst++;

const UGeckoInstruction inst = result.hex;
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(inst);
const GekkoOPInfo* opinfo = PPCTables::GetOpInfo(inst, address);
code[i] = {};
code[i].opinfo = opinfo;
code[i].address = address;
@@ -392,19 +392,21 @@ void Cache::DoState(PointerWrap& p)
u32 InstructionCache::ReadInstruction(u32 addr)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
auto& ppc_state = system.GetPPCState();

if (!HID0(PowerPC::ppcState).ICE || m_disable_icache) // instruction cache is disabled
return memory.Read_U32(addr);
if (!HID0(ppc_state).ICE || m_disable_icache) // instruction cache is disabled
return system.GetMemory().Read_U32(addr);

u32 value;
Read(addr, &value, sizeof(value), HID0(PowerPC::ppcState).ILOCK);
Read(addr, &value, sizeof(value), HID0(ppc_state).ILOCK);
return Common::swap32(value);
}

void InstructionCache::Invalidate(u32 addr)
{
if (!HID0(PowerPC::ppcState).ICE || m_disable_icache)
auto& system = Core::System::GetInstance();
auto& ppc_state = system.GetPPCState();
if (!HID0(ppc_state).ICE || m_disable_icache)
return;

// Invalidates the whole set
@@ -424,7 +426,7 @@ void InstructionCache::Invalidate(u32 addr)
valid[set] = 0;
modified[set] = 0;

Core::System::GetInstance().GetJitInterface().InvalidateICacheLine(addr);
system.GetJitInterface().InvalidateICacheLine(addr);
}

void InstructionCache::RefreshConfig()
@@ -613,7 +613,7 @@ constexpr Tables s_tables = []() consteval
}
();

const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst)
const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst, u32 pc)
{
const GekkoOPInfo* info = &s_tables.all_instructions[s_tables.primary_table[inst.OPCD]];
if (info->type == OpType::Subtable)
@@ -631,17 +631,15 @@ const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst)
case 63:
return &s_tables.all_instructions[s_tables.table63[inst.SUBOP10]];
default:
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid subtable op {:08x} @ {:08x}", inst.hex,
PowerPC::ppcState.pc);
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid subtable op {:08x} @ {:08x}", inst.hex, pc);
return &s_tables.all_instructions[s_tables.unknown_op_info];
}
}
else
{
if (info->type == OpType::Invalid)
{
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid op {:08x} @ {:08x}", inst.hex,
PowerPC::ppcState.pc);
ASSERT_MSG(POWERPC, 0, "GetOpInfo - invalid op {:08x} @ {:08x}", inst.hex, pc);
return &s_tables.all_instructions[s_tables.unknown_op_info];
}
return info;
@@ -658,21 +656,21 @@ std::vector<u32> rsplocations;
}
#endif

const char* GetInstructionName(UGeckoInstruction inst)
const char* GetInstructionName(UGeckoInstruction inst, u32 pc)
{
const GekkoOPInfo* info = GetOpInfo(inst);
const GekkoOPInfo* info = GetOpInfo(inst, pc);
return info->opname;
}

bool IsValidInstruction(UGeckoInstruction inst)
bool IsValidInstruction(UGeckoInstruction inst, u32 pc)
{
const GekkoOPInfo* info = GetOpInfo(inst);
const GekkoOPInfo* info = GetOpInfo(inst, pc);
return info->type != OpType::Invalid && info->type != OpType::Unknown;
}

void CountInstruction(UGeckoInstruction inst)
void CountInstruction(UGeckoInstruction inst, u32 pc)
{
const GekkoOPInfo* info = GetOpInfo(inst);
const GekkoOPInfo* info = GetOpInfo(inst, pc);
info->stats->run_count++;
}

@@ -118,13 +118,13 @@ struct GekkoOPInfo

namespace PPCTables
{
const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst);
const GekkoOPInfo* GetOpInfo(UGeckoInstruction inst, u32 pc);

bool IsValidInstruction(UGeckoInstruction inst);
bool IsValidInstruction(UGeckoInstruction inst, u32 pc);

void CountInstruction(UGeckoInstruction inst);
void CountInstruction(UGeckoInstruction inst, u32 pc);
void CountInstructionCompile(const GekkoOPInfo* info, u32 pc);
void PrintInstructionRunCounts();
void LogCompiledInstructions();
const char* GetInstructionName(UGeckoInstruction inst);
const char* GetInstructionName(UGeckoInstruction inst, u32 pc);
} // namespace PPCTables
@@ -645,7 +645,7 @@ void CheckBreakPoints()
{
const TBreakPoint* bp = PowerPC::breakpoints.GetBreakpoint(PowerPC::ppcState.pc);

if (!bp || !bp->is_enabled || !EvaluateCondition(bp->condition))
if (!bp || !bp->is_enabled || !EvaluateCondition(Core::System::GetInstance(), bp->condition))
return;

if (bp->break_on_hit)

0 comments on commit 5686c61

Please sign in to comment.