mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-28 18:09:37 -06:00

Fix Frame Advance and FifoPlayer pause/unpause/stop. CPU::EnableStepping is not atomic but is called from multiple threads which races and leaves the system in a random state; also instruction stepping was unstable, m_StepEvent had an almost random value because of the dual purpose it served which could cause races where CPU::Run would SingleStep when it was supposed to be sleeping. FifoPlayer never FinishStateMove()d which was causing it to deadlock. Rather than partially reimplementing CPU::Run, just use CPUCoreBase and then call CPU::Run(). More DRY and less likely to have weird bugs specific to the player (i.e the previous freezing on pause/stop). Refactor PowerPC::state into CPU since it manages the state of the CPU Thread which is controlled by CPU, not PowerPC. This simplifies the architecture somewhat and eliminates races that can be caused by calling PowerPC state functions directly instead of using CPU's (because they bypassed the EnableStepping lock).
219 lines
4.6 KiB
C++
219 lines
4.6 KiB
C++
// Copyright 2008 Dolphin Emulator Project
|
|
// Licensed under GPLv2+
|
|
// Refer to the license.txt file included.
|
|
|
|
#include <string>
|
|
|
|
#include "Common/GekkoDisassembler.h"
|
|
|
|
#include "Core/Core.h"
|
|
#include "Core/Host.h"
|
|
#include "Core/Debugger/Debugger_SymbolMap.h"
|
|
#include "Core/Debugger/PPCDebugInterface.h"
|
|
#include "Core/HW/DSP.h"
|
|
#include "Core/HW/Memmap.h"
|
|
#include "Core/PowerPC/PowerPC.h"
|
|
#include "Core/PowerPC/PPCSymbolDB.h"
|
|
#include "Core/PowerPC/JitCommon/JitBase.h"
|
|
|
|
std::string PPCDebugInterface::Disassemble(unsigned int address)
|
|
{
|
|
// PowerPC::HostRead_U32 seemed to crash on shutdown
|
|
if (!IsAlive())
|
|
return "";
|
|
|
|
if (Core::GetState() == Core::CORE_PAUSE)
|
|
{
|
|
if (!PowerPC::HostIsRAMAddress(address))
|
|
{
|
|
return "(No RAM here)";
|
|
}
|
|
|
|
u32 op = PowerPC::HostRead_Instruction(address);
|
|
std::string disasm = GekkoDisassembler::Disassemble(op, address);
|
|
|
|
UGeckoInstruction inst;
|
|
inst.hex = PowerPC::HostRead_U32(address);
|
|
|
|
if (inst.OPCD == 1)
|
|
{
|
|
disasm += " (hle)";
|
|
}
|
|
|
|
return disasm;
|
|
}
|
|
else
|
|
{
|
|
return "<unknown>";
|
|
}
|
|
}
|
|
|
|
void PPCDebugInterface::GetRawMemoryString(int memory, unsigned int address, char *dest, int max_size)
|
|
{
|
|
if (IsAlive())
|
|
{
|
|
if (memory || PowerPC::HostIsRAMAddress(address))
|
|
{
|
|
snprintf(dest, max_size, "%08X%s", ReadExtraMemory(memory, address), memory ? " (ARAM)" : "");
|
|
}
|
|
else
|
|
{
|
|
strcpy(dest, memory ? "--ARAM--" : "--------");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
strcpy(dest, "<unknwn>"); // bad spelling - 8 chars
|
|
}
|
|
}
|
|
|
|
unsigned int PPCDebugInterface::ReadMemory(unsigned int address)
|
|
{
|
|
return PowerPC::HostRead_U32(address);
|
|
}
|
|
|
|
unsigned int PPCDebugInterface::ReadExtraMemory(int memory, unsigned int address)
|
|
{
|
|
switch (memory)
|
|
{
|
|
case 0:
|
|
return PowerPC::HostRead_U32(address);
|
|
case 1:
|
|
return (DSP::ReadARAM(address) << 24) |
|
|
(DSP::ReadARAM(address + 1) << 16) |
|
|
(DSP::ReadARAM(address + 2) << 8) |
|
|
(DSP::ReadARAM(address + 3));
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
unsigned int PPCDebugInterface::ReadInstruction(unsigned int address)
|
|
{
|
|
return PowerPC::HostRead_Instruction(address);
|
|
}
|
|
|
|
bool PPCDebugInterface::IsAlive()
|
|
{
|
|
return Core::IsRunning();
|
|
}
|
|
|
|
bool PPCDebugInterface::IsBreakpoint(unsigned int address)
|
|
{
|
|
return PowerPC::breakpoints.IsAddressBreakPoint(address);
|
|
}
|
|
|
|
void PPCDebugInterface::SetBreakpoint(unsigned int address)
|
|
{
|
|
PowerPC::breakpoints.Add(address);
|
|
}
|
|
|
|
void PPCDebugInterface::ClearBreakpoint(unsigned int address)
|
|
{
|
|
PowerPC::breakpoints.Remove(address);
|
|
}
|
|
|
|
void PPCDebugInterface::ClearAllBreakpoints()
|
|
{
|
|
PowerPC::breakpoints.Clear();
|
|
}
|
|
|
|
void PPCDebugInterface::ToggleBreakpoint(unsigned int address)
|
|
{
|
|
if (PowerPC::breakpoints.IsAddressBreakPoint(address))
|
|
PowerPC::breakpoints.Remove(address);
|
|
else
|
|
PowerPC::breakpoints.Add(address);
|
|
}
|
|
|
|
void PPCDebugInterface::AddWatch(unsigned int address)
|
|
{
|
|
PowerPC::watches.Add(address);
|
|
}
|
|
|
|
void PPCDebugInterface::ClearAllMemChecks()
|
|
{
|
|
PowerPC::memchecks.Clear();
|
|
}
|
|
|
|
bool PPCDebugInterface::IsMemCheck(unsigned int address)
|
|
{
|
|
return (Memory::AreMemoryBreakpointsActivated() &&
|
|
PowerPC::memchecks.GetMemCheck(address));
|
|
}
|
|
|
|
void PPCDebugInterface::ToggleMemCheck(unsigned int address)
|
|
{
|
|
if (Memory::AreMemoryBreakpointsActivated() &&
|
|
!PowerPC::memchecks.GetMemCheck(address))
|
|
{
|
|
// Add Memory Check
|
|
TMemCheck MemCheck;
|
|
MemCheck.StartAddress = address;
|
|
MemCheck.EndAddress = address;
|
|
MemCheck.OnRead = true;
|
|
MemCheck.OnWrite = true;
|
|
|
|
MemCheck.Log = true;
|
|
MemCheck.Break = true;
|
|
|
|
PowerPC::memchecks.Add(MemCheck);
|
|
}
|
|
else
|
|
PowerPC::memchecks.Remove(address);
|
|
}
|
|
|
|
void PPCDebugInterface::InsertBLR(unsigned int address, unsigned int value)
|
|
{
|
|
PowerPC::HostWrite_U32(value, address);
|
|
}
|
|
|
|
|
|
// =======================================================
|
|
// Separate the blocks with colors.
|
|
// -------------
|
|
int PPCDebugInterface::GetColor(unsigned int address)
|
|
{
|
|
if (!IsAlive())
|
|
return 0xFFFFFF;
|
|
if (!PowerPC::HostIsRAMAddress(address))
|
|
return 0xeeeeee;
|
|
static const int colors[6] =
|
|
{
|
|
0xd0FFFF, // light cyan
|
|
0xFFd0d0, // light red
|
|
0xd8d8FF, // light blue
|
|
0xFFd0FF, // light purple
|
|
0xd0FFd0, // light green
|
|
0xFFFFd0, // light yellow
|
|
};
|
|
Symbol *symbol = g_symbolDB.GetSymbolFromAddr(address);
|
|
if (!symbol)
|
|
return 0xFFFFFF;
|
|
if (symbol->type != Symbol::SYMBOL_FUNCTION)
|
|
return 0xEEEEFF;
|
|
return colors[symbol->index % 6];
|
|
}
|
|
// =============
|
|
|
|
|
|
std::string PPCDebugInterface::GetDescription(unsigned int address)
|
|
{
|
|
return g_symbolDB.GetDescription(address);
|
|
}
|
|
|
|
unsigned int PPCDebugInterface::GetPC()
|
|
{
|
|
return PowerPC::ppcState.pc;
|
|
}
|
|
|
|
void PPCDebugInterface::SetPC(unsigned int address)
|
|
{
|
|
PowerPC::ppcState.pc = address;
|
|
}
|
|
|
|
void PPCDebugInterface::RunToBreakpoint()
|
|
{
|
|
|
|
}
|