Merge pull request #11741 from AdmiralCurtiss/ppc-class
PowerPC: Refactor to class, move to System.
This commit is contained in:
commit
4c80c992eb
|
@ -126,16 +126,18 @@ InstructionAttributes CodeTrace::GetInstructionAttributes(const TraceOutput& ins
|
|||
TraceOutput CodeTrace::SaveCurrentInstruction(const Core::CPUThreadGuard& guard) const
|
||||
{
|
||||
auto& system = guard.GetSystem();
|
||||
auto& ppc_state = system.GetPPCState();
|
||||
auto& power_pc = system.GetPowerPC();
|
||||
auto& ppc_state = power_pc.GetPPCState();
|
||||
auto& debug_interface = power_pc.GetDebugInterface();
|
||||
|
||||
// Quickly save instruction and memory target for fast logging.
|
||||
TraceOutput output;
|
||||
const std::string instr = PowerPC::debug_interface.Disassemble(&guard, ppc_state.pc);
|
||||
const std::string instr = debug_interface.Disassemble(&guard, ppc_state.pc);
|
||||
output.instruction = instr;
|
||||
output.address = ppc_state.pc;
|
||||
|
||||
if (IsInstructionLoadStore(output.instruction))
|
||||
output.memory_target = PowerPC::debug_interface.GetMemoryAddressFromInstruction(instr);
|
||||
output.memory_target = debug_interface.GetMemoryAddressFromInstruction(instr);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
@ -189,16 +191,17 @@ AutoStepResults CodeTrace::AutoStepping(const Core::CPUThreadGuard& guard, bool
|
|||
else if (stop_on == AutoStop::Changed)
|
||||
stop_condition = HitType::ACTIVE;
|
||||
|
||||
PowerPC::breakpoints.ClearAllTemporary();
|
||||
auto& power_pc = guard.GetSystem().GetPowerPC();
|
||||
power_pc.GetBreakPoints().ClearAllTemporary();
|
||||
using clock = std::chrono::steady_clock;
|
||||
clock::time_point timeout = clock::now() + std::chrono::seconds(4);
|
||||
|
||||
PowerPC::CoreMode old_mode = PowerPC::GetMode();
|
||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||
PowerPC::CoreMode old_mode = power_pc.GetMode();
|
||||
power_pc.SetMode(PowerPC::CoreMode::Interpreter);
|
||||
|
||||
do
|
||||
{
|
||||
PowerPC::SingleStep();
|
||||
power_pc.SingleStep();
|
||||
|
||||
pc_instr = SaveCurrentInstruction(guard);
|
||||
hit = TraceLogic(pc_instr);
|
||||
|
@ -210,7 +213,7 @@ AutoStepResults CodeTrace::AutoStepping(const Core::CPUThreadGuard& guard, bool
|
|||
if (clock::now() >= timeout)
|
||||
results.timed_out = true;
|
||||
|
||||
PowerPC::SetMode(old_mode);
|
||||
power_pc.SetMode(old_mode);
|
||||
m_recording = false;
|
||||
|
||||
results.reg_tracked = m_reg_autotrack;
|
||||
|
|
|
@ -57,13 +57,14 @@ void PresetTimeBaseTicks(Core::System& system, const Core::CPUThreadGuard& guard
|
|||
|
||||
void CBoot::RunFunction(Core::System& system, u32 address)
|
||||
{
|
||||
auto& ppc_state = system.GetPPCState();
|
||||
auto& power_pc = system.GetPowerPC();
|
||||
auto& ppc_state = power_pc.GetPPCState();
|
||||
|
||||
ppc_state.pc = address;
|
||||
LR(ppc_state) = 0x00;
|
||||
|
||||
while (ppc_state.pc != 0x00)
|
||||
PowerPC::SingleStep();
|
||||
power_pc.SingleStep();
|
||||
}
|
||||
|
||||
void CBoot::SetupMSR(PowerPC::PowerPCState& ppc_state)
|
||||
|
|
|
@ -435,7 +435,8 @@ static void FifoPlayerThread(const std::optional<std::string>& savestate_path,
|
|||
{
|
||||
DeclareAsCPUThread();
|
||||
|
||||
if (Core::System::GetInstance().IsDualCoreMode())
|
||||
auto& system = Core::System::GetInstance();
|
||||
if (system.IsDualCoreMode())
|
||||
Common::SetCurrentThreadName("FIFO player thread");
|
||||
else
|
||||
Common::SetCurrentThreadName("FIFO-GPU thread");
|
||||
|
@ -443,15 +444,14 @@ static void FifoPlayerThread(const std::optional<std::string>& savestate_path,
|
|||
// Enter CPU run loop. When we leave it - we are done.
|
||||
if (auto cpu_core = FifoPlayer::GetInstance().GetCPUCore())
|
||||
{
|
||||
PowerPC::InjectExternalCPUCore(cpu_core.get());
|
||||
system.GetPowerPC().InjectExternalCPUCore(cpu_core.get());
|
||||
s_is_started = true;
|
||||
|
||||
CPUSetInitialExecutionState();
|
||||
auto& system = Core::System::GetInstance();
|
||||
system.GetCPU().Run();
|
||||
|
||||
s_is_started = false;
|
||||
PowerPC::InjectExternalCPUCore(nullptr);
|
||||
system.GetPowerPC().InjectExternalCPUCore(nullptr);
|
||||
FifoPlayer::GetInstance().Close();
|
||||
}
|
||||
else
|
||||
|
@ -552,7 +552,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
|||
HLE::Clear();
|
||||
|
||||
CPUThreadGuard guard(system);
|
||||
PowerPC::debug_interface.Clear(guard);
|
||||
system.GetPowerPC().GetDebugInterface().Clear(guard);
|
||||
}};
|
||||
|
||||
VideoBackendBase::PopulateBackendInfo();
|
||||
|
@ -590,7 +590,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
|||
system.GetCPU().Break();
|
||||
|
||||
// Load GCM/DOL/ELF whatever ... we boot with the interpreter core
|
||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||
system.GetPowerPC().SetMode(PowerPC::CoreMode::Interpreter);
|
||||
|
||||
// Determine the CPU thread function
|
||||
void (*cpuThreadFunc)(const std::optional<std::string>& savestate_path, bool delete_savestate);
|
||||
|
@ -628,11 +628,11 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
|||
// Setup our core
|
||||
if (Config::Get(Config::MAIN_CPU_CORE) != PowerPC::CPUCore::Interpreter)
|
||||
{
|
||||
PowerPC::SetMode(PowerPC::CoreMode::JIT);
|
||||
system.GetPowerPC().SetMode(PowerPC::CoreMode::JIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||
system.GetPowerPC().SetMode(PowerPC::CoreMode::Interpreter);
|
||||
}
|
||||
|
||||
UpdateTitle();
|
||||
|
@ -901,7 +901,7 @@ void UpdateTitle()
|
|||
{
|
||||
// Settings are shown the same for both extended and summary info
|
||||
const std::string SSettings = fmt::format(
|
||||
"{} {} | {} | {}", PowerPC::GetCPUName(),
|
||||
"{} {} | {} | {}", Core::System::GetInstance().GetPowerPC().GetCPUName(),
|
||||
Core::System::GetInstance().IsDualCoreMode() ? "DC" : "SC", g_video_backend->GetDisplayName(),
|
||||
Config::Get(Config::MAIN_DSP_HLE) ? "HLE" : "LLE");
|
||||
|
||||
|
|
|
@ -303,8 +303,8 @@ void CoreTimingManager::MoveEvents()
|
|||
|
||||
void CoreTimingManager::Advance()
|
||||
{
|
||||
auto& system = m_system;
|
||||
auto& ppc_state = m_system.GetPPCState();
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
auto& ppc_state = power_pc.GetPPCState();
|
||||
|
||||
MoveEvents();
|
||||
|
||||
|
@ -323,7 +323,7 @@ void CoreTimingManager::Advance()
|
|||
m_event_queue.pop_back();
|
||||
|
||||
Throttle(evt.time);
|
||||
evt.type->callback(system, evt.userdata, m_globals.global_timer - evt.time);
|
||||
evt.type->callback(m_system, evt.userdata, m_globals.global_timer - evt.time);
|
||||
}
|
||||
|
||||
m_is_global_timer_sane = false;
|
||||
|
@ -341,7 +341,7 @@ void CoreTimingManager::Advance()
|
|||
// It's important to do this after processing events otherwise any exceptions will be delayed
|
||||
// until the next slice:
|
||||
// Pokemon Box refuses to boot if the first exception from the audio DMA is received late
|
||||
PowerPC::CheckExternalExceptions();
|
||||
power_pc.CheckExternalExceptions();
|
||||
}
|
||||
|
||||
void CoreTimingManager::Throttle(const s64 target_cycle)
|
||||
|
|
|
@ -32,7 +32,7 @@ void AddAutoBreakpoints()
|
|||
{
|
||||
Common::Symbol* symbol = g_symbolDB.GetSymbolFromName(bp);
|
||||
if (symbol)
|
||||
PowerPC::breakpoints.Add(symbol->address, false);
|
||||
Core::System::GetInstance().GetPowerPC().GetBreakPoints().Add(symbol->address, false);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -36,6 +36,7 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPa
|
|||
if (!PowerPC::MMU::HostIsRAMAddress(guard, address))
|
||||
return;
|
||||
|
||||
auto& power_pc = guard.GetSystem().GetPowerPC();
|
||||
for (u32 offset = 0; offset < size; ++offset)
|
||||
{
|
||||
if (store_existing_value)
|
||||
|
@ -50,11 +51,11 @@ void ApplyMemoryPatch(const Core::CPUThreadGuard& guard, Common::Debug::MemoryPa
|
|||
}
|
||||
|
||||
if (((address + offset) % 4) == 3)
|
||||
PowerPC::ScheduleInvalidateCacheThreadSafe(Common::AlignDown(address + offset, 4));
|
||||
power_pc.ScheduleInvalidateCacheThreadSafe(Common::AlignDown(address + offset, 4));
|
||||
}
|
||||
if (((address + size) % 4) != 0)
|
||||
{
|
||||
PowerPC::ScheduleInvalidateCacheThreadSafe(
|
||||
power_pc.ScheduleInvalidateCacheThreadSafe(
|
||||
Common::AlignDown(address + static_cast<u32>(size), 4));
|
||||
}
|
||||
}
|
||||
|
@ -347,40 +348,41 @@ bool PPCDebugInterface::IsAlive() const
|
|||
|
||||
bool PPCDebugInterface::IsBreakpoint(u32 address) const
|
||||
{
|
||||
return PowerPC::breakpoints.IsAddressBreakPoint(address);
|
||||
return m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(address);
|
||||
}
|
||||
|
||||
void PPCDebugInterface::SetBreakpoint(u32 address)
|
||||
{
|
||||
PowerPC::breakpoints.Add(address);
|
||||
m_system.GetPowerPC().GetBreakPoints().Add(address);
|
||||
}
|
||||
|
||||
void PPCDebugInterface::ClearBreakpoint(u32 address)
|
||||
{
|
||||
PowerPC::breakpoints.Remove(address);
|
||||
m_system.GetPowerPC().GetBreakPoints().Remove(address);
|
||||
}
|
||||
|
||||
void PPCDebugInterface::ClearAllBreakpoints()
|
||||
{
|
||||
PowerPC::breakpoints.Clear();
|
||||
m_system.GetPowerPC().GetBreakPoints().Clear();
|
||||
}
|
||||
|
||||
void PPCDebugInterface::ToggleBreakpoint(u32 address)
|
||||
{
|
||||
if (PowerPC::breakpoints.IsAddressBreakPoint(address))
|
||||
PowerPC::breakpoints.Remove(address);
|
||||
auto& breakpoints = m_system.GetPowerPC().GetBreakPoints();
|
||||
if (breakpoints.IsAddressBreakPoint(address))
|
||||
breakpoints.Remove(address);
|
||||
else
|
||||
PowerPC::breakpoints.Add(address);
|
||||
breakpoints.Add(address);
|
||||
}
|
||||
|
||||
void PPCDebugInterface::ClearAllMemChecks()
|
||||
{
|
||||
PowerPC::memchecks.Clear();
|
||||
m_system.GetPowerPC().GetMemChecks().Clear();
|
||||
}
|
||||
|
||||
bool PPCDebugInterface::IsMemCheck(u32 address, size_t size) const
|
||||
{
|
||||
return PowerPC::memchecks.GetMemCheck(address, size) != nullptr;
|
||||
return m_system.GetPowerPC().GetMemChecks().GetMemCheck(address, size) != nullptr;
|
||||
}
|
||||
|
||||
void PPCDebugInterface::ToggleMemCheck(u32 address, bool read, bool write, bool log)
|
||||
|
@ -397,11 +399,11 @@ void PPCDebugInterface::ToggleMemCheck(u32 address, bool read, bool write, bool
|
|||
MemCheck.log_on_hit = log;
|
||||
MemCheck.break_on_hit = true;
|
||||
|
||||
PowerPC::memchecks.Add(std::move(MemCheck));
|
||||
m_system.GetPowerPC().GetMemChecks().Add(std::move(MemCheck));
|
||||
}
|
||||
else
|
||||
{
|
||||
PowerPC::memchecks.Remove(address);
|
||||
m_system.GetPowerPC().GetMemChecks().Remove(address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ HookFlag GetHookFlagsByIndex(u32 index)
|
|||
bool IsEnabled(HookFlag flag)
|
||||
{
|
||||
return flag != HLE::HookFlag::Debug || Config::Get(Config::MAIN_ENABLE_DEBUGGING) ||
|
||||
PowerPC::GetMode() == PowerPC::CoreMode::Interpreter;
|
||||
Core::System::GetInstance().GetPowerPC().GetMode() == PowerPC::CoreMode::Interpreter;
|
||||
}
|
||||
|
||||
u32 UnPatch(Core::System& system, std::string_view patch_name)
|
||||
|
|
|
@ -19,19 +19,21 @@
|
|||
|
||||
namespace CPU
|
||||
{
|
||||
CPUManager::CPUManager() = default;
|
||||
CPUManager::CPUManager(Core::System& system) : m_system(system)
|
||||
{
|
||||
}
|
||||
CPUManager::~CPUManager() = default;
|
||||
|
||||
void CPUManager::Init(PowerPC::CPUCore cpu_core)
|
||||
{
|
||||
PowerPC::Init(cpu_core);
|
||||
m_system.GetPowerPC().Init(cpu_core);
|
||||
m_state = State::Stepping;
|
||||
}
|
||||
|
||||
void CPUManager::Shutdown()
|
||||
{
|
||||
Stop();
|
||||
PowerPC::Shutdown();
|
||||
m_system.GetPowerPC().Shutdown();
|
||||
}
|
||||
|
||||
// Requires holding m_state_change_lock
|
||||
|
@ -62,11 +64,11 @@ void CPUManager::ExecutePendingJobs(std::unique_lock<std::mutex>& state_lock)
|
|||
|
||||
void CPUManager::Run()
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
|
||||
// Updating the host CPU's rounding mode must be done on the CPU thread.
|
||||
// We can't rely on PowerPC::Init doing it, since it's called from EmuThread.
|
||||
PowerPC::RoundingModeUpdated();
|
||||
PowerPC::RoundingModeUpdated(power_pc.GetPPCState());
|
||||
|
||||
std::unique_lock state_lock(m_state_change_lock);
|
||||
while (m_state != State::PowerDown)
|
||||
|
@ -85,22 +87,22 @@ void CPUManager::Run()
|
|||
// SingleStep so that the "continue", "step over" and "step out" debugger functions
|
||||
// work when the PC is at a breakpoint at the beginning of the block
|
||||
// If watchpoints are enabled, any instruction could be a breakpoint.
|
||||
if (PowerPC::GetMode() != PowerPC::CoreMode::Interpreter)
|
||||
if (power_pc.GetMode() != PowerPC::CoreMode::Interpreter)
|
||||
{
|
||||
if (PowerPC::breakpoints.IsAddressBreakPoint(system.GetPPCState().pc) ||
|
||||
PowerPC::memchecks.HasAny())
|
||||
if (power_pc.GetBreakPoints().IsAddressBreakPoint(power_pc.GetPPCState().pc) ||
|
||||
power_pc.GetMemChecks().HasAny())
|
||||
{
|
||||
m_state = State::Stepping;
|
||||
PowerPC::CoreMode old_mode = PowerPC::GetMode();
|
||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||
PowerPC::SingleStep();
|
||||
PowerPC::SetMode(old_mode);
|
||||
PowerPC::CoreMode old_mode = power_pc.GetMode();
|
||||
power_pc.SetMode(PowerPC::CoreMode::Interpreter);
|
||||
power_pc.SingleStep();
|
||||
power_pc.SetMode(old_mode);
|
||||
m_state = State::Running;
|
||||
}
|
||||
}
|
||||
|
||||
// Enter a fast runloop
|
||||
PowerPC::RunLoop();
|
||||
power_pc.RunLoop();
|
||||
|
||||
state_lock.lock();
|
||||
m_state_cpu_thread_active = false;
|
||||
|
@ -147,7 +149,7 @@ void CPUManager::Run()
|
|||
m_state_cpu_thread_active = true;
|
||||
state_lock.unlock();
|
||||
|
||||
PowerPC::SingleStep();
|
||||
power_pc.SingleStep();
|
||||
|
||||
state_lock.lock();
|
||||
m_state_cpu_thread_active = false;
|
||||
|
|
|
@ -12,7 +12,10 @@ namespace Common
|
|||
{
|
||||
class Event;
|
||||
}
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class System;
|
||||
}
|
||||
namespace PowerPC
|
||||
{
|
||||
enum class CPUCore;
|
||||
|
@ -30,7 +33,7 @@ enum class State
|
|||
class CPUManager
|
||||
{
|
||||
public:
|
||||
CPUManager();
|
||||
explicit CPUManager(Core::System& system);
|
||||
CPUManager(const CPUManager& other) = delete;
|
||||
CPUManager(CPUManager&& other) = delete;
|
||||
CPUManager& operator=(const CPUManager& other) = delete;
|
||||
|
@ -130,5 +133,7 @@ private:
|
|||
bool m_state_cpu_step_instruction = false;
|
||||
Common::Event* m_state_cpu_step_instruction_sync = nullptr;
|
||||
std::queue<std::function<void()>> m_pending_jobs;
|
||||
|
||||
Core::System& m_system;
|
||||
};
|
||||
} // namespace CPU
|
||||
|
|
|
@ -448,7 +448,7 @@ void CEXIETHERNET::SendFromDirectFIFO()
|
|||
const u8* frame = tx_fifo.get();
|
||||
const u16 size = Common::BitCastPtr<u16>(&mBbaMem[BBA_TXFIFOCNT]);
|
||||
if (m_network_interface->SendFrame(frame, size))
|
||||
PowerPC::debug_interface.NetworkLogger()->LogBBA(frame, size);
|
||||
m_system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogBBA(frame, size);
|
||||
}
|
||||
|
||||
void CEXIETHERNET::SendFromPacketBuffer()
|
||||
|
@ -561,7 +561,8 @@ bool CEXIETHERNET::RecvHandlePacket()
|
|||
INFO_LOG_FMT(SP1, "{:x} {:x} {:x} {:x}", page_ptr(BBA_BP), page_ptr(BBA_RRP), page_ptr(BBA_RWP),
|
||||
page_ptr(BBA_RHBP));
|
||||
#endif
|
||||
PowerPC::debug_interface.NetworkLogger()->LogBBA(mRecvBuffer.get(), mRecvBufferLength);
|
||||
m_system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogBBA(mRecvBuffer.get(),
|
||||
mRecvBufferLength);
|
||||
write_ptr = &mBbaMem[page_ptr(BBA_RWP) << 8];
|
||||
|
||||
descriptor = (Descriptor*)write_ptr;
|
||||
|
|
|
@ -223,7 +223,7 @@ void TimeBaseSet()
|
|||
auto& system = Core::System::GetInstance();
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
core_timing.SetFakeTBStartTicks(core_timing.GetTicks());
|
||||
core_timing.SetFakeTBStartValue(PowerPC::ReadFullTimeBaseValue());
|
||||
core_timing.SetFakeTBStartValue(system.GetPowerPC().ReadFullTimeBaseValue());
|
||||
}
|
||||
|
||||
u64 GetFakeTimeBase()
|
||||
|
|
|
@ -200,8 +200,9 @@ static void ResetAndPausePPC()
|
|||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.Write_U32(0x48000000, 0x00000000); // b 0x0
|
||||
PowerPC::Reset();
|
||||
system.GetPPCState().pc = 0;
|
||||
auto& power_pc = system.GetPowerPC();
|
||||
power_pc.Reset();
|
||||
power_pc.GetPPCState().pc = 0;
|
||||
}
|
||||
|
||||
static void ReleasePPC()
|
||||
|
|
|
@ -43,7 +43,7 @@ static void ReinitHardware()
|
|||
// (and not by MIOS), causing games that use DTK to break. Perhaps MIOS doesn't actually
|
||||
// reset DI fully, in such a way that the DTK config isn't cleared?
|
||||
// system.GetDVDInterface().ResetDrive(true);
|
||||
PowerPC::Reset();
|
||||
system.GetPowerPC().Reset();
|
||||
Wiimote::ResetAllWiimotes();
|
||||
// Note: this is specific to Dolphin and is required because we initialised it in Wii mode.
|
||||
auto& dsp = system.GetDSP();
|
||||
|
@ -83,18 +83,18 @@ bool Load()
|
|||
Host_NotifyMapLoaded();
|
||||
}
|
||||
|
||||
auto& ppc_state = system.GetPPCState();
|
||||
const PowerPC::CoreMode core_mode = PowerPC::GetMode();
|
||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||
ppc_state.msr.Hex = 0;
|
||||
ppc_state.pc = 0x3400;
|
||||
auto& power_pc = system.GetPowerPC();
|
||||
const PowerPC::CoreMode core_mode = power_pc.GetMode();
|
||||
power_pc.SetMode(PowerPC::CoreMode::Interpreter);
|
||||
power_pc.GetPPCState().msr.Hex = 0;
|
||||
power_pc.GetPPCState().pc = 0x3400;
|
||||
NOTICE_LOG_FMT(IOS, "Loaded MIOS and bootstrapped PPC.");
|
||||
|
||||
// IOS writes 0 to 0x30f8 before bootstrapping the PPC. Once started, the IPL eventually writes
|
||||
// 0xdeadbeef there, then waits for it to be cleared by IOS before continuing.
|
||||
while (memory.Read_U32(ADDRESS_INIT_SEMAPHORE) != 0xdeadbeef)
|
||||
PowerPC::SingleStep();
|
||||
PowerPC::SetMode(core_mode);
|
||||
power_pc.SingleStep();
|
||||
power_pc.SetMode(core_mode);
|
||||
|
||||
memory.Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
|
||||
NOTICE_LOG_FMT(IOS, "IPL ready.");
|
||||
|
|
|
@ -63,7 +63,10 @@ int SSLSendWithoutSNI(void* ctx, const unsigned char* buf, size_t len)
|
|||
|
||||
// Log raw SSL packets if we don't dump unencrypted SSL writes
|
||||
if (!Config::Get(Config::MAIN_NETWORK_SSL_DUMP_WRITE) && ret > 0)
|
||||
PowerPC::debug_interface.NetworkLogger()->LogWrite(buf, ret, *fd, nullptr);
|
||||
{
|
||||
Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->LogWrite(
|
||||
buf, ret, *fd, nullptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -76,7 +79,10 @@ int SSLRecv(void* ctx, unsigned char* buf, size_t len)
|
|||
|
||||
// Log raw SSL packets if we don't dump unencrypted SSL reads
|
||||
if (!Config::Get(Config::MAIN_NETWORK_SSL_DUMP_READ) && ret > 0)
|
||||
PowerPC::debug_interface.NetworkLogger()->LogRead(buf, ret, *fd, nullptr);
|
||||
{
|
||||
Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->LogRead(
|
||||
buf, ret, *fd, nullptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -487,8 +487,8 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
|||
|
||||
if (ret >= 0)
|
||||
{
|
||||
PowerPC::debug_interface.NetworkLogger()->LogSSLWrite(memory.GetPointer(BufferOut2),
|
||||
ret, ssl->hostfd);
|
||||
system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogSSLWrite(
|
||||
memory.GetPointer(BufferOut2), ret, ssl->hostfd);
|
||||
// Return bytes written or SSL_ERR_ZERO if none
|
||||
WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
|
||||
}
|
||||
|
@ -521,8 +521,8 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
|||
|
||||
if (ret >= 0)
|
||||
{
|
||||
PowerPC::debug_interface.NetworkLogger()->LogSSLRead(memory.GetPointer(BufferIn2),
|
||||
ret, ssl->hostfd);
|
||||
system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogSSLRead(
|
||||
memory.GetPointer(BufferIn2), ret, ssl->hostfd);
|
||||
// Return bytes read or SSL_ERR_ZERO if none
|
||||
WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
|
||||
}
|
||||
|
@ -595,7 +595,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
|||
const int ret = sendto(fd, data, BufferInSize, flags, to, tolen);
|
||||
ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_SENDTO", true);
|
||||
if (ret > 0)
|
||||
PowerPC::debug_interface.NetworkLogger()->LogWrite(data, ret, fd, to);
|
||||
system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogWrite(data, ret, fd, to);
|
||||
|
||||
INFO_LOG_FMT(IOS_NET,
|
||||
"{} = {} Socket: {:08x}, BufferIn: ({:08x}, {}), BufferIn2: ({:08x}, {}), "
|
||||
|
@ -654,7 +654,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
|
|||
ReturnValue =
|
||||
WiiSockMan::GetNetErrorCode(ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true);
|
||||
if (ret > 0)
|
||||
PowerPC::debug_interface.NetworkLogger()->LogRead(data, ret, fd, from);
|
||||
system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogRead(data, ret, fd, from);
|
||||
|
||||
INFO_LOG_FMT(IOS_NET,
|
||||
"{}({}, {}) Socket: {:08X}, Flags: {:08X}, "
|
||||
|
@ -865,7 +865,7 @@ s32 WiiSockMan::AddSocket(s32 fd, bool is_rw)
|
|||
WiiSocket& sock = WiiSockets[wii_fd];
|
||||
sock.SetFd(fd);
|
||||
sock.SetWiiFd(wii_fd);
|
||||
PowerPC::debug_interface.NetworkLogger()->OnNewSocket(fd);
|
||||
Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->OnNewSocket(fd);
|
||||
|
||||
#ifdef __APPLE__
|
||||
int opt_no_sigpipe = 1;
|
||||
|
|
|
@ -277,7 +277,7 @@ static void ApplyMemoryPatches(const Core::CPUThreadGuard& guard,
|
|||
std::lock_guard lock(s_on_frame_memory_mutex);
|
||||
for (std::size_t index : memory_patch_indices)
|
||||
{
|
||||
PowerPC::debug_interface.ApplyExistingPatch(guard, index);
|
||||
guard.GetSystem().GetPowerPC().GetDebugInterface().ApplyExistingPatch(guard, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
BreakPoints::BreakPoints(Core::System& system) : m_system(system)
|
||||
{
|
||||
}
|
||||
|
||||
BreakPoints::~BreakPoints() = default;
|
||||
|
||||
bool BreakPoints::IsAddressBreakPoint(u32 address) const
|
||||
{
|
||||
return std::any_of(m_breakpoints.begin(), m_breakpoints.end(),
|
||||
|
@ -107,7 +113,7 @@ void BreakPoints::Add(TBreakPoint bp)
|
|||
if (IsAddressBreakPoint(bp.address))
|
||||
return;
|
||||
|
||||
Core::System::GetInstance().GetJitInterface().InvalidateICache(bp.address, 4, true);
|
||||
m_system.GetJitInterface().InvalidateICache(bp.address, 4, true);
|
||||
|
||||
m_breakpoints.emplace_back(std::move(bp));
|
||||
}
|
||||
|
@ -143,7 +149,7 @@ void BreakPoints::Add(u32 address, bool temp, bool break_on_hit, bool log_on_hit
|
|||
m_breakpoints.emplace_back(std::move(bp));
|
||||
}
|
||||
|
||||
Core::System::GetInstance().GetJitInterface().InvalidateICache(address, 4, true);
|
||||
m_system.GetJitInterface().InvalidateICache(address, 4, true);
|
||||
}
|
||||
|
||||
bool BreakPoints::ToggleBreakPoint(u32 address)
|
||||
|
@ -167,14 +173,14 @@ void BreakPoints::Remove(u32 address)
|
|||
return;
|
||||
|
||||
m_breakpoints.erase(iter);
|
||||
Core::System::GetInstance().GetJitInterface().InvalidateICache(address, 4, true);
|
||||
m_system.GetJitInterface().InvalidateICache(address, 4, true);
|
||||
}
|
||||
|
||||
void BreakPoints::Clear()
|
||||
{
|
||||
for (const TBreakPoint& bp : m_breakpoints)
|
||||
{
|
||||
Core::System::GetInstance().GetJitInterface().InvalidateICache(bp.address, 4, true);
|
||||
m_system.GetJitInterface().InvalidateICache(bp.address, 4, true);
|
||||
}
|
||||
|
||||
m_breakpoints.clear();
|
||||
|
@ -187,7 +193,7 @@ void BreakPoints::ClearAllTemporary()
|
|||
{
|
||||
if (bp->is_temporary)
|
||||
{
|
||||
Core::System::GetInstance().GetJitInterface().InvalidateICache(bp->address, 4, true);
|
||||
m_system.GetJitInterface().InvalidateICache(bp->address, 4, true);
|
||||
bp = m_breakpoints.erase(bp);
|
||||
}
|
||||
else
|
||||
|
@ -197,6 +203,12 @@ void BreakPoints::ClearAllTemporary()
|
|||
}
|
||||
}
|
||||
|
||||
MemChecks::MemChecks(Core::System& system) : m_system(system)
|
||||
{
|
||||
}
|
||||
|
||||
MemChecks::~MemChecks() = default;
|
||||
|
||||
MemChecks::TMemChecksStr MemChecks::GetStrings() const
|
||||
{
|
||||
TMemChecksStr mc_strings;
|
||||
|
@ -280,8 +292,8 @@ void MemChecks::Add(TMemCheck memory_check)
|
|||
// If this is the first one, clear the JIT cache so it can switch to
|
||||
// watchpoint-compatible code.
|
||||
if (!had_any)
|
||||
Core::System::GetInstance().GetJitInterface().ClearCache();
|
||||
Core::System::GetInstance().GetMMU().DBATUpdated();
|
||||
m_system.GetJitInterface().ClearCache();
|
||||
m_system.GetMMU().DBATUpdated();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -309,8 +321,8 @@ void MemChecks::Remove(u32 address)
|
|||
Core::RunAsCPUThread([&] {
|
||||
m_mem_checks.erase(iter);
|
||||
if (!HasAny())
|
||||
Core::System::GetInstance().GetJitInterface().ClearCache();
|
||||
Core::System::GetInstance().GetMMU().DBATUpdated();
|
||||
m_system.GetJitInterface().ClearCache();
|
||||
m_system.GetMMU().DBATUpdated();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -318,8 +330,8 @@ void MemChecks::Clear()
|
|||
{
|
||||
Core::RunAsCPUThread([&] {
|
||||
m_mem_checks.clear();
|
||||
Core::System::GetInstance().GetJitInterface().ClearCache();
|
||||
Core::System::GetInstance().GetMMU().DBATUpdated();
|
||||
m_system.GetJitInterface().ClearCache();
|
||||
m_system.GetMMU().DBATUpdated();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@ namespace Common
|
|||
{
|
||||
class DebugInterface;
|
||||
}
|
||||
namespace Core
|
||||
{
|
||||
class System;
|
||||
}
|
||||
|
||||
struct TBreakPoint
|
||||
{
|
||||
|
@ -53,6 +57,13 @@ struct TMemCheck
|
|||
class BreakPoints
|
||||
{
|
||||
public:
|
||||
explicit BreakPoints(Core::System& system);
|
||||
BreakPoints(const BreakPoints& other) = delete;
|
||||
BreakPoints(BreakPoints&& other) = delete;
|
||||
BreakPoints& operator=(const BreakPoints& other) = delete;
|
||||
BreakPoints& operator=(BreakPoints&& other) = delete;
|
||||
~BreakPoints();
|
||||
|
||||
using TBreakPoints = std::vector<TBreakPoint>;
|
||||
using TBreakPointsStr = std::vector<std::string>;
|
||||
|
||||
|
@ -82,12 +93,20 @@ public:
|
|||
|
||||
private:
|
||||
TBreakPoints m_breakpoints;
|
||||
Core::System& m_system;
|
||||
};
|
||||
|
||||
// Memory breakpoints
|
||||
class MemChecks
|
||||
{
|
||||
public:
|
||||
explicit MemChecks(Core::System& system);
|
||||
MemChecks(const MemChecks& other) = delete;
|
||||
MemChecks(MemChecks&& other) = delete;
|
||||
MemChecks& operator=(const MemChecks& other) = delete;
|
||||
MemChecks& operator=(MemChecks&& other) = delete;
|
||||
~MemChecks();
|
||||
|
||||
using TMemChecks = std::vector<TMemCheck>;
|
||||
using TMemChecksStr = std::vector<std::string>;
|
||||
|
||||
|
@ -109,4 +128,5 @@ public:
|
|||
|
||||
private:
|
||||
TMemChecks m_mem_checks;
|
||||
Core::System& m_system;
|
||||
};
|
||||
|
|
|
@ -214,7 +214,7 @@ bool CachedInterpreter::CheckFPU(CachedInterpreter& cached_interpreter, u32 data
|
|||
if (!ppc_state.msr.FP)
|
||||
{
|
||||
ppc_state.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
|
||||
PowerPC::CheckExceptions();
|
||||
cached_interpreter.m_system.GetPowerPC().CheckExceptions();
|
||||
ppc_state.downcount -= data;
|
||||
return true;
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ bool CachedInterpreter::CheckDSI(CachedInterpreter& cached_interpreter, u32 data
|
|||
auto& ppc_state = cached_interpreter.m_ppc_state;
|
||||
if (ppc_state.Exceptions & EXCEPTION_DSI)
|
||||
{
|
||||
PowerPC::CheckExceptions();
|
||||
cached_interpreter.m_system.GetPowerPC().CheckExceptions();
|
||||
ppc_state.downcount -= data;
|
||||
return true;
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ bool CachedInterpreter::CheckProgramException(CachedInterpreter& cached_interpre
|
|||
auto& ppc_state = cached_interpreter.m_ppc_state;
|
||||
if (ppc_state.Exceptions & EXCEPTION_PROGRAM)
|
||||
{
|
||||
PowerPC::CheckExceptions();
|
||||
cached_interpreter.m_system.GetPowerPC().CheckExceptions();
|
||||
ppc_state.downcount -= data;
|
||||
return true;
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ bool CachedInterpreter::CheckProgramException(CachedInterpreter& cached_interpre
|
|||
|
||||
bool CachedInterpreter::CheckBreakpoint(CachedInterpreter& cached_interpreter, u32 data)
|
||||
{
|
||||
PowerPC::CheckBreakPoints();
|
||||
cached_interpreter.m_system.GetPowerPC().CheckBreakPoints();
|
||||
if (cached_interpreter.m_system.GetCPU().GetState() != CPU::State::Running)
|
||||
{
|
||||
cached_interpreter.m_ppc_state.downcount -= data;
|
||||
|
@ -295,7 +295,7 @@ void CachedInterpreter::Jit(u32 address)
|
|||
// Address of instruction could not be translated
|
||||
m_ppc_state.npc = nextPC;
|
||||
m_ppc_state.Exceptions |= EXCEPTION_ISI;
|
||||
PowerPC::CheckExceptions();
|
||||
m_system.GetPowerPC().CheckExceptions();
|
||||
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC);
|
||||
return;
|
||||
}
|
||||
|
@ -329,7 +329,8 @@ void CachedInterpreter::Jit(u32 address)
|
|||
if (!op.skip)
|
||||
{
|
||||
const bool breakpoint =
|
||||
m_enable_debugging && PowerPC::breakpoints.IsAddressBreakPoint(op.address);
|
||||
m_enable_debugging &&
|
||||
m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(op.address);
|
||||
const bool check_fpu = (op.opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound;
|
||||
const bool endblock = (op.opinfo->flags & FL_ENDBLOCK) != 0;
|
||||
const bool memcheck = (op.opinfo->flags & FL_LOADSTORE) && jo.memcheck;
|
||||
|
|
|
@ -163,17 +163,19 @@ static void RemoveBreakpoint(BreakpointType type, u32 addr, u32 len)
|
|||
{
|
||||
if (type == BreakpointType::ExecuteHard || type == BreakpointType::ExecuteSoft)
|
||||
{
|
||||
while (PowerPC::breakpoints.IsAddressBreakPoint(addr))
|
||||
auto& breakpoints = Core::System::GetInstance().GetPowerPC().GetBreakPoints();
|
||||
while (breakpoints.IsAddressBreakPoint(addr))
|
||||
{
|
||||
PowerPC::breakpoints.Remove(addr);
|
||||
breakpoints.Remove(addr);
|
||||
INFO_LOG_FMT(GDB_STUB, "gdb: removed a breakpoint: {:08x} bytes at {:08x}", len, addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (PowerPC::memchecks.GetMemCheck(addr, len) != nullptr)
|
||||
auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks();
|
||||
while (memchecks.GetMemCheck(addr, len) != nullptr)
|
||||
{
|
||||
PowerPC::memchecks.Remove(addr);
|
||||
memchecks.Remove(addr);
|
||||
INFO_LOG_FMT(GDB_STUB, "gdb: removed a memcheck: {:08x} bytes at {:08x}", len, addr);
|
||||
}
|
||||
}
|
||||
|
@ -869,7 +871,8 @@ static bool AddBreakpoint(BreakpointType type, u32 addr, u32 len)
|
|||
{
|
||||
if (type == BreakpointType::ExecuteHard || type == BreakpointType::ExecuteSoft)
|
||||
{
|
||||
PowerPC::breakpoints.Add(addr);
|
||||
auto& breakpoints = Core::System::GetInstance().GetPowerPC().GetBreakPoints();
|
||||
breakpoints.Add(addr);
|
||||
INFO_LOG_FMT(GDB_STUB, "gdb: added {} breakpoint: {:08x} bytes at {:08x}",
|
||||
static_cast<int>(type), len, addr);
|
||||
}
|
||||
|
@ -886,7 +889,8 @@ static bool AddBreakpoint(BreakpointType type, u32 addr, u32 len)
|
|||
new_memcheck.break_on_hit = true;
|
||||
new_memcheck.log_on_hit = false;
|
||||
new_memcheck.is_enabled = true;
|
||||
PowerPC::memchecks.Add(std::move(new_memcheck));
|
||||
auto& memchecks = Core::System::GetInstance().GetPowerPC().GetMemChecks();
|
||||
memchecks.Add(std::move(new_memcheck));
|
||||
INFO_LOG_FMT(GDB_STUB, "gdb: added {} memcheck: {:08x} bytes at {:08x}", static_cast<int>(type),
|
||||
len, addr);
|
||||
}
|
||||
|
|
|
@ -206,7 +206,7 @@ void Interpreter::SingleStep()
|
|||
|
||||
if (m_ppc_state.Exceptions != 0)
|
||||
{
|
||||
PowerPC::CheckExceptions();
|
||||
m_system.GetPowerPC().CheckExceptions();
|
||||
m_ppc_state.pc = m_ppc_state.npc;
|
||||
}
|
||||
}
|
||||
|
@ -224,6 +224,7 @@ void Interpreter::Run()
|
|||
{
|
||||
auto& core_timing = m_system.GetCoreTiming();
|
||||
auto& cpu = m_system.GetCPU();
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
while (cpu.GetState() == CPU::State::Running)
|
||||
{
|
||||
// CoreTiming Advance() ends the previous slice and declares the start of the next
|
||||
|
@ -255,7 +256,7 @@ void Interpreter::Run()
|
|||
#endif
|
||||
|
||||
// 2: check for breakpoint
|
||||
if (PowerPC::breakpoints.IsAddressBreakPoint(m_ppc_state.pc))
|
||||
if (power_pc.GetBreakPoints().IsAddressBreakPoint(m_ppc_state.pc))
|
||||
{
|
||||
#ifdef SHOW_HISTORY
|
||||
NOTICE_LOG_FMT(POWERPC, "----------------------------");
|
||||
|
@ -280,8 +281,8 @@ void Interpreter::Run()
|
|||
cpu.Break();
|
||||
if (GDBStub::IsActive())
|
||||
GDBStub::TakeControl();
|
||||
if (PowerPC::breakpoints.IsTempBreakPoint(m_ppc_state.pc))
|
||||
PowerPC::breakpoints.Remove(m_ppc_state.pc);
|
||||
if (power_pc.GetBreakPoints().IsTempBreakPoint(m_ppc_state.pc))
|
||||
power_pc.GetBreakPoints().Remove(m_ppc_state.pc);
|
||||
|
||||
Host_UpdateDisasmDialog();
|
||||
return;
|
||||
|
@ -347,7 +348,7 @@ void Interpreter::ClearCache()
|
|||
|
||||
void Interpreter::CheckExceptions()
|
||||
{
|
||||
PowerPC::CheckExceptions();
|
||||
m_system.GetPowerPC().CheckExceptions();
|
||||
m_end_block = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,6 +145,6 @@ void Interpreter::sc(Interpreter& interpreter, UGeckoInstruction inst)
|
|||
auto& ppc_state = interpreter.m_ppc_state;
|
||||
|
||||
ppc_state.Exceptions |= EXCEPTION_SYSCALL;
|
||||
PowerPC::CheckExceptions();
|
||||
interpreter.m_system.GetPowerPC().CheckExceptions();
|
||||
interpreter.m_end_block = true;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Common/Logging/Log.h"
|
||||
#include "Core/PowerPC/Interpreter/ExceptionUtils.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
void Interpreter::Helper_UpdateCR0(PowerPC::PowerPCState& ppc_state, u32 value)
|
||||
{
|
||||
|
@ -150,7 +151,7 @@ void Interpreter::twi(Interpreter& interpreter, UGeckoInstruction inst)
|
|||
(u32(a) < u32(b) && (TO & 0x02) != 0) || (u32(a) > u32(b) && (TO & 0x01) != 0))
|
||||
{
|
||||
GenerateProgramException(ppc_state, ProgramExceptionCause::Trap);
|
||||
PowerPC::CheckExceptions();
|
||||
interpreter.m_system.GetPowerPC().CheckExceptions();
|
||||
interpreter.m_end_block = true; // Dunno about this
|
||||
}
|
||||
}
|
||||
|
@ -381,7 +382,7 @@ void Interpreter::tw(Interpreter& interpreter, UGeckoInstruction inst)
|
|||
((u32(a) < u32(b)) && (TO & 0x02) != 0) || ((u32(a) > u32(b)) && (TO & 0x01) != 0))
|
||||
{
|
||||
GenerateProgramException(ppc_state, ProgramExceptionCause::Trap);
|
||||
PowerPC::CheckExceptions();
|
||||
interpreter.m_system.GetPowerPC().CheckExceptions();
|
||||
interpreter.m_end_block = true; // Dunno about this
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ mffsx: 80036650 (huh?)
|
|||
static void FPSCRUpdated(PowerPC::PowerPCState& ppc_state)
|
||||
{
|
||||
UpdateFPExceptionSummary(ppc_state);
|
||||
PowerPC::RoundingModeUpdated();
|
||||
PowerPC::RoundingModeUpdated(ppc_state);
|
||||
}
|
||||
|
||||
void Interpreter::mtfsb0x(Interpreter& interpreter, UGeckoInstruction inst)
|
||||
|
@ -184,7 +184,7 @@ void Interpreter::mtmsr(Interpreter& interpreter, UGeckoInstruction inst)
|
|||
// FE0/FE1 may have been set
|
||||
CheckFPExceptions(ppc_state);
|
||||
|
||||
PowerPC::CheckExceptions();
|
||||
interpreter.m_system.GetPowerPC().CheckExceptions();
|
||||
interpreter.m_end_block = true;
|
||||
}
|
||||
|
||||
|
@ -249,7 +249,7 @@ void Interpreter::mfspr(Interpreter& interpreter, UGeckoInstruction inst)
|
|||
|
||||
case SPR_TL:
|
||||
case SPR_TU:
|
||||
PowerPC::WriteFullTimeBaseValue(SystemTimers::GetFakeTimeBase());
|
||||
interpreter.m_system.GetPowerPC().WriteFullTimeBaseValue(SystemTimers::GetFakeTimeBase());
|
||||
break;
|
||||
|
||||
case SPR_WPAR:
|
||||
|
|
|
@ -593,7 +593,7 @@ void Jit64::WriteRfiExitDestInRSCRATCH()
|
|||
MOV(32, PPCSTATE(npc), R(RSCRATCH));
|
||||
Cleanup();
|
||||
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||
ABI_CallFunction(PowerPC::CheckExceptions);
|
||||
ABI_CallFunctionP(PowerPC::CheckExceptionsFromJIT, &m_system.GetPowerPC());
|
||||
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
|
||||
JMP(asm_routines.dispatcher, true);
|
||||
|
@ -614,7 +614,7 @@ void Jit64::WriteExceptionExit()
|
|||
MOV(32, R(RSCRATCH), PPCSTATE(pc));
|
||||
MOV(32, PPCSTATE(npc), R(RSCRATCH));
|
||||
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||
ABI_CallFunction(PowerPC::CheckExceptions);
|
||||
ABI_CallFunctionP(PowerPC::CheckExceptionsFromJIT, &m_system.GetPowerPC());
|
||||
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
|
||||
JMP(asm_routines.dispatcher, true);
|
||||
|
@ -626,7 +626,7 @@ void Jit64::WriteExternalExceptionExit()
|
|||
MOV(32, R(RSCRATCH), PPCSTATE(pc));
|
||||
MOV(32, PPCSTATE(npc), R(RSCRATCH));
|
||||
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||
ABI_CallFunction(PowerPC::CheckExternalExceptions);
|
||||
ABI_CallFunctionP(PowerPC::CheckExternalExceptionsFromJIT, &m_system.GetPowerPC());
|
||||
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||
SUB(32, PPCSTATE(downcount), Imm32(js.downcountAmount));
|
||||
JMP(asm_routines.dispatcher, true);
|
||||
|
@ -740,7 +740,7 @@ void Jit64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
|
|||
// Address of instruction could not be translated
|
||||
m_ppc_state.npc = nextPC;
|
||||
m_ppc_state.Exceptions |= EXCEPTION_ISI;
|
||||
PowerPC::CheckExceptions();
|
||||
m_system.GetPowerPC().CheckExceptions();
|
||||
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC);
|
||||
return;
|
||||
}
|
||||
|
@ -1006,14 +1006,16 @@ bool Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
}
|
||||
|
||||
auto& cpu = m_system.GetCPU();
|
||||
if (m_enable_debugging && breakpoints.IsAddressBreakPoint(op.address) && !cpu.IsStepping())
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
if (m_enable_debugging && power_pc.GetBreakPoints().IsAddressBreakPoint(op.address) &&
|
||||
!cpu.IsStepping())
|
||||
{
|
||||
gpr.Flush();
|
||||
fpr.Flush();
|
||||
|
||||
MOV(32, PPCSTATE(pc), Imm32(op.address));
|
||||
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||
ABI_CallFunction(PowerPC::CheckBreakPoints);
|
||||
ABI_CallFunctionP(PowerPC::CheckBreakPointsFromJIT, &power_pc);
|
||||
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||
MOV(64, R(RSCRATCH), ImmPtr(cpu.GetStatePtr()));
|
||||
TEST(32, MatR(RSCRATCH), Imm32(0xFFFFFFFF));
|
||||
|
|
|
@ -514,10 +514,11 @@ void JitArm64::WriteExceptionExit(ARM64Reg dest, bool only_external, bool always
|
|||
static_assert(PPCSTATE_OFF(pc) + 4 == PPCSTATE_OFF(npc));
|
||||
STP(IndexType::Signed, DISPATCHER_PC, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetPowerPC());
|
||||
if (only_external)
|
||||
MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExternalExceptions);
|
||||
MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExternalExceptionsFromJIT);
|
||||
else
|
||||
MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExceptions);
|
||||
MOVP2R(EncodeRegTo64(DISPATCHER_PC), &PowerPC::CheckExceptionsFromJIT);
|
||||
BLR(EncodeRegTo64(DISPATCHER_PC));
|
||||
|
||||
LDR(IndexType::Unsigned, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(npc));
|
||||
|
@ -742,7 +743,7 @@ void JitArm64::Jit(u32 em_address, bool clear_cache_and_retry_on_failure)
|
|||
// Address of instruction could not be translated
|
||||
m_ppc_state.npc = nextPC;
|
||||
m_ppc_state.Exceptions |= EXCEPTION_ISI;
|
||||
PowerPC::CheckExceptions();
|
||||
m_system.GetPowerPC().CheckExceptions();
|
||||
WARN_LOG_FMT(POWERPC, "ISI exception at {:#010x}", nextPC);
|
||||
return;
|
||||
}
|
||||
|
@ -1033,8 +1034,8 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
js.firstFPInstructionFound = true;
|
||||
}
|
||||
|
||||
if (m_enable_debugging && PowerPC::breakpoints.IsAddressBreakPoint(op.address) &&
|
||||
!cpu.IsStepping())
|
||||
if (m_enable_debugging && !cpu.IsStepping() &&
|
||||
m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(op.address))
|
||||
{
|
||||
FlushCarry();
|
||||
gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
|
||||
|
@ -1045,8 +1046,9 @@ bool JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC)
|
|||
|
||||
MOVI2R(DISPATCHER_PC, op.address);
|
||||
STP(IndexType::Signed, DISPATCHER_PC, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||
MOVP2R(ARM64Reg::X0, &PowerPC::CheckBreakPoints);
|
||||
BLR(ARM64Reg::X0);
|
||||
MOVP2R(ARM64Reg::X0, &m_system.GetPowerPC());
|
||||
MOVP2R(ARM64Reg::X1, &PowerPC::CheckBreakPointsFromJIT);
|
||||
BLR(ARM64Reg::X1);
|
||||
|
||||
LDR(IndexType::Unsigned, ARM64Reg::W0, ARM64Reg::X0,
|
||||
MOVPage2R(ARM64Reg::X0, cpu.GetStatePtr()));
|
||||
|
|
|
@ -78,6 +78,7 @@ void JitArm64::UpdateRoundingMode()
|
|||
|
||||
ABI_PushRegisters(gprs_to_save);
|
||||
m_float_emit.ABI_PushRegisters(fprs_to_save, ARM64Reg::X8);
|
||||
MOVP2R(ARM64Reg::X0, &m_ppc_state);
|
||||
MOVP2R(ARM64Reg::X8, &PowerPC::RoundingModeUpdated);
|
||||
BLR(ARM64Reg::X8);
|
||||
m_float_emit.ABI_PopRegisters(fprs_to_save, ARM64Reg::X8);
|
||||
|
|
|
@ -220,8 +220,11 @@ bool JitBase::CanMergeNextInstructions(int count) const
|
|||
// Be careful: a breakpoint kills flags in between instructions
|
||||
for (int i = 1; i <= count; i++)
|
||||
{
|
||||
if (m_enable_debugging && PowerPC::breakpoints.IsAddressBreakPoint(js.op[i].address))
|
||||
if (m_enable_debugging &&
|
||||
m_system.GetPowerPC().GetBreakPoints().IsAddressBreakPoint(js.op[i].address))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (js.op[i].isBranchTarget)
|
||||
return false;
|
||||
}
|
||||
|
@ -230,7 +233,7 @@ bool JitBase::CanMergeNextInstructions(int count) const
|
|||
|
||||
void JitBase::UpdateMemoryAndExceptionOptions()
|
||||
{
|
||||
bool any_watchpoints = PowerPC::memchecks.HasAny();
|
||||
bool any_watchpoints = m_system.GetPowerPC().GetMemChecks().HasAny();
|
||||
jo.fastmem = m_fastmem_enabled && jo.fastmem_arena && (m_ppc_state.msr.DR || !any_watchpoints);
|
||||
jo.memcheck = m_mmu_enabled || m_pause_on_panic_enabled || any_watchpoints;
|
||||
jo.fp_exceptions = m_enable_float_exceptions;
|
||||
|
|
|
@ -52,8 +52,8 @@
|
|||
|
||||
namespace PowerPC
|
||||
{
|
||||
MMU::MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCState& ppc_state)
|
||||
: m_system(system), m_memory(memory), m_ppc_state(ppc_state)
|
||||
MMU::MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCManager& power_pc)
|
||||
: m_system(system), m_memory(memory), m_power_pc(power_pc), m_ppc_state(power_pc.GetPPCState())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -530,10 +530,10 @@ std::optional<ReadResult<u32>> MMU::HostTryReadInstruction(const Core::CPUThread
|
|||
|
||||
void MMU::Memcheck(u32 address, u64 var, bool write, size_t size)
|
||||
{
|
||||
if (!memchecks.HasAny())
|
||||
if (!m_power_pc.GetMemChecks().HasAny())
|
||||
return;
|
||||
|
||||
TMemCheck* mc = memchecks.GetMemCheck(address, size);
|
||||
TMemCheck* mc = m_power_pc.GetMemChecks().GetMemCheck(address, size);
|
||||
if (mc == nullptr)
|
||||
return;
|
||||
|
||||
|
@ -545,8 +545,8 @@ void MMU::Memcheck(u32 address, u64 var, bool write, size_t size)
|
|||
|
||||
mc->num_hits++;
|
||||
|
||||
const bool pause =
|
||||
mc->Action(m_system, &debug_interface, var, address, write, size, m_ppc_state.pc);
|
||||
const bool pause = mc->Action(m_system, &m_power_pc.GetDebugInterface(), var, address, write,
|
||||
size, m_ppc_state.pc);
|
||||
if (!pause)
|
||||
return;
|
||||
|
||||
|
@ -892,7 +892,7 @@ std::optional<ReadResult<std::string>> MMU::HostTryReadString(const Core::CPUThr
|
|||
|
||||
bool MMU::IsOptimizableRAMAddress(const u32 address) const
|
||||
{
|
||||
if (PowerPC::memchecks.HasAny())
|
||||
if (m_power_pc.GetMemChecks().HasAny())
|
||||
return false;
|
||||
|
||||
if (!m_ppc_state.msr.DR)
|
||||
|
@ -1189,7 +1189,7 @@ void MMU::TouchDCacheLine(u32 address, bool store)
|
|||
|
||||
u32 MMU::IsOptimizableMMIOAccess(u32 address, u32 access_size) const
|
||||
{
|
||||
if (PowerPC::memchecks.HasAny())
|
||||
if (m_power_pc.GetMemChecks().HasAny())
|
||||
return 0;
|
||||
|
||||
if (!m_ppc_state.msr.DR)
|
||||
|
@ -1212,7 +1212,7 @@ u32 MMU::IsOptimizableMMIOAccess(u32 address, u32 access_size) const
|
|||
|
||||
bool MMU::IsOptimizableGatherPipeWrite(u32 address) const
|
||||
{
|
||||
if (PowerPC::memchecks.HasAny())
|
||||
if (m_power_pc.GetMemChecks().HasAny())
|
||||
return false;
|
||||
|
||||
if (!m_ppc_state.msr.DR)
|
||||
|
@ -1566,7 +1566,7 @@ void MMU::UpdateBATs(BatTable& bat_table, u32 base_spr)
|
|||
}
|
||||
|
||||
// Fastmem doesn't support memchecks, so disable it for all overlapping virtual pages.
|
||||
if (PowerPC::memchecks.OverlapsMemcheck(virtual_address, BAT_PAGE_SIZE))
|
||||
if (m_power_pc.GetMemChecks().OverlapsMemcheck(virtual_address, BAT_PAGE_SIZE))
|
||||
valid_bit &= ~BAT_PHYSICAL_BIT;
|
||||
|
||||
// (BEPI | j) == (BEPI & ~BL) | (j & BL).
|
||||
|
@ -1586,7 +1586,7 @@ void MMU::UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr)
|
|||
u32 p_address = 0x7E000000 | (i << BAT_INDEX_SHIFT & m_memory.GetFakeVMemMask());
|
||||
u32 flags = BAT_MAPPED_BIT | BAT_PHYSICAL_BIT;
|
||||
|
||||
if (PowerPC::memchecks.OverlapsMemcheck(e_address << BAT_INDEX_SHIFT, BAT_PAGE_SIZE))
|
||||
if (m_power_pc.GetMemChecks().OverlapsMemcheck(e_address << BAT_INDEX_SHIFT, BAT_PAGE_SIZE))
|
||||
flags &= ~BAT_PHYSICAL_BIT;
|
||||
|
||||
bat_table[e_address] = p_address | flags;
|
||||
|
|
|
@ -23,6 +23,7 @@ class MemoryManager;
|
|||
|
||||
namespace PowerPC
|
||||
{
|
||||
class PowerPCManager;
|
||||
struct PowerPCState;
|
||||
|
||||
enum class RequestedAddressSpace
|
||||
|
@ -108,7 +109,7 @@ enum class XCheckTLBFlag
|
|||
class MMU
|
||||
{
|
||||
public:
|
||||
MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCState& ppc_state);
|
||||
MMU(Core::System& system, Memory::MemoryManager& memory, PowerPC::PowerPCManager& power_pc);
|
||||
MMU(const MMU& other) = delete;
|
||||
MMU(MMU&& other) = delete;
|
||||
MMU& operator=(const MMU& other) = delete;
|
||||
|
@ -318,6 +319,7 @@ private:
|
|||
|
||||
Core::System& m_system;
|
||||
Memory::MemoryManager& m_memory;
|
||||
PowerPC::PowerPCManager& m_power_pc;
|
||||
PowerPC::PowerPCState& m_ppc_state;
|
||||
|
||||
BatTable m_ibat_table;
|
||||
|
|
|
@ -209,10 +209,11 @@ bool PPCAnalyzer::CanSwapAdjacentOps(const CodeOp& a, const CodeOp& b) const
|
|||
u64 b_flags = b_info->flags;
|
||||
|
||||
// can't reorder around breakpoints
|
||||
if (m_is_debugging_enabled && (PowerPC::breakpoints.IsAddressBreakPoint(a.address) ||
|
||||
PowerPC::breakpoints.IsAddressBreakPoint(b.address)))
|
||||
if (m_is_debugging_enabled)
|
||||
{
|
||||
return false;
|
||||
auto& breakpoints = Core::System::GetInstance().GetPowerPC().GetBreakPoints();
|
||||
if (breakpoints.IsAddressBreakPoint(a.address) || breakpoints.IsAddressBreakPoint(b.address))
|
||||
return false;
|
||||
}
|
||||
// Any instruction which can raise an interrupt is *not* a possible swap candidate:
|
||||
// see [1] for an example of a crash caused by this error.
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
PPCSymbolDB g_symbolDB;
|
||||
|
||||
PPCSymbolDB::PPCSymbolDB() : debugger{&PowerPC::debug_interface}
|
||||
PPCSymbolDB::PPCSymbolDB() : debugger{&Core::System::GetInstance().GetPowerPC().GetDebugInterface()}
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -35,19 +35,6 @@
|
|||
|
||||
namespace PowerPC
|
||||
{
|
||||
// STATE_TO_SAVE
|
||||
PowerPCState ppcState;
|
||||
|
||||
static CPUCoreBase* s_cpu_core_base = nullptr;
|
||||
static bool s_cpu_core_base_is_injected = false;
|
||||
static CoreMode s_mode = CoreMode::Interpreter;
|
||||
|
||||
BreakPoints breakpoints;
|
||||
MemChecks memchecks;
|
||||
PPCDebugInterface debug_interface(Core::System::GetInstance());
|
||||
|
||||
static CoreTiming::EventType* s_invalidate_cache_thread_safe;
|
||||
|
||||
double PairedSingle::PS0AsDouble() const
|
||||
{
|
||||
return Common::BitCast<double>(ps0);
|
||||
|
@ -70,7 +57,7 @@ void PairedSingle::SetPS1(double value)
|
|||
|
||||
static void InvalidateCacheThreadSafe(Core::System& system, u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
ppcState.iCache.Invalidate(static_cast<u32>(userdata));
|
||||
system.GetPPCState().iCache.Invalidate(static_cast<u32>(userdata));
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& is, CPUCore& core)
|
||||
|
@ -97,7 +84,14 @@ std::ostream& operator<<(std::ostream& os, CPUCore core)
|
|||
return os;
|
||||
}
|
||||
|
||||
void DoState(PointerWrap& p)
|
||||
PowerPCManager::PowerPCManager(Core::System& system)
|
||||
: m_breakpoints(system), m_memchecks(system), m_debug_interface(system), m_system(system)
|
||||
{
|
||||
}
|
||||
|
||||
PowerPCManager::~PowerPCManager() = default;
|
||||
|
||||
void PowerPCManager::DoState(PointerWrap& p)
|
||||
{
|
||||
// some of this code has been disabled, because
|
||||
// it changes registers even in Mode::Measure (which is suspicious and seems like it could cause
|
||||
|
@ -105,49 +99,49 @@ void DoState(PointerWrap& p)
|
|||
// and because the values it's changing have been added to CoreTiming::DoState, so it might
|
||||
// conflict to mess with them here.
|
||||
|
||||
// PowerPC::ppcState.spr[SPR_DEC] = SystemTimers::GetFakeDecrementer();
|
||||
// *((u64 *)&TL(PowerPC::ppcState)) = SystemTimers::GetFakeTimeBase(); //works since we are little
|
||||
// m_ppc_state.spr[SPR_DEC] = SystemTimers::GetFakeDecrementer();
|
||||
// *((u64 *)&TL(m_ppc_state)) = SystemTimers::GetFakeTimeBase(); //works since we are little
|
||||
// endian and TL comes first :)
|
||||
|
||||
p.DoArray(ppcState.gpr);
|
||||
p.Do(ppcState.pc);
|
||||
p.Do(ppcState.npc);
|
||||
p.DoArray(ppcState.cr.fields);
|
||||
p.Do(ppcState.msr);
|
||||
p.Do(ppcState.fpscr);
|
||||
p.Do(ppcState.Exceptions);
|
||||
p.Do(ppcState.downcount);
|
||||
p.Do(ppcState.xer_ca);
|
||||
p.Do(ppcState.xer_so_ov);
|
||||
p.Do(ppcState.xer_stringctrl);
|
||||
p.DoArray(ppcState.ps);
|
||||
p.DoArray(ppcState.sr);
|
||||
p.DoArray(ppcState.spr);
|
||||
p.DoArray(ppcState.tlb);
|
||||
p.Do(ppcState.pagetable_base);
|
||||
p.Do(ppcState.pagetable_hashmask);
|
||||
p.DoArray(m_ppc_state.gpr);
|
||||
p.Do(m_ppc_state.pc);
|
||||
p.Do(m_ppc_state.npc);
|
||||
p.DoArray(m_ppc_state.cr.fields);
|
||||
p.Do(m_ppc_state.msr);
|
||||
p.Do(m_ppc_state.fpscr);
|
||||
p.Do(m_ppc_state.Exceptions);
|
||||
p.Do(m_ppc_state.downcount);
|
||||
p.Do(m_ppc_state.xer_ca);
|
||||
p.Do(m_ppc_state.xer_so_ov);
|
||||
p.Do(m_ppc_state.xer_stringctrl);
|
||||
p.DoArray(m_ppc_state.ps);
|
||||
p.DoArray(m_ppc_state.sr);
|
||||
p.DoArray(m_ppc_state.spr);
|
||||
p.DoArray(m_ppc_state.tlb);
|
||||
p.Do(m_ppc_state.pagetable_base);
|
||||
p.Do(m_ppc_state.pagetable_hashmask);
|
||||
|
||||
p.Do(ppcState.reserve);
|
||||
p.Do(ppcState.reserve_address);
|
||||
p.Do(m_ppc_state.reserve);
|
||||
p.Do(m_ppc_state.reserve_address);
|
||||
|
||||
ppcState.iCache.DoState(p);
|
||||
ppcState.dCache.DoState(p);
|
||||
m_ppc_state.iCache.DoState(p);
|
||||
m_ppc_state.dCache.DoState(p);
|
||||
|
||||
if (p.IsReadMode())
|
||||
{
|
||||
if (!ppcState.m_enable_dcache)
|
||||
if (!m_ppc_state.m_enable_dcache)
|
||||
{
|
||||
INFO_LOG_FMT(POWERPC, "Flushing data cache");
|
||||
ppcState.dCache.FlushAll();
|
||||
m_ppc_state.dCache.FlushAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
ppcState.dCache.Reset();
|
||||
m_ppc_state.dCache.Reset();
|
||||
}
|
||||
|
||||
RoundingModeUpdated();
|
||||
RoundingModeUpdated(m_ppc_state);
|
||||
|
||||
auto& mmu = Core::System::GetInstance().GetMMU();
|
||||
auto& mmu = m_system.GetMMU();
|
||||
mmu.IBATUpdated();
|
||||
mmu.DBATUpdated();
|
||||
}
|
||||
|
@ -155,15 +149,15 @@ void DoState(PointerWrap& p)
|
|||
// SystemTimers::DecrementerSet();
|
||||
// SystemTimers::TimeBaseSet();
|
||||
|
||||
Core::System::GetInstance().GetJitInterface().DoState(p);
|
||||
m_system.GetJitInterface().DoState(p);
|
||||
}
|
||||
|
||||
static void ResetRegisters()
|
||||
void PowerPCManager::ResetRegisters()
|
||||
{
|
||||
std::fill(std::begin(ppcState.ps), std::end(ppcState.ps), PairedSingle{});
|
||||
std::fill(std::begin(ppcState.sr), std::end(ppcState.sr), 0U);
|
||||
std::fill(std::begin(ppcState.gpr), std::end(ppcState.gpr), 0U);
|
||||
std::fill(std::begin(ppcState.spr), std::end(ppcState.spr), 0U);
|
||||
std::fill(std::begin(m_ppc_state.ps), std::end(m_ppc_state.ps), PairedSingle{});
|
||||
std::fill(std::begin(m_ppc_state.sr), std::end(m_ppc_state.sr), 0U);
|
||||
std::fill(std::begin(m_ppc_state.gpr), std::end(m_ppc_state.gpr), 0U);
|
||||
std::fill(std::begin(m_ppc_state.spr), std::end(m_ppc_state.spr), 0U);
|
||||
|
||||
// Gamecube:
|
||||
// 0x00080200 = lonestar 2.0
|
||||
|
@ -178,73 +172,72 @@ static void ResetRegisters()
|
|||
// 0x00087102 = broadway retail hw
|
||||
if (SConfig::GetInstance().bWii)
|
||||
{
|
||||
ppcState.spr[SPR_PVR] = 0x00087102;
|
||||
m_ppc_state.spr[SPR_PVR] = 0x00087102;
|
||||
}
|
||||
else
|
||||
{
|
||||
ppcState.spr[SPR_PVR] = 0x00083214;
|
||||
m_ppc_state.spr[SPR_PVR] = 0x00083214;
|
||||
}
|
||||
ppcState.spr[SPR_HID1] = 0x80000000; // We're running at 3x the bus clock
|
||||
ppcState.spr[SPR_ECID_U] = 0x0d96e200;
|
||||
ppcState.spr[SPR_ECID_M] = 0x1840c00d;
|
||||
ppcState.spr[SPR_ECID_L] = 0x82bb08e8;
|
||||
m_ppc_state.spr[SPR_HID1] = 0x80000000; // We're running at 3x the bus clock
|
||||
m_ppc_state.spr[SPR_ECID_U] = 0x0d96e200;
|
||||
m_ppc_state.spr[SPR_ECID_M] = 0x1840c00d;
|
||||
m_ppc_state.spr[SPR_ECID_L] = 0x82bb08e8;
|
||||
|
||||
ppcState.fpscr.Hex = 0;
|
||||
ppcState.pc = 0;
|
||||
ppcState.npc = 0;
|
||||
ppcState.Exceptions = 0;
|
||||
m_ppc_state.fpscr.Hex = 0;
|
||||
m_ppc_state.pc = 0;
|
||||
m_ppc_state.npc = 0;
|
||||
m_ppc_state.Exceptions = 0;
|
||||
|
||||
ppcState.reserve = false;
|
||||
ppcState.reserve_address = 0;
|
||||
m_ppc_state.reserve = false;
|
||||
m_ppc_state.reserve_address = 0;
|
||||
|
||||
for (auto& v : ppcState.cr.fields)
|
||||
for (auto& v : m_ppc_state.cr.fields)
|
||||
{
|
||||
v = 0x8000000000000001;
|
||||
}
|
||||
ppcState.SetXER({});
|
||||
m_ppc_state.SetXER({});
|
||||
|
||||
RoundingModeUpdated();
|
||||
RoundingModeUpdated(m_ppc_state);
|
||||
|
||||
auto& mmu = Core::System::GetInstance().GetMMU();
|
||||
auto& mmu = m_system.GetMMU();
|
||||
mmu.DBATUpdated();
|
||||
mmu.IBATUpdated();
|
||||
|
||||
TL(PowerPC::ppcState) = 0;
|
||||
TU(PowerPC::ppcState) = 0;
|
||||
TL(m_ppc_state) = 0;
|
||||
TU(m_ppc_state) = 0;
|
||||
SystemTimers::TimeBaseSet();
|
||||
|
||||
// MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :}
|
||||
ppcState.msr.Hex = 0;
|
||||
ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
||||
m_ppc_state.msr.Hex = 0;
|
||||
m_ppc_state.spr[SPR_DEC] = 0xFFFFFFFF;
|
||||
SystemTimers::DecrementerSet();
|
||||
}
|
||||
|
||||
static void InitializeCPUCore(CPUCore cpu_core)
|
||||
void PowerPCManager::InitializeCPUCore(CPUCore cpu_core)
|
||||
{
|
||||
// We initialize the interpreter because
|
||||
// it is used on boot and code window independently.
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& interpreter = system.GetInterpreter();
|
||||
auto& interpreter = m_system.GetInterpreter();
|
||||
interpreter.Init();
|
||||
|
||||
switch (cpu_core)
|
||||
{
|
||||
case CPUCore::Interpreter:
|
||||
s_cpu_core_base = &interpreter;
|
||||
m_cpu_core_base = &interpreter;
|
||||
break;
|
||||
|
||||
default:
|
||||
s_cpu_core_base = system.GetJitInterface().InitJitCore(cpu_core);
|
||||
if (!s_cpu_core_base) // Handle Situations where JIT core isn't available
|
||||
m_cpu_core_base = m_system.GetJitInterface().InitJitCore(cpu_core);
|
||||
if (!m_cpu_core_base) // Handle Situations where JIT core isn't available
|
||||
{
|
||||
WARN_LOG_FMT(POWERPC, "CPU core {} not available. Falling back to default.",
|
||||
static_cast<int>(cpu_core));
|
||||
s_cpu_core_base = system.GetJitInterface().InitJitCore(DefaultCPUCore());
|
||||
m_cpu_core_base = m_system.GetJitInterface().InitJitCore(DefaultCPUCore());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
s_mode = s_cpu_core_base == &interpreter ? CoreMode::Interpreter : CoreMode::JIT;
|
||||
m_mode = m_cpu_core_base == &interpreter ? CoreMode::Interpreter : CoreMode::JIT;
|
||||
}
|
||||
|
||||
const std::vector<CPUCore>& AvailableCPUCores()
|
||||
|
@ -273,147 +266,143 @@ CPUCore DefaultCPUCore()
|
|||
#endif
|
||||
}
|
||||
|
||||
void Init(CPUCore cpu_core)
|
||||
void PowerPCManager::Init(CPUCore cpu_core)
|
||||
{
|
||||
s_invalidate_cache_thread_safe = Core::System::GetInstance().GetCoreTiming().RegisterEvent(
|
||||
"invalidateEmulatedCache", InvalidateCacheThreadSafe);
|
||||
m_invalidate_cache_thread_safe =
|
||||
m_system.GetCoreTiming().RegisterEvent("invalidateEmulatedCache", InvalidateCacheThreadSafe);
|
||||
|
||||
Reset();
|
||||
|
||||
InitializeCPUCore(cpu_core);
|
||||
ppcState.iCache.Init();
|
||||
ppcState.dCache.Init();
|
||||
m_ppc_state.iCache.Init();
|
||||
m_ppc_state.dCache.Init();
|
||||
|
||||
ppcState.m_enable_dcache = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE);
|
||||
m_ppc_state.m_enable_dcache = Config::Get(Config::MAIN_ACCURATE_CPU_CACHE);
|
||||
|
||||
if (Config::Get(Config::MAIN_ENABLE_DEBUGGING))
|
||||
breakpoints.ClearAllTemporary();
|
||||
m_breakpoints.ClearAllTemporary();
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void PowerPCManager::Reset()
|
||||
{
|
||||
ppcState.pagetable_base = 0;
|
||||
ppcState.pagetable_hashmask = 0;
|
||||
ppcState.tlb = {};
|
||||
m_ppc_state.pagetable_base = 0;
|
||||
m_ppc_state.pagetable_hashmask = 0;
|
||||
m_ppc_state.tlb = {};
|
||||
|
||||
ResetRegisters();
|
||||
ppcState.iCache.Reset();
|
||||
ppcState.dCache.Reset();
|
||||
m_ppc_state.iCache.Reset();
|
||||
m_ppc_state.dCache.Reset();
|
||||
}
|
||||
|
||||
void ScheduleInvalidateCacheThreadSafe(u32 address)
|
||||
void PowerPCManager::ScheduleInvalidateCacheThreadSafe(u32 address)
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& cpu = system.GetCPU();
|
||||
auto& cpu = m_system.GetCPU();
|
||||
|
||||
if (cpu.GetState() == CPU::State::Running && !Core::IsCPUThread())
|
||||
{
|
||||
system.GetCoreTiming().ScheduleEvent(0, s_invalidate_cache_thread_safe, address,
|
||||
CoreTiming::FromThread::NON_CPU);
|
||||
m_system.GetCoreTiming().ScheduleEvent(0, m_invalidate_cache_thread_safe, address,
|
||||
CoreTiming::FromThread::NON_CPU);
|
||||
}
|
||||
else
|
||||
{
|
||||
PowerPC::ppcState.iCache.Invalidate(static_cast<u32>(address));
|
||||
m_ppc_state.iCache.Invalidate(static_cast<u32>(address));
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
void PowerPCManager::Shutdown()
|
||||
{
|
||||
InjectExternalCPUCore(nullptr);
|
||||
auto& system = Core::System::GetInstance();
|
||||
system.GetJitInterface().Shutdown();
|
||||
auto& interpreter = system.GetInterpreter();
|
||||
interpreter.Shutdown();
|
||||
s_cpu_core_base = nullptr;
|
||||
m_system.GetJitInterface().Shutdown();
|
||||
m_system.GetInterpreter().Shutdown();
|
||||
m_cpu_core_base = nullptr;
|
||||
}
|
||||
|
||||
CoreMode GetMode()
|
||||
CoreMode PowerPCManager::GetMode() const
|
||||
{
|
||||
return !s_cpu_core_base_is_injected ? s_mode : CoreMode::Interpreter;
|
||||
return !m_cpu_core_base_is_injected ? m_mode : CoreMode::Interpreter;
|
||||
}
|
||||
|
||||
static void ApplyMode()
|
||||
void PowerPCManager::ApplyMode()
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& interpreter = system.GetInterpreter();
|
||||
auto& interpreter = m_system.GetInterpreter();
|
||||
|
||||
switch (s_mode)
|
||||
switch (m_mode)
|
||||
{
|
||||
case CoreMode::Interpreter: // Switching from JIT to interpreter
|
||||
s_cpu_core_base = &interpreter;
|
||||
m_cpu_core_base = &interpreter;
|
||||
break;
|
||||
|
||||
case CoreMode::JIT: // Switching from interpreter to JIT.
|
||||
// Don't really need to do much. It'll work, the cache will refill itself.
|
||||
s_cpu_core_base = system.GetJitInterface().GetCore();
|
||||
if (!s_cpu_core_base) // Has a chance to not get a working JIT core if one isn't active on host
|
||||
s_cpu_core_base = &interpreter;
|
||||
m_cpu_core_base = m_system.GetJitInterface().GetCore();
|
||||
if (!m_cpu_core_base) // Has a chance to not get a working JIT core if one isn't active on host
|
||||
m_cpu_core_base = &interpreter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetMode(CoreMode new_mode)
|
||||
void PowerPCManager::SetMode(CoreMode new_mode)
|
||||
{
|
||||
if (new_mode == s_mode)
|
||||
if (new_mode == m_mode)
|
||||
return; // We don't need to do anything.
|
||||
|
||||
s_mode = new_mode;
|
||||
m_mode = new_mode;
|
||||
|
||||
// If we're using an external CPU core implementation then don't do anything.
|
||||
if (s_cpu_core_base_is_injected)
|
||||
if (m_cpu_core_base_is_injected)
|
||||
return;
|
||||
|
||||
ApplyMode();
|
||||
}
|
||||
|
||||
const char* GetCPUName()
|
||||
const char* PowerPCManager::GetCPUName() const
|
||||
{
|
||||
return s_cpu_core_base->GetName();
|
||||
return m_cpu_core_base->GetName();
|
||||
}
|
||||
|
||||
void InjectExternalCPUCore(CPUCoreBase* new_cpu)
|
||||
void PowerPCManager::InjectExternalCPUCore(CPUCoreBase* new_cpu)
|
||||
{
|
||||
// Previously injected.
|
||||
if (s_cpu_core_base_is_injected)
|
||||
s_cpu_core_base->Shutdown();
|
||||
if (m_cpu_core_base_is_injected)
|
||||
m_cpu_core_base->Shutdown();
|
||||
|
||||
// nullptr means just remove
|
||||
if (!new_cpu)
|
||||
{
|
||||
if (s_cpu_core_base_is_injected)
|
||||
if (m_cpu_core_base_is_injected)
|
||||
{
|
||||
s_cpu_core_base_is_injected = false;
|
||||
m_cpu_core_base_is_injected = false;
|
||||
ApplyMode();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
new_cpu->Init();
|
||||
s_cpu_core_base = new_cpu;
|
||||
s_cpu_core_base_is_injected = true;
|
||||
m_cpu_core_base = new_cpu;
|
||||
m_cpu_core_base_is_injected = true;
|
||||
}
|
||||
|
||||
void SingleStep()
|
||||
void PowerPCManager::SingleStep()
|
||||
{
|
||||
s_cpu_core_base->SingleStep();
|
||||
m_cpu_core_base->SingleStep();
|
||||
}
|
||||
|
||||
void RunLoop()
|
||||
void PowerPCManager::RunLoop()
|
||||
{
|
||||
s_cpu_core_base->Run();
|
||||
m_cpu_core_base->Run();
|
||||
Host_UpdateDisasmDialog();
|
||||
}
|
||||
|
||||
u64 ReadFullTimeBaseValue()
|
||||
u64 PowerPCManager::ReadFullTimeBaseValue() const
|
||||
{
|
||||
u64 value;
|
||||
std::memcpy(&value, &TL(PowerPC::ppcState), sizeof(value));
|
||||
std::memcpy(&value, &TL(m_ppc_state), sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
void WriteFullTimeBaseValue(u64 value)
|
||||
void PowerPCManager::WriteFullTimeBaseValue(u64 value)
|
||||
{
|
||||
std::memcpy(&TL(PowerPC::ppcState), &value, sizeof(value));
|
||||
std::memcpy(&TL(m_ppc_state), &value, sizeof(value));
|
||||
}
|
||||
|
||||
void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst,
|
||||
|
@ -478,9 +467,9 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst,
|
|||
}
|
||||
}
|
||||
|
||||
void CheckExceptions()
|
||||
void PowerPCManager::CheckExceptions()
|
||||
{
|
||||
u32 exceptions = ppcState.Exceptions;
|
||||
u32 exceptions = m_ppc_state.Exceptions;
|
||||
|
||||
// Example procedure:
|
||||
// Set SRR0 to either PC or NPC
|
||||
|
@ -505,79 +494,79 @@ void CheckExceptions()
|
|||
|
||||
if (exceptions & EXCEPTION_ISI)
|
||||
{
|
||||
SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc;
|
||||
SRR0(m_ppc_state) = m_ppc_state.npc;
|
||||
// Page fault occurred
|
||||
SRR1(PowerPC::ppcState) = (PowerPC::ppcState.msr.Hex & 0x87C0FFFF) | (1 << 30);
|
||||
PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE;
|
||||
PowerPC::ppcState.msr.Hex &= ~0x04EF36;
|
||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000400;
|
||||
SRR1(m_ppc_state) = (m_ppc_state.msr.Hex & 0x87C0FFFF) | (1 << 30);
|
||||
m_ppc_state.msr.LE = m_ppc_state.msr.ILE;
|
||||
m_ppc_state.msr.Hex &= ~0x04EF36;
|
||||
m_ppc_state.pc = m_ppc_state.npc = 0x00000400;
|
||||
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_ISI");
|
||||
ppcState.Exceptions &= ~EXCEPTION_ISI;
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_ISI;
|
||||
}
|
||||
else if (exceptions & EXCEPTION_PROGRAM)
|
||||
{
|
||||
SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc;
|
||||
SRR0(m_ppc_state) = m_ppc_state.pc;
|
||||
// SRR1 was partially set by GenerateProgramException, so bitwise or is used here
|
||||
SRR1(PowerPC::ppcState) |= PowerPC::ppcState.msr.Hex & 0x87C0FFFF;
|
||||
PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE;
|
||||
PowerPC::ppcState.msr.Hex &= ~0x04EF36;
|
||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000700;
|
||||
SRR1(m_ppc_state) |= m_ppc_state.msr.Hex & 0x87C0FFFF;
|
||||
m_ppc_state.msr.LE = m_ppc_state.msr.ILE;
|
||||
m_ppc_state.msr.Hex &= ~0x04EF36;
|
||||
m_ppc_state.pc = m_ppc_state.npc = 0x00000700;
|
||||
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_PROGRAM");
|
||||
ppcState.Exceptions &= ~EXCEPTION_PROGRAM;
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_PROGRAM;
|
||||
}
|
||||
else if (exceptions & EXCEPTION_SYSCALL)
|
||||
{
|
||||
SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc;
|
||||
SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF;
|
||||
PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE;
|
||||
PowerPC::ppcState.msr.Hex &= ~0x04EF36;
|
||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000C00;
|
||||
SRR0(m_ppc_state) = m_ppc_state.npc;
|
||||
SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF;
|
||||
m_ppc_state.msr.LE = m_ppc_state.msr.ILE;
|
||||
m_ppc_state.msr.Hex &= ~0x04EF36;
|
||||
m_ppc_state.pc = m_ppc_state.npc = 0x00000C00;
|
||||
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_SYSCALL (PC={:08x})", PowerPC::ppcState.pc);
|
||||
ppcState.Exceptions &= ~EXCEPTION_SYSCALL;
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_SYSCALL (PC={:08x})", m_ppc_state.pc);
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_SYSCALL;
|
||||
}
|
||||
else if (exceptions & EXCEPTION_FPU_UNAVAILABLE)
|
||||
{
|
||||
// This happens a lot - GameCube OS uses deferred FPU context switching
|
||||
SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc; // re-execute the instruction
|
||||
SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF;
|
||||
PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE;
|
||||
PowerPC::ppcState.msr.Hex &= ~0x04EF36;
|
||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000800;
|
||||
SRR0(m_ppc_state) = m_ppc_state.pc; // re-execute the instruction
|
||||
SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF;
|
||||
m_ppc_state.msr.LE = m_ppc_state.msr.ILE;
|
||||
m_ppc_state.msr.Hex &= ~0x04EF36;
|
||||
m_ppc_state.pc = m_ppc_state.npc = 0x00000800;
|
||||
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
|
||||
ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE;
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE;
|
||||
}
|
||||
else if (exceptions & EXCEPTION_FAKE_MEMCHECK_HIT)
|
||||
{
|
||||
ppcState.Exceptions &= ~EXCEPTION_DSI & ~EXCEPTION_FAKE_MEMCHECK_HIT;
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_DSI & ~EXCEPTION_FAKE_MEMCHECK_HIT;
|
||||
}
|
||||
else if (exceptions & EXCEPTION_DSI)
|
||||
{
|
||||
SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc;
|
||||
SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF;
|
||||
PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE;
|
||||
PowerPC::ppcState.msr.Hex &= ~0x04EF36;
|
||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000300;
|
||||
SRR0(m_ppc_state) = m_ppc_state.pc;
|
||||
SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF;
|
||||
m_ppc_state.msr.LE = m_ppc_state.msr.ILE;
|
||||
m_ppc_state.msr.Hex &= ~0x04EF36;
|
||||
m_ppc_state.pc = m_ppc_state.npc = 0x00000300;
|
||||
// DSISR and DAR regs are changed in GenerateDSIException()
|
||||
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_DSI");
|
||||
ppcState.Exceptions &= ~EXCEPTION_DSI;
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_DSI;
|
||||
}
|
||||
else if (exceptions & EXCEPTION_ALIGNMENT)
|
||||
{
|
||||
SRR0(PowerPC::ppcState) = PowerPC::ppcState.pc;
|
||||
SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF;
|
||||
PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE;
|
||||
PowerPC::ppcState.msr.Hex &= ~0x04EF36;
|
||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000600;
|
||||
SRR0(m_ppc_state) = m_ppc_state.pc;
|
||||
SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF;
|
||||
m_ppc_state.msr.LE = m_ppc_state.msr.ILE;
|
||||
m_ppc_state.msr.Hex &= ~0x04EF36;
|
||||
m_ppc_state.pc = m_ppc_state.npc = 0x00000600;
|
||||
|
||||
// TODO crazy amount of DSISR options to check out
|
||||
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_ALIGNMENT");
|
||||
ppcState.Exceptions &= ~EXCEPTION_ALIGNMENT;
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_ALIGNMENT;
|
||||
}
|
||||
|
||||
// EXTERNAL INTERRUPT
|
||||
|
@ -587,50 +576,49 @@ void CheckExceptions()
|
|||
}
|
||||
}
|
||||
|
||||
void CheckExternalExceptions()
|
||||
void PowerPCManager::CheckExternalExceptions()
|
||||
{
|
||||
u32 exceptions = ppcState.Exceptions;
|
||||
u32 exceptions = m_ppc_state.Exceptions;
|
||||
|
||||
// EXTERNAL INTERRUPT
|
||||
// Handling is delayed until MSR.EE=1.
|
||||
if (exceptions && PowerPC::ppcState.msr.EE)
|
||||
if (exceptions && m_ppc_state.msr.EE)
|
||||
{
|
||||
if (exceptions & EXCEPTION_EXTERNAL_INT)
|
||||
{
|
||||
// Pokemon gets this "too early", it hasn't a handler yet
|
||||
SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc;
|
||||
SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF;
|
||||
PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE;
|
||||
PowerPC::ppcState.msr.Hex &= ~0x04EF36;
|
||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000500;
|
||||
SRR0(m_ppc_state) = m_ppc_state.npc;
|
||||
SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF;
|
||||
m_ppc_state.msr.LE = m_ppc_state.msr.ILE;
|
||||
m_ppc_state.msr.Hex &= ~0x04EF36;
|
||||
m_ppc_state.pc = m_ppc_state.npc = 0x00000500;
|
||||
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_EXTERNAL_INT");
|
||||
ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT;
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_EXTERNAL_INT;
|
||||
|
||||
DEBUG_ASSERT_MSG(POWERPC, (SRR1(PowerPC::ppcState) & 0x02) != 0,
|
||||
"EXTERNAL_INT unrecoverable???");
|
||||
DEBUG_ASSERT_MSG(POWERPC, (SRR1(m_ppc_state) & 0x02) != 0, "EXTERNAL_INT unrecoverable???");
|
||||
}
|
||||
else if (exceptions & EXCEPTION_PERFORMANCE_MONITOR)
|
||||
{
|
||||
SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc;
|
||||
SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF;
|
||||
PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE;
|
||||
PowerPC::ppcState.msr.Hex &= ~0x04EF36;
|
||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000F00;
|
||||
SRR0(m_ppc_state) = m_ppc_state.npc;
|
||||
SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF;
|
||||
m_ppc_state.msr.LE = m_ppc_state.msr.ILE;
|
||||
m_ppc_state.msr.Hex &= ~0x04EF36;
|
||||
m_ppc_state.pc = m_ppc_state.npc = 0x00000F00;
|
||||
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
|
||||
ppcState.Exceptions &= ~EXCEPTION_PERFORMANCE_MONITOR;
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_PERFORMANCE_MONITOR;
|
||||
}
|
||||
else if (exceptions & EXCEPTION_DECREMENTER)
|
||||
{
|
||||
SRR0(PowerPC::ppcState) = PowerPC::ppcState.npc;
|
||||
SRR1(PowerPC::ppcState) = PowerPC::ppcState.msr.Hex & 0x87C0FFFF;
|
||||
PowerPC::ppcState.msr.LE = PowerPC::ppcState.msr.ILE;
|
||||
PowerPC::ppcState.msr.Hex &= ~0x04EF36;
|
||||
PowerPC::ppcState.pc = PowerPC::ppcState.npc = 0x00000900;
|
||||
SRR0(m_ppc_state) = m_ppc_state.npc;
|
||||
SRR1(m_ppc_state) = m_ppc_state.msr.Hex & 0x87C0FFFF;
|
||||
m_ppc_state.msr.LE = m_ppc_state.msr.ILE;
|
||||
m_ppc_state.msr.Hex &= ~0x04EF36;
|
||||
m_ppc_state.pc = m_ppc_state.npc = 0x00000900;
|
||||
|
||||
DEBUG_LOG_FMT(POWERPC, "EXCEPTION_DECREMENTER");
|
||||
ppcState.Exceptions &= ~EXCEPTION_DECREMENTER;
|
||||
m_ppc_state.Exceptions &= ~EXCEPTION_DECREMENTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -641,17 +629,16 @@ void CheckExternalExceptions()
|
|||
}
|
||||
}
|
||||
|
||||
void CheckBreakPoints()
|
||||
void PowerPCManager::CheckBreakPoints()
|
||||
{
|
||||
const TBreakPoint* bp = PowerPC::breakpoints.GetBreakpoint(PowerPC::ppcState.pc);
|
||||
const TBreakPoint* bp = m_breakpoints.GetBreakpoint(m_ppc_state.pc);
|
||||
|
||||
if (!bp || !bp->is_enabled || !EvaluateCondition(Core::System::GetInstance(), bp->condition))
|
||||
if (!bp || !bp->is_enabled || !EvaluateCondition(m_system, bp->condition))
|
||||
return;
|
||||
|
||||
if (bp->break_on_hit)
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
system.GetCPU().Break();
|
||||
m_system.GetCPU().Break();
|
||||
if (GDBStub::IsActive())
|
||||
GDBStub::TakeControl();
|
||||
}
|
||||
|
@ -660,14 +647,13 @@ void CheckBreakPoints()
|
|||
NOTICE_LOG_FMT(MEMMAP,
|
||||
"BP {:08x} {}({:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} "
|
||||
"{:08x}) LR={:08x}",
|
||||
PowerPC::ppcState.pc, g_symbolDB.GetDescription(PowerPC::ppcState.pc),
|
||||
PowerPC::ppcState.gpr[3], PowerPC::ppcState.gpr[4], PowerPC::ppcState.gpr[5],
|
||||
PowerPC::ppcState.gpr[6], PowerPC::ppcState.gpr[7], PowerPC::ppcState.gpr[8],
|
||||
PowerPC::ppcState.gpr[9], PowerPC::ppcState.gpr[10], PowerPC::ppcState.gpr[11],
|
||||
PowerPC::ppcState.gpr[12], LR(PowerPC::ppcState));
|
||||
m_ppc_state.pc, g_symbolDB.GetDescription(m_ppc_state.pc), m_ppc_state.gpr[3],
|
||||
m_ppc_state.gpr[4], m_ppc_state.gpr[5], m_ppc_state.gpr[6], m_ppc_state.gpr[7],
|
||||
m_ppc_state.gpr[8], m_ppc_state.gpr[9], m_ppc_state.gpr[10], m_ppc_state.gpr[11],
|
||||
m_ppc_state.gpr[12], LR(m_ppc_state));
|
||||
}
|
||||
if (PowerPC::breakpoints.IsTempBreakPoint(PowerPC::ppcState.pc))
|
||||
PowerPC::breakpoints.Remove(PowerPC::ppcState.pc);
|
||||
if (m_breakpoints.IsTempBreakPoint(m_ppc_state.pc))
|
||||
m_breakpoints.Remove(m_ppc_state.pc);
|
||||
}
|
||||
|
||||
void PowerPCState::SetSR(u32 index, u32 value)
|
||||
|
@ -688,12 +674,26 @@ void PowerPCState::UpdateFPRFSingle(float fvalue)
|
|||
fpscr.FPRF = Common::ClassifyFloat(fvalue);
|
||||
}
|
||||
|
||||
void RoundingModeUpdated()
|
||||
void RoundingModeUpdated(PowerPCState& ppc_state)
|
||||
{
|
||||
// The rounding mode is separate for each thread, so this must run on the CPU thread
|
||||
ASSERT(Core::IsCPUThread());
|
||||
|
||||
Common::FPU::SetSIMDMode(PowerPC::ppcState.fpscr.RN, PowerPC::ppcState.fpscr.NI);
|
||||
Common::FPU::SetSIMDMode(ppc_state.fpscr.RN, ppc_state.fpscr.NI);
|
||||
}
|
||||
|
||||
void CheckExceptionsFromJIT(PowerPCManager& power_pc)
|
||||
{
|
||||
power_pc.CheckExceptions();
|
||||
}
|
||||
|
||||
void CheckExternalExceptionsFromJIT(PowerPCManager& power_pc)
|
||||
{
|
||||
power_pc.CheckExternalExceptions();
|
||||
}
|
||||
|
||||
void CheckBreakPointsFromJIT(PowerPCManager& power_pc)
|
||||
{
|
||||
power_pc.CheckBreakPoints();
|
||||
}
|
||||
} // namespace PowerPC
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
|
||||
class CPUCoreBase;
|
||||
class PointerWrap;
|
||||
namespace CoreTiming
|
||||
{
|
||||
struct EventType;
|
||||
}
|
||||
|
||||
namespace PowerPC
|
||||
{
|
||||
|
@ -234,49 +238,86 @@ static_assert(offsetof(PowerPC::PowerPCState, above_fits_in_first_0x100) <= 0x10
|
|||
#endif
|
||||
#endif
|
||||
|
||||
extern PowerPCState ppcState;
|
||||
|
||||
extern BreakPoints breakpoints;
|
||||
extern MemChecks memchecks;
|
||||
extern PPCDebugInterface debug_interface;
|
||||
|
||||
const std::vector<CPUCore>& AvailableCPUCores();
|
||||
CPUCore DefaultCPUCore();
|
||||
|
||||
void Init(CPUCore cpu_core);
|
||||
void Reset();
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap& p);
|
||||
void ScheduleInvalidateCacheThreadSafe(u32 address);
|
||||
class PowerPCManager
|
||||
{
|
||||
public:
|
||||
explicit PowerPCManager(Core::System& system);
|
||||
PowerPCManager(const PowerPCManager& other) = delete;
|
||||
PowerPCManager(PowerPCManager&& other) = delete;
|
||||
PowerPCManager& operator=(const PowerPCManager& other) = delete;
|
||||
PowerPCManager& operator=(PowerPCManager&& other) = delete;
|
||||
~PowerPCManager();
|
||||
|
||||
CoreMode GetMode();
|
||||
// [NOT THREADSAFE] CPU Thread or CPU::PauseAndLock or Core::State::Uninitialized
|
||||
void SetMode(CoreMode _coreType);
|
||||
const char* GetCPUName();
|
||||
void Init(CPUCore cpu_core);
|
||||
void Reset();
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap& p);
|
||||
void ScheduleInvalidateCacheThreadSafe(u32 address);
|
||||
|
||||
// Set the current CPU Core to the given implementation until removed.
|
||||
// Remove the current injected CPU Core by passing nullptr.
|
||||
// While an external CPUCoreBase is injected, GetMode() will return CoreMode::Interpreter.
|
||||
// Init() will be called when added and Shutdown() when removed.
|
||||
// [Threadsafety: Same as SetMode(), except it cannot be called from inside the CPU
|
||||
// run loop on the CPU Thread - it doesn't make sense for a CPU to remove itself
|
||||
// while it is in State::Running]
|
||||
void InjectExternalCPUCore(CPUCoreBase* core);
|
||||
CoreMode GetMode() const;
|
||||
// [NOT THREADSAFE] CPU Thread or CPU::PauseAndLock or Core::State::Uninitialized
|
||||
void SetMode(CoreMode _coreType);
|
||||
const char* GetCPUName() const;
|
||||
|
||||
// Stepping requires the CPU Execution lock (CPU::PauseAndLock or CPU Thread)
|
||||
// It's not threadsafe otherwise.
|
||||
void SingleStep();
|
||||
void CheckExceptions();
|
||||
void CheckExternalExceptions();
|
||||
void CheckBreakPoints();
|
||||
void RunLoop();
|
||||
// Set the current CPU Core to the given implementation until removed.
|
||||
// Remove the current injected CPU Core by passing nullptr.
|
||||
// While an external CPUCoreBase is injected, GetMode() will return CoreMode::Interpreter.
|
||||
// Init() will be called when added and Shutdown() when removed.
|
||||
// [Threadsafety: Same as SetMode(), except it cannot be called from inside the CPU
|
||||
// run loop on the CPU Thread - it doesn't make sense for a CPU to remove itself
|
||||
// while it is in State::Running]
|
||||
void InjectExternalCPUCore(CPUCoreBase* core);
|
||||
|
||||
u64 ReadFullTimeBaseValue();
|
||||
void WriteFullTimeBaseValue(u64 value);
|
||||
// Stepping requires the CPU Execution lock (CPU::PauseAndLock or CPU Thread)
|
||||
// It's not threadsafe otherwise.
|
||||
void SingleStep();
|
||||
void CheckExceptions();
|
||||
void CheckExternalExceptions();
|
||||
void CheckBreakPoints();
|
||||
void RunLoop();
|
||||
|
||||
u64 ReadFullTimeBaseValue() const;
|
||||
void WriteFullTimeBaseValue(u64 value);
|
||||
|
||||
PowerPCState& GetPPCState() { return m_ppc_state; }
|
||||
const PowerPCState& GetPPCState() const { return m_ppc_state; }
|
||||
BreakPoints& GetBreakPoints() { return m_breakpoints; }
|
||||
const BreakPoints& GetBreakPoints() const { return m_breakpoints; }
|
||||
MemChecks& GetMemChecks() { return m_memchecks; }
|
||||
const MemChecks& GetMemChecks() const { return m_memchecks; }
|
||||
PPCDebugInterface& GetDebugInterface() { return m_debug_interface; }
|
||||
const PPCDebugInterface& GetDebugInterface() const { return m_debug_interface; }
|
||||
|
||||
private:
|
||||
void InitializeCPUCore(CPUCore cpu_core);
|
||||
void ApplyMode();
|
||||
void ResetRegisters();
|
||||
|
||||
PowerPCState m_ppc_state;
|
||||
|
||||
CPUCoreBase* m_cpu_core_base = nullptr;
|
||||
bool m_cpu_core_base_is_injected = false;
|
||||
CoreMode m_mode = CoreMode::Interpreter;
|
||||
|
||||
BreakPoints m_breakpoints;
|
||||
MemChecks m_memchecks;
|
||||
PPCDebugInterface m_debug_interface;
|
||||
|
||||
CoreTiming::EventType* m_invalidate_cache_thread_safe = nullptr;
|
||||
|
||||
Core::System& m_system;
|
||||
};
|
||||
|
||||
void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst,
|
||||
PowerPCState& ppc_state);
|
||||
|
||||
void CheckExceptionsFromJIT(PowerPCManager& power_pc);
|
||||
void CheckExternalExceptionsFromJIT(PowerPCManager& power_pc);
|
||||
void CheckBreakPointsFromJIT(PowerPCManager& power_pc);
|
||||
|
||||
// Easy register access macros.
|
||||
#define HID0(ppc_state) ((UReg_HID0&)(ppc_state).spr[SPR_HID0])
|
||||
#define HID2(ppc_state) ((UReg_HID2&)(ppc_state).spr[SPR_HID2])
|
||||
|
@ -297,6 +338,6 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst,
|
|||
#define TL(ppc_state) (ppc_state).spr[SPR_TL]
|
||||
#define TU(ppc_state) (ppc_state).spr[SPR_TU]
|
||||
|
||||
void RoundingModeUpdated();
|
||||
void RoundingModeUpdated(PowerPCState& ppc_state);
|
||||
|
||||
} // namespace PowerPC
|
||||
|
|
|
@ -233,7 +233,7 @@ static void DoState(PointerWrap& p)
|
|||
HW::DoState(system, p);
|
||||
p.DoMarker("HW");
|
||||
|
||||
PowerPC::DoState(p);
|
||||
system.GetPowerPC().DoState(p);
|
||||
p.DoMarker("PowerPC");
|
||||
|
||||
if (SConfig::GetInstance().bWii)
|
||||
|
|
|
@ -38,11 +38,12 @@ namespace Core
|
|||
struct System::Impl
|
||||
{
|
||||
explicit Impl(System& system)
|
||||
: m_audio_interface(system), m_core_timing(system), m_dsp(system), m_dvd_interface(system),
|
||||
m_dvd_thread(system), m_expansion_interface(system), m_gp_fifo(system), m_memory(system),
|
||||
m_ppc_state(PowerPC::ppcState), m_mmu(system, m_memory, m_ppc_state),
|
||||
m_processor_interface(system), m_serial_interface(system), m_video_interface(system),
|
||||
m_interpreter(system, m_ppc_state, m_mmu), m_jit_interface(system)
|
||||
: m_audio_interface(system), m_core_timing(system), m_cpu(system), m_dsp(system),
|
||||
m_dvd_interface(system), m_dvd_thread(system), m_expansion_interface(system),
|
||||
m_gp_fifo(system), m_memory(system), m_power_pc(system),
|
||||
m_mmu(system, m_memory, m_power_pc), m_processor_interface(system),
|
||||
m_serial_interface(system), m_video_interface(system),
|
||||
m_interpreter(system, m_power_pc.GetPPCState(), m_mmu), m_jit_interface(system)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -67,7 +68,7 @@ struct System::Impl
|
|||
MemoryInterface::MemoryInterfaceManager m_memory_interface;
|
||||
PixelEngine::PixelEngineManager m_pixel_engine;
|
||||
PixelShaderManager m_pixel_shader_manager;
|
||||
PowerPC::PowerPCState& m_ppc_state;
|
||||
PowerPC::PowerPCManager m_power_pc;
|
||||
PowerPC::MMU m_mmu;
|
||||
ProcessorInterface::ProcessorInterfaceManager m_processor_interface;
|
||||
SerialInterface::SerialInterfaceManager m_serial_interface;
|
||||
|
@ -221,9 +222,14 @@ PixelShaderManager& System::GetPixelShaderManager() const
|
|||
return m_impl->m_pixel_shader_manager;
|
||||
}
|
||||
|
||||
PowerPC::PowerPCManager& System::GetPowerPC() const
|
||||
{
|
||||
return m_impl->m_power_pc;
|
||||
}
|
||||
|
||||
PowerPC::PowerPCState& System::GetPPCState() const
|
||||
{
|
||||
return m_impl->m_ppc_state;
|
||||
return m_impl->m_power_pc.GetPPCState();
|
||||
}
|
||||
|
||||
ProcessorInterface::ProcessorInterfaceManager& System::GetProcessorInterface() const
|
||||
|
|
|
@ -73,6 +73,7 @@ class PixelEngineManager;
|
|||
namespace PowerPC
|
||||
{
|
||||
class MMU;
|
||||
class PowerPCManager;
|
||||
struct PowerPCState;
|
||||
} // namespace PowerPC
|
||||
namespace ProcessorInterface
|
||||
|
@ -142,6 +143,7 @@ public:
|
|||
PowerPC::MMU& GetMMU() const;
|
||||
PixelEngine::PixelEngineManager& GetPixelEngine() const;
|
||||
PixelShaderManager& GetPixelShaderManager() const;
|
||||
PowerPC::PowerPCManager& GetPowerPC() const;
|
||||
PowerPC::PowerPCState& GetPPCState() const;
|
||||
ProcessorInterface::ProcessorInterfaceManager& GetProcessorInterface() const;
|
||||
SerialInterface::SerialInterfaceManager& GetSerialInterface() const;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "Core/PowerPC/Expression.h"
|
||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
#include "DolphinQt/Debugger/BreakpointDialog.h"
|
||||
#include "DolphinQt/Debugger/MemoryWidget.h"
|
||||
|
@ -34,7 +35,8 @@ enum CustomRole
|
|||
};
|
||||
}
|
||||
|
||||
BreakpointWidget::BreakpointWidget(QWidget* parent) : QDockWidget(parent)
|
||||
BreakpointWidget::BreakpointWidget(QWidget* parent)
|
||||
: QDockWidget(parent), m_system(Core::System::GetInstance())
|
||||
{
|
||||
setWindowTitle(tr("Breakpoints"));
|
||||
setObjectName(QStringLiteral("breakpoints"));
|
||||
|
@ -172,8 +174,12 @@ void BreakpointWidget::Update()
|
|||
return item;
|
||||
};
|
||||
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
auto& breakpoints = power_pc.GetBreakPoints();
|
||||
auto& memchecks = power_pc.GetMemChecks();
|
||||
|
||||
// Breakpoints
|
||||
for (const auto& bp : PowerPC::breakpoints.GetBreakPoints())
|
||||
for (const auto& bp : breakpoints.GetBreakPoints())
|
||||
{
|
||||
m_table->setRowCount(i + 1);
|
||||
|
||||
|
@ -215,7 +221,7 @@ void BreakpointWidget::Update()
|
|||
}
|
||||
|
||||
// Memory Breakpoints
|
||||
for (const auto& mbp : PowerPC::memchecks.GetMemChecks())
|
||||
for (const auto& mbp : memchecks.GetMemChecks())
|
||||
{
|
||||
m_table->setRowCount(i + 1);
|
||||
auto* active =
|
||||
|
@ -279,11 +285,11 @@ void BreakpointWidget::OnDelete()
|
|||
if (is_memcheck)
|
||||
{
|
||||
const QSignalBlocker blocker(Settings::Instance());
|
||||
PowerPC::memchecks.Remove(address);
|
||||
m_system.GetPowerPC().GetMemChecks().Remove(address);
|
||||
}
|
||||
else
|
||||
{
|
||||
PowerPC::breakpoints.Remove(address);
|
||||
m_system.GetPowerPC().GetBreakPoints().Remove(address);
|
||||
}
|
||||
|
||||
emit BreakpointsChanged();
|
||||
|
@ -292,10 +298,10 @@ void BreakpointWidget::OnDelete()
|
|||
|
||||
void BreakpointWidget::OnClear()
|
||||
{
|
||||
PowerPC::debug_interface.ClearAllBreakpoints();
|
||||
m_system.GetPowerPC().GetDebugInterface().ClearAllBreakpoints();
|
||||
{
|
||||
const QSignalBlocker blocker(Settings::Instance());
|
||||
PowerPC::debug_interface.ClearAllMemChecks();
|
||||
m_system.GetPowerPC().GetDebugInterface().ClearAllMemChecks();
|
||||
}
|
||||
|
||||
m_table->setRowCount(0);
|
||||
|
@ -314,12 +320,14 @@ void BreakpointWidget::OnEditBreakpoint(u32 address, bool is_instruction_bp)
|
|||
{
|
||||
if (is_instruction_bp)
|
||||
{
|
||||
auto* dialog = new BreakpointDialog(this, PowerPC::breakpoints.GetBreakpoint(address));
|
||||
auto* dialog =
|
||||
new BreakpointDialog(this, m_system.GetPowerPC().GetBreakPoints().GetBreakpoint(address));
|
||||
dialog->exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto* dialog = new BreakpointDialog(this, PowerPC::memchecks.GetMemCheck(address));
|
||||
auto* dialog =
|
||||
new BreakpointDialog(this, m_system.GetPowerPC().GetMemChecks().GetMemCheck(address));
|
||||
dialog->exec();
|
||||
}
|
||||
|
||||
|
@ -339,16 +347,18 @@ void BreakpointWidget::OnLoad()
|
|||
BreakPoints::TBreakPointsStr new_bps;
|
||||
if (ini.GetLines("BreakPoints", &new_bps, false))
|
||||
{
|
||||
PowerPC::breakpoints.Clear();
|
||||
PowerPC::breakpoints.AddFromStrings(new_bps);
|
||||
auto& breakpoints = m_system.GetPowerPC().GetBreakPoints();
|
||||
breakpoints.Clear();
|
||||
breakpoints.AddFromStrings(new_bps);
|
||||
}
|
||||
|
||||
MemChecks::TMemChecksStr new_mcs;
|
||||
if (ini.GetLines("MemoryBreakPoints", &new_mcs, false))
|
||||
{
|
||||
PowerPC::memchecks.Clear();
|
||||
auto& memchecks = m_system.GetPowerPC().GetMemChecks();
|
||||
memchecks.Clear();
|
||||
const QSignalBlocker blocker(Settings::Instance());
|
||||
PowerPC::memchecks.AddFromStrings(new_mcs);
|
||||
memchecks.AddFromStrings(new_mcs);
|
||||
}
|
||||
|
||||
emit BreakpointsChanged();
|
||||
|
@ -360,8 +370,8 @@ void BreakpointWidget::OnSave()
|
|||
IniFile ini;
|
||||
ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini",
|
||||
false);
|
||||
ini.SetLines("BreakPoints", PowerPC::breakpoints.GetStrings());
|
||||
ini.SetLines("MemoryBreakPoints", PowerPC::memchecks.GetStrings());
|
||||
ini.SetLines("BreakPoints", m_system.GetPowerPC().GetBreakPoints().GetStrings());
|
||||
ini.SetLines("MemoryBreakPoints", m_system.GetPowerPC().GetMemChecks().GetStrings());
|
||||
ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini");
|
||||
}
|
||||
|
||||
|
@ -381,7 +391,7 @@ void BreakpointWidget::OnContextMenu()
|
|||
|
||||
if (!is_memory_breakpoint)
|
||||
{
|
||||
const auto& inst_breakpoints = PowerPC::breakpoints.GetBreakPoints();
|
||||
const auto& inst_breakpoints = m_system.GetPowerPC().GetBreakPoints().GetBreakPoints();
|
||||
const auto bp_iter =
|
||||
std::find_if(inst_breakpoints.begin(), inst_breakpoints.end(),
|
||||
[bp_address](const auto& bp) { return bp.address == bp_address; });
|
||||
|
@ -390,7 +400,7 @@ void BreakpointWidget::OnContextMenu()
|
|||
|
||||
menu->addAction(tr("Show in Code"), [this, bp_address] { emit ShowCode(bp_address); });
|
||||
menu->addAction(bp_iter->is_enabled ? tr("Disable") : tr("Enable"), [this, &bp_address]() {
|
||||
PowerPC::breakpoints.ToggleBreakPoint(bp_address);
|
||||
m_system.GetPowerPC().GetBreakPoints().ToggleBreakPoint(bp_address);
|
||||
|
||||
emit BreakpointsChanged();
|
||||
Update();
|
||||
|
@ -398,7 +408,7 @@ void BreakpointWidget::OnContextMenu()
|
|||
}
|
||||
else
|
||||
{
|
||||
const auto& memory_breakpoints = PowerPC::memchecks.GetMemChecks();
|
||||
const auto& memory_breakpoints = m_system.GetPowerPC().GetMemChecks().GetMemChecks();
|
||||
const auto mb_iter =
|
||||
std::find_if(memory_breakpoints.begin(), memory_breakpoints.end(),
|
||||
[bp_address](const auto& bp) { return bp.start_address == bp_address; });
|
||||
|
@ -407,7 +417,7 @@ void BreakpointWidget::OnContextMenu()
|
|||
|
||||
menu->addAction(tr("Show in Memory"), [this, bp_address] { emit ShowMemory(bp_address); });
|
||||
menu->addAction(mb_iter->is_enabled ? tr("Disable") : tr("Enable"), [this, &bp_address]() {
|
||||
PowerPC::memchecks.ToggleBreakPoint(bp_address);
|
||||
m_system.GetPowerPC().GetMemChecks().ToggleBreakPoint(bp_address);
|
||||
|
||||
emit BreakpointsChanged();
|
||||
Update();
|
||||
|
@ -428,7 +438,7 @@ void BreakpointWidget::AddBP(u32 addr)
|
|||
void BreakpointWidget::AddBP(u32 addr, bool temp, bool break_on_hit, bool log_on_hit,
|
||||
const QString& condition)
|
||||
{
|
||||
PowerPC::breakpoints.Add(
|
||||
m_system.GetPowerPC().GetBreakPoints().Add(
|
||||
addr, temp, break_on_hit, log_on_hit,
|
||||
!condition.isEmpty() ? Expression::TryParse(condition.toUtf8().constData()) : std::nullopt);
|
||||
|
||||
|
@ -452,7 +462,7 @@ void BreakpointWidget::AddAddressMBP(u32 addr, bool on_read, bool on_write, bool
|
|||
!condition.isEmpty() ? Expression::TryParse(condition.toUtf8().constData()) : std::nullopt;
|
||||
{
|
||||
const QSignalBlocker blocker(Settings::Instance());
|
||||
PowerPC::memchecks.Add(std::move(check));
|
||||
m_system.GetPowerPC().GetMemChecks().Add(std::move(check));
|
||||
}
|
||||
|
||||
emit BreakpointsChanged();
|
||||
|
@ -475,7 +485,7 @@ void BreakpointWidget::AddRangedMBP(u32 from, u32 to, bool on_read, bool on_writ
|
|||
!condition.isEmpty() ? Expression::TryParse(condition.toUtf8().constData()) : std::nullopt;
|
||||
{
|
||||
const QSignalBlocker blocker(Settings::Instance());
|
||||
PowerPC::memchecks.Add(std::move(check));
|
||||
m_system.GetPowerPC().GetMemChecks().Add(std::move(check));
|
||||
}
|
||||
|
||||
emit BreakpointsChanged();
|
||||
|
|
|
@ -12,6 +12,10 @@ class QCloseEvent;
|
|||
class QShowEvent;
|
||||
class QTableWidget;
|
||||
class QToolBar;
|
||||
namespace Core
|
||||
{
|
||||
class System;
|
||||
}
|
||||
|
||||
class BreakpointWidget : public QDockWidget
|
||||
{
|
||||
|
@ -51,6 +55,8 @@ private:
|
|||
|
||||
void UpdateIcons();
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
QToolBar* m_toolbar;
|
||||
QTableWidget* m_table;
|
||||
QAction* m_new;
|
||||
|
|
|
@ -487,8 +487,9 @@ void CodeDiffDialog::OnSetBLR()
|
|||
return;
|
||||
|
||||
{
|
||||
Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
PowerPC::debug_interface.SetPatch(guard, symbol->address, 0x4E800020);
|
||||
auto& system = Core::System::GetInstance();
|
||||
Core::CPUThreadGuard guard(system);
|
||||
system.GetPowerPC().GetDebugInterface().SetPatch(guard, symbol->address, 0x4E800020);
|
||||
}
|
||||
|
||||
int row = item->row();
|
||||
|
|
|
@ -184,7 +184,7 @@ CodeViewWidget::~CodeViewWidget() = default;
|
|||
|
||||
static u32 GetBranchFromAddress(const Core::CPUThreadGuard& guard, u32 addr)
|
||||
{
|
||||
std::string disasm = PowerPC::debug_interface.Disassemble(&guard, addr);
|
||||
std::string disasm = guard.GetSystem().GetPowerPC().GetDebugInterface().Disassemble(&guard, addr);
|
||||
size_t pos = disasm.find("->0x");
|
||||
|
||||
if (pos == std::string::npos)
|
||||
|
@ -294,8 +294,11 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard)
|
|||
for (int i = 0; i < rows; i++)
|
||||
setRowHeight(i, rowh);
|
||||
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
auto& debug_interface = power_pc.GetDebugInterface();
|
||||
|
||||
const std::optional<u32> pc =
|
||||
guard ? std::make_optional(m_system.GetPPCState().pc) : std::nullopt;
|
||||
guard ? std::make_optional(power_pc.GetPPCState().pc) : std::nullopt;
|
||||
|
||||
const bool dark_theme = qApp->palette().color(QPalette::Base).valueF() < 0.5;
|
||||
|
||||
|
@ -304,16 +307,16 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard)
|
|||
for (int i = 0; i < rowCount(); i++)
|
||||
{
|
||||
const u32 addr = AddressForRow(i);
|
||||
const u32 color = PowerPC::debug_interface.GetColor(guard, addr);
|
||||
const u32 color = debug_interface.GetColor(guard, addr);
|
||||
auto* bp_item = new QTableWidgetItem;
|
||||
auto* addr_item = new QTableWidgetItem(QStringLiteral("%1").arg(addr, 8, 16, QLatin1Char('0')));
|
||||
|
||||
std::string disas = PowerPC::debug_interface.Disassemble(guard, addr);
|
||||
std::string disas = debug_interface.Disassemble(guard, addr);
|
||||
auto split = disas.find('\t');
|
||||
|
||||
std::string ins = (split == std::string::npos ? disas : disas.substr(0, split));
|
||||
std::string param = (split == std::string::npos ? "" : disas.substr(split + 1));
|
||||
std::string desc = PowerPC::debug_interface.GetDescription(addr);
|
||||
std::string desc = debug_interface.GetDescription(addr);
|
||||
|
||||
// Adds whitespace and a minimum size to ins and param. Helps to prevent frequent resizing while
|
||||
// scrolling.
|
||||
|
@ -360,19 +363,19 @@ void CodeViewWidget::Update(const Core::CPUThreadGuard* guard)
|
|||
branch.dst_addr = branch_addr;
|
||||
branch.is_link = IsBranchInstructionWithLink(ins);
|
||||
|
||||
description_item->setText(tr("--> %1").arg(
|
||||
QString::fromStdString(PowerPC::debug_interface.GetDescription(branch_addr))));
|
||||
description_item->setText(
|
||||
tr("--> %1").arg(QString::fromStdString(debug_interface.GetDescription(branch_addr))));
|
||||
param_item->setForeground(Qt::magenta);
|
||||
}
|
||||
|
||||
if (ins == "blr")
|
||||
ins_item->setForeground(dark_theme ? QColor(0xa0FFa0) : Qt::darkGreen);
|
||||
|
||||
if (PowerPC::debug_interface.IsBreakpoint(addr))
|
||||
if (debug_interface.IsBreakpoint(addr))
|
||||
{
|
||||
auto icon =
|
||||
Resources::GetScaledThemeIcon("debugger_breakpoint").pixmap(QSize(rowh - 2, rowh - 2));
|
||||
if (!PowerPC::breakpoints.IsBreakPointEnable(addr))
|
||||
if (!m_system.GetPowerPC().GetBreakPoints().IsBreakPointEnable(addr))
|
||||
{
|
||||
QPixmap disabled_icon(icon.size());
|
||||
disabled_icon.fill(Qt::transparent);
|
||||
|
@ -536,8 +539,8 @@ void CodeViewWidget::ReplaceAddress(u32 address, ReplaceWith replace)
|
|||
{
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
|
||||
PowerPC::debug_interface.SetPatch(guard, address,
|
||||
replace == ReplaceWith::BLR ? 0x4e800020 : 0x60000000);
|
||||
m_system.GetPowerPC().GetDebugInterface().SetPatch(
|
||||
guard, address, replace == ReplaceWith::BLR ? 0x4e800020 : 0x60000000);
|
||||
|
||||
Update(&guard);
|
||||
}
|
||||
|
@ -598,7 +601,7 @@ void CodeViewWidget::OnContextMenu()
|
|||
{
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
const u32 pc = m_system.GetPPCState().pc;
|
||||
const std::string disasm = PowerPC::debug_interface.Disassemble(&guard, pc);
|
||||
const std::string disasm = m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, pc);
|
||||
|
||||
if (addr == pc)
|
||||
{
|
||||
|
@ -642,7 +645,8 @@ void CodeViewWidget::OnContextMenu()
|
|||
action->setEnabled(valid_load_store);
|
||||
}
|
||||
|
||||
restore_action->setEnabled(running && PowerPC::debug_interface.HasEnabledPatch(addr));
|
||||
restore_action->setEnabled(running &&
|
||||
m_system.GetPowerPC().GetDebugInterface().HasEnabledPatch(addr));
|
||||
|
||||
menu->exec(QCursor::pos());
|
||||
Update();
|
||||
|
@ -745,14 +749,14 @@ void CodeViewWidget::OnCopyTargetAddress()
|
|||
|
||||
const std::string code_line = [this, addr] {
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
return PowerPC::debug_interface.Disassemble(&guard, addr);
|
||||
return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr);
|
||||
}();
|
||||
|
||||
if (!IsInstructionLoadStore(code_line))
|
||||
return;
|
||||
|
||||
const std::optional<u32> target_addr =
|
||||
PowerPC::debug_interface.GetMemoryAddressFromInstruction(code_line);
|
||||
m_system.GetPowerPC().GetDebugInterface().GetMemoryAddressFromInstruction(code_line);
|
||||
|
||||
if (target_addr)
|
||||
{
|
||||
|
@ -775,14 +779,14 @@ void CodeViewWidget::OnShowTargetInMemory()
|
|||
|
||||
const std::string code_line = [this, addr] {
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
return PowerPC::debug_interface.Disassemble(&guard, addr);
|
||||
return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr);
|
||||
}();
|
||||
|
||||
if (!IsInstructionLoadStore(code_line))
|
||||
return;
|
||||
|
||||
const std::optional<u32> target_addr =
|
||||
PowerPC::debug_interface.GetMemoryAddressFromInstruction(code_line);
|
||||
m_system.GetPowerPC().GetDebugInterface().GetMemoryAddressFromInstruction(code_line);
|
||||
|
||||
if (target_addr)
|
||||
emit ShowMemory(*target_addr);
|
||||
|
@ -794,7 +798,7 @@ void CodeViewWidget::OnCopyCode()
|
|||
|
||||
const std::string text = [this, addr] {
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
return PowerPC::debug_interface.Disassemble(&guard, addr);
|
||||
return m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr);
|
||||
}();
|
||||
|
||||
QApplication::clipboard()->setText(QString::fromStdString(text));
|
||||
|
@ -818,7 +822,8 @@ void CodeViewWidget::OnCopyFunction()
|
|||
const u32 end = start + symbol->size;
|
||||
for (u32 addr = start; addr != end; addr += 4)
|
||||
{
|
||||
const std::string disasm = PowerPC::debug_interface.Disassemble(&guard, addr);
|
||||
const std::string disasm =
|
||||
m_system.GetPowerPC().GetDebugInterface().Disassemble(&guard, addr);
|
||||
fmt::format_to(std::back_inserter(text), "{:08x}: {}\r\n", addr, disasm);
|
||||
}
|
||||
}
|
||||
|
@ -832,7 +837,7 @@ void CodeViewWidget::OnCopyHex()
|
|||
|
||||
const u32 instruction = [this, addr] {
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
return PowerPC::debug_interface.ReadInstruction(guard, addr);
|
||||
return m_system.GetPowerPC().GetDebugInterface().ReadInstruction(guard, addr);
|
||||
}();
|
||||
|
||||
QApplication::clipboard()->setText(
|
||||
|
@ -843,8 +848,8 @@ void CodeViewWidget::OnRunToHere()
|
|||
{
|
||||
const u32 addr = GetContextAddress();
|
||||
|
||||
PowerPC::debug_interface.SetBreakpoint(addr);
|
||||
PowerPC::debug_interface.RunToBreakpoint();
|
||||
m_system.GetPowerPC().GetDebugInterface().SetBreakpoint(addr);
|
||||
m_system.GetPowerPC().GetDebugInterface().RunToBreakpoint();
|
||||
Update();
|
||||
}
|
||||
|
||||
|
@ -997,11 +1002,12 @@ void CodeViewWidget::OnReplaceInstruction()
|
|||
if (!read_result.valid)
|
||||
return;
|
||||
|
||||
PatchInstructionDialog dialog(this, addr, PowerPC::debug_interface.ReadInstruction(guard, addr));
|
||||
auto& debug_interface = m_system.GetPowerPC().GetDebugInterface();
|
||||
PatchInstructionDialog dialog(this, addr, debug_interface.ReadInstruction(guard, addr));
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
PowerPC::debug_interface.SetPatch(guard, addr, dialog.GetCode());
|
||||
debug_interface.SetPatch(guard, addr, dialog.GetCode());
|
||||
Update(&guard);
|
||||
}
|
||||
}
|
||||
|
@ -1012,7 +1018,7 @@ void CodeViewWidget::OnRestoreInstruction()
|
|||
|
||||
const u32 addr = GetContextAddress();
|
||||
|
||||
PowerPC::debug_interface.UnsetPatch(guard, addr);
|
||||
m_system.GetPowerPC().GetDebugInterface().UnsetPatch(guard, addr);
|
||||
Update(&guard);
|
||||
}
|
||||
|
||||
|
@ -1091,10 +1097,11 @@ void CodeViewWidget::showEvent(QShowEvent* event)
|
|||
|
||||
void CodeViewWidget::ToggleBreakpoint()
|
||||
{
|
||||
if (PowerPC::debug_interface.IsBreakpoint(GetContextAddress()))
|
||||
PowerPC::breakpoints.Remove(GetContextAddress());
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
if (power_pc.GetDebugInterface().IsBreakpoint(GetContextAddress()))
|
||||
power_pc.GetBreakPoints().Remove(GetContextAddress());
|
||||
else
|
||||
PowerPC::breakpoints.Add(GetContextAddress());
|
||||
power_pc.GetBreakPoints().Add(GetContextAddress());
|
||||
|
||||
emit BreakpointsChanged();
|
||||
Update();
|
||||
|
@ -1102,7 +1109,7 @@ void CodeViewWidget::ToggleBreakpoint()
|
|||
|
||||
void CodeViewWidget::AddBreakpoint()
|
||||
{
|
||||
PowerPC::breakpoints.Add(GetContextAddress());
|
||||
m_system.GetPowerPC().GetBreakPoints().Add(GetContextAddress());
|
||||
|
||||
emit BreakpointsChanged();
|
||||
Update();
|
||||
|
|
|
@ -442,12 +442,13 @@ void CodeWidget::Step()
|
|||
|
||||
Common::Event sync_event;
|
||||
|
||||
PowerPC::CoreMode old_mode = PowerPC::GetMode();
|
||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||
PowerPC::breakpoints.ClearAllTemporary();
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
PowerPC::CoreMode old_mode = power_pc.GetMode();
|
||||
power_pc.SetMode(PowerPC::CoreMode::Interpreter);
|
||||
power_pc.GetBreakPoints().ClearAllTemporary();
|
||||
cpu.StepOpcode(&sync_event);
|
||||
sync_event.WaitFor(std::chrono::milliseconds(20));
|
||||
PowerPC::SetMode(old_mode);
|
||||
power_pc.SetMode(old_mode);
|
||||
Core::DisplayMessage(tr("Step successful!").toStdString(), 2000);
|
||||
// Will get a UpdateDisasmDialog(), don't update the GUI here.
|
||||
}
|
||||
|
@ -466,8 +467,9 @@ void CodeWidget::StepOver()
|
|||
|
||||
if (inst.LK)
|
||||
{
|
||||
PowerPC::breakpoints.ClearAllTemporary();
|
||||
PowerPC::breakpoints.Add(m_system.GetPPCState().pc + 4, true);
|
||||
auto& breakpoints = m_system.GetPowerPC().GetBreakPoints();
|
||||
breakpoints.ClearAllTemporary();
|
||||
breakpoints.Add(m_system.GetPPCState().pc + 4, true);
|
||||
cpu.EnableStepping(false);
|
||||
Core::DisplayMessage(tr("Step over in progress...").toStdString(), 2000);
|
||||
}
|
||||
|
@ -501,14 +503,16 @@ void CodeWidget::StepOut()
|
|||
using clock = std::chrono::steady_clock;
|
||||
clock::time_point timeout = clock::now() + std::chrono::seconds(5);
|
||||
|
||||
auto& ppc_state = m_system.GetPPCState();
|
||||
auto& power_pc = m_system.GetPowerPC();
|
||||
auto& ppc_state = power_pc.GetPPCState();
|
||||
auto& breakpoints = power_pc.GetBreakPoints();
|
||||
{
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
|
||||
PowerPC::breakpoints.ClearAllTemporary();
|
||||
breakpoints.ClearAllTemporary();
|
||||
|
||||
PowerPC::CoreMode old_mode = PowerPC::GetMode();
|
||||
PowerPC::SetMode(PowerPC::CoreMode::Interpreter);
|
||||
PowerPC::CoreMode old_mode = power_pc.GetMode();
|
||||
power_pc.SetMode(PowerPC::CoreMode::Interpreter);
|
||||
|
||||
// Loop until either the current instruction is a return instruction with no Link flag
|
||||
// or a breakpoint is detected so it can step at the breakpoint. If the PC is currently
|
||||
|
@ -518,7 +522,7 @@ void CodeWidget::StepOut()
|
|||
{
|
||||
if (WillInstructionReturn(m_system, inst))
|
||||
{
|
||||
PowerPC::SingleStep();
|
||||
power_pc.SingleStep();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -528,24 +532,24 @@ void CodeWidget::StepOut()
|
|||
u32 next_pc = ppc_state.pc + 4;
|
||||
do
|
||||
{
|
||||
PowerPC::SingleStep();
|
||||
power_pc.SingleStep();
|
||||
} while (ppc_state.pc != next_pc && clock::now() < timeout &&
|
||||
!PowerPC::breakpoints.IsAddressBreakPoint(ppc_state.pc));
|
||||
!breakpoints.IsAddressBreakPoint(ppc_state.pc));
|
||||
}
|
||||
else
|
||||
{
|
||||
PowerPC::SingleStep();
|
||||
power_pc.SingleStep();
|
||||
}
|
||||
|
||||
inst = PowerPC::MMU::HostRead_Instruction(guard, ppc_state.pc);
|
||||
} while (clock::now() < timeout && !PowerPC::breakpoints.IsAddressBreakPoint(ppc_state.pc));
|
||||
} while (clock::now() < timeout && !breakpoints.IsAddressBreakPoint(ppc_state.pc));
|
||||
|
||||
PowerPC::SetMode(old_mode);
|
||||
power_pc.SetMode(old_mode);
|
||||
}
|
||||
|
||||
emit Host::GetInstance()->UpdateDisasmDialog();
|
||||
|
||||
if (PowerPC::breakpoints.IsAddressBreakPoint(ppc_state.pc))
|
||||
if (breakpoints.IsAddressBreakPoint(ppc_state.pc))
|
||||
Core::DisplayMessage(tr("Breakpoint encountered! Step out aborted.").toStdString(), 2000);
|
||||
else if (clock::now() >= timeout)
|
||||
Core::DisplayMessage(tr("Step out timed out!").toStdString(), 2000);
|
||||
|
|
|
@ -170,7 +170,8 @@ private:
|
|||
MemoryViewWidget* m_view;
|
||||
};
|
||||
|
||||
MemoryViewWidget::MemoryViewWidget(QWidget* parent) : QWidget(parent)
|
||||
MemoryViewWidget::MemoryViewWidget(QWidget* parent)
|
||||
: QWidget(parent), m_system(Core::System::GetInstance())
|
||||
{
|
||||
auto* layout = new QHBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
@ -571,7 +572,7 @@ void MemoryViewWidget::UpdateBreakpointTags()
|
|||
}
|
||||
|
||||
if (m_address_space == AddressSpace::Type::Effective &&
|
||||
PowerPC::memchecks.GetMemCheck(address, GetTypeSize(m_type)) != nullptr)
|
||||
m_system.GetPowerPC().GetMemChecks().GetMemCheck(address, GetTypeSize(m_type)) != nullptr)
|
||||
{
|
||||
row_breakpoint = true;
|
||||
cell->setBackground(Qt::red);
|
||||
|
@ -808,15 +809,17 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row)
|
|||
const int breaks = row ? (m_bytes_per_row / length) : 1;
|
||||
bool overlap = false;
|
||||
|
||||
auto& memchecks = m_system.GetPowerPC().GetMemChecks();
|
||||
|
||||
// Row breakpoint should either remove any breakpoint left on the row, or activate all
|
||||
// breakpoints.
|
||||
if (row && PowerPC::memchecks.OverlapsMemcheck(addr, m_bytes_per_row))
|
||||
if (row && memchecks.OverlapsMemcheck(addr, m_bytes_per_row))
|
||||
overlap = true;
|
||||
|
||||
for (int i = 0; i < breaks; i++)
|
||||
{
|
||||
u32 address = addr + length * i;
|
||||
TMemCheck* check_ptr = PowerPC::memchecks.GetMemCheck(address, length);
|
||||
TMemCheck* check_ptr = memchecks.GetMemCheck(address, length);
|
||||
|
||||
if (check_ptr == nullptr && !overlap)
|
||||
{
|
||||
|
@ -829,12 +832,12 @@ void MemoryViewWidget::ToggleBreakpoint(u32 addr, bool row)
|
|||
check.log_on_hit = m_do_log;
|
||||
check.break_on_hit = true;
|
||||
|
||||
PowerPC::memchecks.Add(std::move(check));
|
||||
memchecks.Add(std::move(check));
|
||||
}
|
||||
else if (check_ptr != nullptr)
|
||||
{
|
||||
// Using the pointer fixes misaligned breakpoints (0x11 breakpoint in 0x10 aligned view).
|
||||
PowerPC::memchecks.Remove(check_ptr->start_address);
|
||||
memchecks.Remove(check_ptr->start_address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ enum class Type;
|
|||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
}
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
class MemoryViewTable;
|
||||
|
||||
|
@ -85,6 +86,8 @@ private:
|
|||
void ScrollbarSliderReleased();
|
||||
QString ValueToString(const Core::CPUThreadGuard& guard, u32 address, Type type);
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
MemoryViewTable* m_table;
|
||||
QScrollBar* m_scrollbar;
|
||||
AddressSpace::Type m_address_space{};
|
||||
|
|
|
@ -409,7 +409,9 @@ void RegisterWidget::PopulateTable()
|
|||
|
||||
// Special registers
|
||||
// TB
|
||||
AddRegister(16, 5, RegisterType::tb, "TB", PowerPC::ReadFullTimeBaseValue, nullptr);
|
||||
AddRegister(
|
||||
16, 5, RegisterType::tb, "TB",
|
||||
[this] { return m_system.GetPowerPC().ReadFullTimeBaseValue(); }, nullptr);
|
||||
|
||||
// PC
|
||||
AddRegister(
|
||||
|
|
|
@ -314,7 +314,7 @@ void ThreadWidget::Update()
|
|||
m_queue_tail->setText(format_hex_from(guard, 0x800000E0));
|
||||
|
||||
// Thread group
|
||||
m_threads = PowerPC::debug_interface.GetThreads(guard);
|
||||
m_threads = guard.GetSystem().GetPowerPC().GetDebugInterface().GetThreads(guard);
|
||||
|
||||
int i = 0;
|
||||
m_thread_table->setRowCount(i);
|
||||
|
@ -458,9 +458,10 @@ void ThreadWidget::UpdateThreadCallstack(const Core::CPUThreadGuard& guard,
|
|||
{
|
||||
const u32 lr_save = PowerPC::MMU::HostRead_U32(guard, sp + 4);
|
||||
m_callstack_table->setItem(i, 2, new QTableWidgetItem(format_hex(lr_save)));
|
||||
m_callstack_table->setItem(i, 3,
|
||||
new QTableWidgetItem(QString::fromStdString(
|
||||
PowerPC::debug_interface.GetDescription(lr_save))));
|
||||
m_callstack_table->setItem(
|
||||
i, 3,
|
||||
new QTableWidgetItem(QString::fromStdString(
|
||||
guard.GetSystem().GetPowerPC().GetDebugInterface().GetDescription(lr_save))));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
#include "DolphinQt/Resources.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
WatchWidget::WatchWidget(QWidget* parent) : QDockWidget(parent)
|
||||
WatchWidget::WatchWidget(QWidget* parent)
|
||||
: QDockWidget(parent), m_system(Core::System::GetInstance())
|
||||
{
|
||||
// i18n: This kind of "watch" is used for watching emulated memory.
|
||||
// It's not related to timekeeping devices.
|
||||
|
@ -167,15 +168,16 @@ void WatchWidget::Update()
|
|||
m_table->setDisabled(false);
|
||||
m_table->clearContents();
|
||||
|
||||
Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
auto& debug_interface = guard.GetSystem().GetPowerPC().GetDebugInterface();
|
||||
|
||||
int size = static_cast<int>(PowerPC::debug_interface.GetWatches().size());
|
||||
int size = static_cast<int>(debug_interface.GetWatches().size());
|
||||
|
||||
m_table->setRowCount(size + 1);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const auto& entry = PowerPC::debug_interface.GetWatch(i);
|
||||
const auto& entry = debug_interface.GetWatch(i);
|
||||
|
||||
auto* label = new QTableWidgetItem(QString::fromStdString(entry.name));
|
||||
auto* address =
|
||||
|
@ -263,7 +265,7 @@ void WatchWidget::OnDelete()
|
|||
|
||||
void WatchWidget::OnClear()
|
||||
{
|
||||
PowerPC::debug_interface.ClearWatches();
|
||||
m_system.GetPowerPC().GetDebugInterface().ClearWatches();
|
||||
Update();
|
||||
}
|
||||
|
||||
|
@ -297,16 +299,17 @@ void WatchWidget::OnLoad()
|
|||
return;
|
||||
}
|
||||
|
||||
Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
|
||||
if (ini.GetLines("Watches", &watches, false))
|
||||
{
|
||||
for (const auto& watch : PowerPC::debug_interface.GetWatches())
|
||||
auto& debug_interface = guard.GetSystem().GetPowerPC().GetDebugInterface();
|
||||
for (const auto& watch : debug_interface.GetWatches())
|
||||
{
|
||||
PowerPC::debug_interface.UnsetPatch(guard, watch.address);
|
||||
debug_interface.UnsetPatch(guard, watch.address);
|
||||
}
|
||||
PowerPC::debug_interface.ClearWatches();
|
||||
PowerPC::debug_interface.LoadWatchesFromStrings(watches);
|
||||
debug_interface.ClearWatches();
|
||||
debug_interface.LoadWatchesFromStrings(watches);
|
||||
}
|
||||
|
||||
Update();
|
||||
|
@ -317,7 +320,7 @@ void WatchWidget::OnSave()
|
|||
IniFile ini;
|
||||
ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini",
|
||||
false);
|
||||
ini.SetLines("Watches", PowerPC::debug_interface.SaveWatchesToStrings());
|
||||
ini.SetLines("Watches", m_system.GetPowerPC().GetDebugInterface().SaveWatchesToStrings());
|
||||
ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + SConfig::GetInstance().GetGameID() + ".ini");
|
||||
}
|
||||
|
||||
|
@ -394,7 +397,7 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)
|
|||
if (item->text().isEmpty())
|
||||
DeleteWatchAndUpdate(row);
|
||||
else
|
||||
PowerPC::debug_interface.UpdateWatchName(row, item->text().toStdString());
|
||||
m_system.GetPowerPC().GetDebugInterface().UpdateWatchName(row, item->text().toStdString());
|
||||
break;
|
||||
case COLUMN_INDEX_ADDRESS:
|
||||
case COLUMN_INDEX_HEX:
|
||||
|
@ -407,19 +410,20 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)
|
|||
|
||||
if (good)
|
||||
{
|
||||
Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
|
||||
auto& debug_interface = m_system.GetPowerPC().GetDebugInterface();
|
||||
if (column == COLUMN_INDEX_ADDRESS)
|
||||
{
|
||||
const auto& watch = PowerPC::debug_interface.GetWatch(row);
|
||||
PowerPC::debug_interface.UnsetPatch(guard, watch.address);
|
||||
PowerPC::debug_interface.UpdateWatchAddress(row, value);
|
||||
const auto& watch = debug_interface.GetWatch(row);
|
||||
debug_interface.UnsetPatch(guard, watch.address);
|
||||
debug_interface.UpdateWatchAddress(row, value);
|
||||
if (watch.locked)
|
||||
LockWatchAddress(guard, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
PowerPC::MMU::HostWrite_U32(guard, value, PowerPC::debug_interface.GetWatch(row).address);
|
||||
PowerPC::MMU::HostWrite_U32(guard, value, debug_interface.GetWatch(row).address);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -430,13 +434,14 @@ void WatchWidget::OnItemChanged(QTableWidgetItem* item)
|
|||
}
|
||||
case COLUMN_INDEX_LOCK:
|
||||
{
|
||||
PowerPC::debug_interface.UpdateWatchLockedState(row, item->checkState() == Qt::Checked);
|
||||
const auto& watch = PowerPC::debug_interface.GetWatch(row);
|
||||
Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
auto& debug_interface = m_system.GetPowerPC().GetDebugInterface();
|
||||
debug_interface.UpdateWatchLockedState(row, item->checkState() == Qt::Checked);
|
||||
const auto& watch = debug_interface.GetWatch(row);
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
if (watch.locked)
|
||||
LockWatchAddress(guard, watch.address);
|
||||
else
|
||||
PowerPC::debug_interface.UnsetPatch(guard, watch.address);
|
||||
debug_interface.UnsetPatch(guard, watch.address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -455,13 +460,13 @@ void WatchWidget::LockWatchAddress(const Core::CPUThreadGuard& guard, u32 addres
|
|||
bytes.push_back(static_cast<u8>(c));
|
||||
}
|
||||
|
||||
PowerPC::debug_interface.SetFramePatch(guard, address, bytes);
|
||||
m_system.GetPowerPC().GetDebugInterface().SetFramePatch(guard, address, bytes);
|
||||
}
|
||||
|
||||
void WatchWidget::DeleteSelectedWatches()
|
||||
{
|
||||
{
|
||||
Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
std::vector<int> row_indices;
|
||||
for (const auto& index : m_table->selectionModel()->selectedRows())
|
||||
{
|
||||
|
@ -486,14 +491,15 @@ void WatchWidget::DeleteSelectedWatches()
|
|||
|
||||
void WatchWidget::DeleteWatch(const Core::CPUThreadGuard& guard, int row)
|
||||
{
|
||||
PowerPC::debug_interface.UnsetPatch(guard, PowerPC::debug_interface.GetWatch(row).address);
|
||||
PowerPC::debug_interface.RemoveWatch(row);
|
||||
auto& debug_interface = m_system.GetPowerPC().GetDebugInterface();
|
||||
debug_interface.UnsetPatch(guard, debug_interface.GetWatch(row).address);
|
||||
debug_interface.RemoveWatch(row);
|
||||
}
|
||||
|
||||
void WatchWidget::DeleteWatchAndUpdate(int row)
|
||||
{
|
||||
{
|
||||
Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
DeleteWatch(guard, row);
|
||||
}
|
||||
|
||||
|
@ -502,24 +508,25 @@ void WatchWidget::DeleteWatchAndUpdate(int row)
|
|||
|
||||
void WatchWidget::AddWatchBreakpoint(int row)
|
||||
{
|
||||
emit RequestMemoryBreakpoint(PowerPC::debug_interface.GetWatch(row).address);
|
||||
emit RequestMemoryBreakpoint(m_system.GetPowerPC().GetDebugInterface().GetWatch(row).address);
|
||||
}
|
||||
|
||||
void WatchWidget::ShowInMemory(int row)
|
||||
{
|
||||
emit ShowMemory(PowerPC::debug_interface.GetWatch(row).address);
|
||||
emit ShowMemory(m_system.GetPowerPC().GetDebugInterface().GetWatch(row).address);
|
||||
}
|
||||
|
||||
void WatchWidget::AddWatch(QString name, u32 addr)
|
||||
{
|
||||
PowerPC::debug_interface.SetWatch(addr, name.toStdString());
|
||||
m_system.GetPowerPC().GetDebugInterface().SetWatch(addr, name.toStdString());
|
||||
Update();
|
||||
}
|
||||
|
||||
void WatchWidget::LockSelectedWatches()
|
||||
{
|
||||
{
|
||||
Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
auto& debug_interface = m_system.GetPowerPC().GetDebugInterface();
|
||||
for (const auto& index : m_table->selectionModel()->selectedRows())
|
||||
{
|
||||
const auto* item = m_table->item(index.row(), index.column());
|
||||
|
@ -527,10 +534,10 @@ void WatchWidget::LockSelectedWatches()
|
|||
if (row_variant.isNull())
|
||||
continue;
|
||||
const int row = row_variant.toInt();
|
||||
const auto& watch = PowerPC::debug_interface.GetWatch(row);
|
||||
const auto& watch = debug_interface.GetWatch(row);
|
||||
if (watch.locked)
|
||||
continue;
|
||||
PowerPC::debug_interface.UpdateWatchLockedState(row, true);
|
||||
debug_interface.UpdateWatchLockedState(row, true);
|
||||
LockWatchAddress(guard, watch.address);
|
||||
}
|
||||
}
|
||||
|
@ -541,7 +548,8 @@ void WatchWidget::LockSelectedWatches()
|
|||
void WatchWidget::UnlockSelectedWatches()
|
||||
{
|
||||
{
|
||||
Core::CPUThreadGuard guard(Core::System::GetInstance());
|
||||
auto& debug_interface = m_system.GetPowerPC().GetDebugInterface();
|
||||
Core::CPUThreadGuard guard(m_system);
|
||||
for (const auto& index : m_table->selectionModel()->selectedRows())
|
||||
{
|
||||
const auto* item = m_table->item(index.row(), index.column());
|
||||
|
@ -549,11 +557,11 @@ void WatchWidget::UnlockSelectedWatches()
|
|||
if (row_variant.isNull())
|
||||
continue;
|
||||
const int row = row_variant.toInt();
|
||||
const auto& watch = PowerPC::debug_interface.GetWatch(row);
|
||||
const auto& watch = debug_interface.GetWatch(row);
|
||||
if (!watch.locked)
|
||||
continue;
|
||||
PowerPC::debug_interface.UpdateWatchLockedState(row, false);
|
||||
PowerPC::debug_interface.UnsetPatch(guard, watch.address);
|
||||
debug_interface.UpdateWatchLockedState(row, false);
|
||||
debug_interface.UnsetPatch(guard, watch.address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ class QToolBar;
|
|||
namespace Core
|
||||
{
|
||||
class CPUThreadGuard;
|
||||
};
|
||||
class System;
|
||||
}; // namespace Core
|
||||
|
||||
class WatchWidget : public QDockWidget
|
||||
{
|
||||
|
@ -62,6 +63,8 @@ private:
|
|||
void LockSelectedWatches();
|
||||
void UnlockSelectedWatches();
|
||||
|
||||
Core::System& m_system;
|
||||
|
||||
QAction* m_new;
|
||||
QAction* m_delete;
|
||||
QAction* m_clear;
|
||||
|
|
|
@ -800,7 +800,8 @@ void MenuBar::AddJITMenu()
|
|||
PowerPC::CPUCore::Interpreter);
|
||||
|
||||
connect(m_jit_interpreter_core, &QAction::toggled, [](bool enabled) {
|
||||
PowerPC::SetMode(enabled ? PowerPC::CoreMode::Interpreter : PowerPC::CoreMode::JIT);
|
||||
Core::System::GetInstance().GetPowerPC().SetMode(enabled ? PowerPC::CoreMode::Interpreter :
|
||||
PowerPC::CoreMode::JIT);
|
||||
});
|
||||
|
||||
m_jit->addSeparator();
|
||||
|
|
|
@ -38,7 +38,7 @@ void CallbackTemplate(Core::System& system, u64 userdata, s64 lateness)
|
|||
class ScopeInit final
|
||||
{
|
||||
public:
|
||||
ScopeInit() : m_profile_path(File::CreateTempDir())
|
||||
explicit ScopeInit(Core::System& system) : m_system(system), m_profile_path(File::CreateTempDir())
|
||||
{
|
||||
if (!UserDirectoryExists())
|
||||
{
|
||||
|
@ -48,8 +48,7 @@ public:
|
|||
UICommon::SetUserDirectory(m_profile_path);
|
||||
Config::Init();
|
||||
SConfig::Init();
|
||||
PowerPC::Init(PowerPC::CPUCore::Interpreter);
|
||||
auto& system = Core::System::GetInstance();
|
||||
system.GetPowerPC().Init(PowerPC::CPUCore::Interpreter);
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
core_timing.Init();
|
||||
}
|
||||
|
@ -59,10 +58,9 @@ public:
|
|||
{
|
||||
return;
|
||||
}
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
auto& core_timing = m_system.GetCoreTiming();
|
||||
core_timing.Shutdown();
|
||||
PowerPC::Shutdown();
|
||||
m_system.GetPowerPC().Shutdown();
|
||||
SConfig::Shutdown();
|
||||
Config::Shutdown();
|
||||
Core::UndeclareAsCPUThread();
|
||||
|
@ -71,6 +69,7 @@ public:
|
|||
bool UserDirectoryExists() const { return !m_profile_path.empty(); }
|
||||
|
||||
private:
|
||||
Core::System& m_system;
|
||||
std::string m_profile_path;
|
||||
};
|
||||
|
||||
|
@ -92,10 +91,11 @@ static void AdvanceAndCheck(Core::System& system, u32 idx, int downcount, int ex
|
|||
|
||||
TEST(CoreTiming, BasicOrder)
|
||||
{
|
||||
ScopeInit guard;
|
||||
auto& system = Core::System::GetInstance();
|
||||
|
||||
ScopeInit guard(system);
|
||||
ASSERT_TRUE(guard.UserDirectoryExists());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
auto& ppc_state = system.GetPPCState();
|
||||
|
||||
|
@ -147,10 +147,11 @@ TEST(CoreTiming, SharedSlot)
|
|||
{
|
||||
using namespace SharedSlotTest;
|
||||
|
||||
ScopeInit guard;
|
||||
auto& system = Core::System::GetInstance();
|
||||
|
||||
ScopeInit guard(system);
|
||||
ASSERT_TRUE(guard.UserDirectoryExists());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
auto& ppc_state = system.GetPPCState();
|
||||
|
||||
|
@ -181,10 +182,11 @@ TEST(CoreTiming, SharedSlot)
|
|||
|
||||
TEST(CoreTiming, PredictableLateness)
|
||||
{
|
||||
ScopeInit guard;
|
||||
auto& system = Core::System::GetInstance();
|
||||
|
||||
ScopeInit guard(system);
|
||||
ASSERT_TRUE(guard.UserDirectoryExists());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
|
||||
CoreTiming::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>);
|
||||
|
@ -222,10 +224,11 @@ TEST(CoreTiming, ChainScheduling)
|
|||
{
|
||||
using namespace ChainSchedulingTest;
|
||||
|
||||
ScopeInit guard;
|
||||
auto& system = Core::System::GetInstance();
|
||||
|
||||
ScopeInit guard(system);
|
||||
ASSERT_TRUE(guard.UserDirectoryExists());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
auto& ppc_state = system.GetPPCState();
|
||||
|
||||
|
@ -282,10 +285,11 @@ TEST(CoreTiming, ScheduleIntoPast)
|
|||
{
|
||||
using namespace ScheduleIntoPastTest;
|
||||
|
||||
ScopeInit guard;
|
||||
auto& system = Core::System::GetInstance();
|
||||
|
||||
ScopeInit guard(system);
|
||||
ASSERT_TRUE(guard.UserDirectoryExists());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
auto& ppc_state = system.GetPPCState();
|
||||
|
||||
|
@ -325,10 +329,11 @@ TEST(CoreTiming, ScheduleIntoPast)
|
|||
|
||||
TEST(CoreTiming, Overclocking)
|
||||
{
|
||||
ScopeInit guard;
|
||||
auto& system = Core::System::GetInstance();
|
||||
|
||||
ScopeInit guard(system);
|
||||
ASSERT_TRUE(guard.UserDirectoryExists());
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
auto& ppc_state = system.GetPPCState();
|
||||
|
||||
|
|
Loading…
Reference in New Issue