mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 21:30:19 -06:00
Common: Move BreakPoints into Core
BreakPoints utilizes the jit global variable, so this was making Core and Common cyclical dependencies on one another.
This commit is contained in:
@ -156,6 +156,7 @@ set(SRCS ActionReplay.cpp
|
||||
IPC_HLE/WII_IPC_HLE_WiiMote.cpp
|
||||
IPC_HLE/WiiMote_HID_Attr.cpp
|
||||
IPC_HLE/WiiNetConfig.cpp
|
||||
PowerPC/BreakPoints.cpp
|
||||
PowerPC/MMU.cpp
|
||||
PowerPC/PowerPC.cpp
|
||||
PowerPC/PPCAnalyst.cpp
|
||||
|
@ -204,6 +204,7 @@
|
||||
<ClCompile Include="NetPlayClient.cpp" />
|
||||
<ClCompile Include="NetPlayServer.cpp" />
|
||||
<ClCompile Include="PatchEngine.cpp" />
|
||||
<ClCompile Include="PowerPC\BreakPoints.cpp" />
|
||||
<ClCompile Include="PowerPC\CachedInterpreter\CachedInterpreter.cpp" />
|
||||
<ClCompile Include="PowerPC\CachedInterpreter\InterpreterBlockCache.cpp" />
|
||||
<ClCompile Include="PowerPC\Interpreter\Interpreter.cpp" />
|
||||
@ -423,6 +424,7 @@
|
||||
<ClInclude Include="NetPlayProto.h" />
|
||||
<ClInclude Include="NetPlayServer.h" />
|
||||
<ClInclude Include="PatchEngine.h" />
|
||||
<ClInclude Include="PowerPC\BreakPoints.h" />
|
||||
<ClInclude Include="PowerPC\CPUCoreBase.h" />
|
||||
<ClInclude Include="PowerPC\Gekko.h" />
|
||||
<ClInclude Include="PowerPC\CachedInterpreter\CachedInterpreter.h" />
|
||||
|
@ -276,6 +276,9 @@
|
||||
<ClCompile Include="HLE\HLE_OS.cpp">
|
||||
<Filter>HLE</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowerPC\BreakPoints.cpp">
|
||||
<Filter>PowerPC</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PowerPC\CachedInterpreter\CachedInterpreter.cpp">
|
||||
<Filter>PowerPC\Cached Interpreter</Filter>
|
||||
</ClCompile>
|
||||
@ -1235,6 +1238,9 @@
|
||||
<ClInclude Include="HW\Wiimote.h">
|
||||
<Filter>HW %28Flipper/Hollywood%29\Wiimote</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PowerPC\BreakPoints.h">
|
||||
<Filter>PowerPC</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PowerPC\CPUCoreBase.h">
|
||||
<Filter>PowerPC</Filter>
|
||||
</ClInclude>
|
||||
|
314
Source/Core/Core/PowerPC/BreakPoints.cpp
Normal file
314
Source/Core/Core/PowerPC/BreakPoints.cpp
Normal file
@ -0,0 +1,314 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Core/PowerPC/BreakPoints.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/DebugInterface.h"
|
||||
#include "Core/PowerPC/JitCommon/JitBase.h"
|
||||
#include "Core/PowerPC/JitCommon/JitCache.h"
|
||||
|
||||
bool BreakPoints::IsAddressBreakPoint(u32 address) const
|
||||
{
|
||||
for (const TBreakPoint& bp : m_BreakPoints)
|
||||
if (bp.iAddress == address)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BreakPoints::IsTempBreakPoint(u32 address) const
|
||||
{
|
||||
for (const TBreakPoint& bp : m_BreakPoints)
|
||||
if (bp.iAddress == address && bp.bTemporary)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const
|
||||
{
|
||||
TBreakPointsStr bps;
|
||||
for (const TBreakPoint& bp : m_BreakPoints)
|
||||
{
|
||||
if (!bp.bTemporary)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << bp.iAddress << " " << (bp.bOn ? "n" : "");
|
||||
bps.push_back(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
return bps;
|
||||
}
|
||||
|
||||
void BreakPoints::AddFromStrings(const TBreakPointsStr& bpstrs)
|
||||
{
|
||||
for (const std::string& bpstr : bpstrs)
|
||||
{
|
||||
TBreakPoint bp;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << bpstr;
|
||||
ss >> bp.iAddress;
|
||||
bp.bOn = bpstr.find("n") != bpstr.npos;
|
||||
bp.bTemporary = false;
|
||||
Add(bp);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakPoints::Add(const TBreakPoint& bp)
|
||||
{
|
||||
if (!IsAddressBreakPoint(bp.iAddress))
|
||||
{
|
||||
m_BreakPoints.push_back(bp);
|
||||
if (g_jit)
|
||||
g_jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4, true);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakPoints::Add(u32 em_address, bool temp)
|
||||
{
|
||||
if (!IsAddressBreakPoint(em_address)) // only add new addresses
|
||||
{
|
||||
TBreakPoint pt; // breakpoint settings
|
||||
pt.bOn = true;
|
||||
pt.bTemporary = temp;
|
||||
pt.iAddress = em_address;
|
||||
|
||||
m_BreakPoints.push_back(pt);
|
||||
|
||||
if (g_jit)
|
||||
g_jit->GetBlockCache()->InvalidateICache(em_address, 4, true);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakPoints::Remove(u32 em_address)
|
||||
{
|
||||
for (auto i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
|
||||
{
|
||||
if (i->iAddress == em_address)
|
||||
{
|
||||
m_BreakPoints.erase(i);
|
||||
if (g_jit)
|
||||
g_jit->GetBlockCache()->InvalidateICache(em_address, 4, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BreakPoints::Clear()
|
||||
{
|
||||
if (g_jit)
|
||||
{
|
||||
for (const TBreakPoint& bp : m_BreakPoints)
|
||||
{
|
||||
g_jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4, true);
|
||||
}
|
||||
}
|
||||
|
||||
m_BreakPoints.clear();
|
||||
}
|
||||
|
||||
void BreakPoints::ClearAllTemporary()
|
||||
{
|
||||
auto bp = m_BreakPoints.begin();
|
||||
while (bp != m_BreakPoints.end())
|
||||
{
|
||||
if (bp->bTemporary)
|
||||
{
|
||||
if (g_jit)
|
||||
g_jit->GetBlockCache()->InvalidateICache(bp->iAddress, 4, true);
|
||||
bp = m_BreakPoints.erase(bp);
|
||||
}
|
||||
else
|
||||
{
|
||||
++bp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MemChecks::TMemChecksStr MemChecks::GetStrings() const
|
||||
{
|
||||
TMemChecksStr mcs;
|
||||
for (const TMemCheck& bp : m_MemChecks)
|
||||
{
|
||||
std::stringstream mc;
|
||||
mc << std::hex << bp.StartAddress;
|
||||
mc << " " << (bp.bRange ? bp.EndAddress : bp.StartAddress) << " " << (bp.bRange ? "n" : "")
|
||||
<< (bp.OnRead ? "r" : "") << (bp.OnWrite ? "w" : "") << (bp.Log ? "l" : "")
|
||||
<< (bp.Break ? "p" : "");
|
||||
mcs.push_back(mc.str());
|
||||
}
|
||||
|
||||
return mcs;
|
||||
}
|
||||
|
||||
void MemChecks::AddFromStrings(const TMemChecksStr& mcstrs)
|
||||
{
|
||||
for (const std::string& mcstr : mcstrs)
|
||||
{
|
||||
TMemCheck mc;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << mcstr;
|
||||
ss >> mc.StartAddress;
|
||||
mc.bRange = mcstr.find("n") != mcstr.npos;
|
||||
mc.OnRead = mcstr.find("r") != mcstr.npos;
|
||||
mc.OnWrite = mcstr.find("w") != mcstr.npos;
|
||||
mc.Log = mcstr.find("l") != mcstr.npos;
|
||||
mc.Break = mcstr.find("p") != mcstr.npos;
|
||||
if (mc.bRange)
|
||||
ss >> mc.EndAddress;
|
||||
else
|
||||
mc.EndAddress = mc.StartAddress;
|
||||
Add(mc);
|
||||
}
|
||||
}
|
||||
|
||||
void MemChecks::Add(const TMemCheck& _rMemoryCheck)
|
||||
{
|
||||
bool had_any = HasAny();
|
||||
if (GetMemCheck(_rMemoryCheck.StartAddress) == nullptr)
|
||||
m_MemChecks.push_back(_rMemoryCheck);
|
||||
// If this is the first one, clear the JIT cache so it can switch to
|
||||
// watchpoint-compatible code.
|
||||
if (!had_any && g_jit)
|
||||
g_jit->GetBlockCache()->SchedulateClearCacheThreadSafe();
|
||||
}
|
||||
|
||||
void MemChecks::Remove(u32 _Address)
|
||||
{
|
||||
for (auto i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i)
|
||||
{
|
||||
if (i->StartAddress == _Address)
|
||||
{
|
||||
m_MemChecks.erase(i);
|
||||
if (!HasAny() && g_jit)
|
||||
g_jit->GetBlockCache()->SchedulateClearCacheThreadSafe();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TMemCheck* MemChecks::GetMemCheck(u32 address)
|
||||
{
|
||||
for (TMemCheck& bp : m_MemChecks)
|
||||
{
|
||||
if (bp.bRange)
|
||||
{
|
||||
if (address >= bp.StartAddress && address <= bp.EndAddress)
|
||||
return &(bp);
|
||||
}
|
||||
else if (bp.StartAddress == address)
|
||||
{
|
||||
return &(bp);
|
||||
}
|
||||
}
|
||||
|
||||
// none found
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool TMemCheck::Action(DebugInterface* debug_interface, u32 iValue, u32 addr, bool write, int size,
|
||||
u32 pc)
|
||||
{
|
||||
if ((write && OnWrite) || (!write && OnRead))
|
||||
{
|
||||
if (Log)
|
||||
{
|
||||
NOTICE_LOG(MEMMAP, "MBP %08x (%s) %s%i %0*x at %08x (%s)", pc,
|
||||
debug_interface->GetDescription(pc).c_str(), write ? "Write" : "Read", size * 8,
|
||||
size * 2, iValue, addr, debug_interface->GetDescription(addr).c_str());
|
||||
}
|
||||
if (Break)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Watches::IsAddressWatch(u32 _iAddress) const
|
||||
{
|
||||
for (const TWatch& bp : m_Watches)
|
||||
if (bp.iAddress == _iAddress)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Watches::TWatchesStr Watches::GetStrings() const
|
||||
{
|
||||
TWatchesStr bps;
|
||||
for (const TWatch& bp : m_Watches)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << bp.iAddress << " " << bp.name;
|
||||
bps.push_back(ss.str());
|
||||
}
|
||||
|
||||
return bps;
|
||||
}
|
||||
|
||||
void Watches::AddFromStrings(const TWatchesStr& bpstrs)
|
||||
{
|
||||
for (const std::string& bpstr : bpstrs)
|
||||
{
|
||||
TWatch bp;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << bpstr;
|
||||
ss >> bp.iAddress;
|
||||
ss >> std::ws;
|
||||
getline(ss, bp.name);
|
||||
Add(bp);
|
||||
}
|
||||
}
|
||||
|
||||
void Watches::Add(const TWatch& bp)
|
||||
{
|
||||
if (!IsAddressWatch(bp.iAddress))
|
||||
{
|
||||
m_Watches.push_back(bp);
|
||||
}
|
||||
}
|
||||
|
||||
void Watches::Add(u32 em_address)
|
||||
{
|
||||
if (!IsAddressWatch(em_address)) // only add new addresses
|
||||
{
|
||||
TWatch pt; // breakpoint settings
|
||||
pt.bOn = true;
|
||||
pt.iAddress = em_address;
|
||||
|
||||
m_Watches.push_back(pt);
|
||||
}
|
||||
}
|
||||
|
||||
void Watches::Update(int count, u32 em_address)
|
||||
{
|
||||
m_Watches.at(count).iAddress = em_address;
|
||||
}
|
||||
|
||||
void Watches::UpdateName(int count, const std::string name)
|
||||
{
|
||||
m_Watches.at(count).name = name;
|
||||
}
|
||||
|
||||
void Watches::Remove(u32 em_address)
|
||||
{
|
||||
for (auto i = m_Watches.begin(); i != m_Watches.end(); ++i)
|
||||
{
|
||||
if (i->iAddress == em_address)
|
||||
{
|
||||
m_Watches.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Watches::Clear()
|
||||
{
|
||||
m_Watches.clear();
|
||||
}
|
130
Source/Core/Core/PowerPC/BreakPoints.h
Normal file
130
Source/Core/Core/PowerPC/BreakPoints.h
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
class DebugInterface;
|
||||
|
||||
struct TBreakPoint
|
||||
{
|
||||
u32 iAddress;
|
||||
bool bOn;
|
||||
bool bTemporary;
|
||||
};
|
||||
|
||||
struct TMemCheck
|
||||
{
|
||||
TMemCheck()
|
||||
{
|
||||
numHits = 0;
|
||||
StartAddress = EndAddress = 0;
|
||||
bRange = OnRead = OnWrite = Log = Break = false;
|
||||
}
|
||||
|
||||
u32 StartAddress;
|
||||
u32 EndAddress;
|
||||
|
||||
bool bRange;
|
||||
|
||||
bool OnRead;
|
||||
bool OnWrite;
|
||||
|
||||
bool Log;
|
||||
bool Break;
|
||||
|
||||
u32 numHits;
|
||||
|
||||
// returns whether to break
|
||||
bool Action(DebugInterface* dbg_interface, u32 _iValue, u32 addr, bool write, int size, u32 pc);
|
||||
};
|
||||
|
||||
struct TWatch
|
||||
{
|
||||
std::string name = "";
|
||||
u32 iAddress;
|
||||
bool bOn;
|
||||
};
|
||||
|
||||
// Code breakpoints.
|
||||
class BreakPoints
|
||||
{
|
||||
public:
|
||||
typedef std::vector<TBreakPoint> TBreakPoints;
|
||||
typedef std::vector<std::string> TBreakPointsStr;
|
||||
|
||||
const TBreakPoints& GetBreakPoints() { return m_BreakPoints; }
|
||||
TBreakPointsStr GetStrings() const;
|
||||
void AddFromStrings(const TBreakPointsStr& bps);
|
||||
|
||||
// is address breakpoint
|
||||
bool IsAddressBreakPoint(u32 address) const;
|
||||
bool IsTempBreakPoint(u32 address) const;
|
||||
|
||||
// Add BreakPoint
|
||||
void Add(u32 em_address, bool temp = false);
|
||||
void Add(const TBreakPoint& bp);
|
||||
|
||||
// Remove Breakpoint
|
||||
void Remove(u32 _iAddress);
|
||||
void Clear();
|
||||
void ClearAllTemporary();
|
||||
|
||||
private:
|
||||
TBreakPoints m_BreakPoints;
|
||||
};
|
||||
|
||||
// Memory breakpoints
|
||||
class MemChecks
|
||||
{
|
||||
public:
|
||||
typedef std::vector<TMemCheck> TMemChecks;
|
||||
typedef std::vector<std::string> TMemChecksStr;
|
||||
|
||||
TMemChecks m_MemChecks;
|
||||
|
||||
const TMemChecks& GetMemChecks() { return m_MemChecks; }
|
||||
TMemChecksStr GetStrings() const;
|
||||
void AddFromStrings(const TMemChecksStr& mcs);
|
||||
|
||||
void Add(const TMemCheck& _rMemoryCheck);
|
||||
|
||||
// memory breakpoint
|
||||
TMemCheck* GetMemCheck(u32 address);
|
||||
void Remove(u32 _Address);
|
||||
|
||||
void Clear() { m_MemChecks.clear(); }
|
||||
bool HasAny() const { return !m_MemChecks.empty(); }
|
||||
};
|
||||
|
||||
class Watches
|
||||
{
|
||||
public:
|
||||
typedef std::vector<TWatch> TWatches;
|
||||
typedef std::vector<std::string> TWatchesStr;
|
||||
|
||||
const TWatches& GetWatches() { return m_Watches; }
|
||||
TWatchesStr GetStrings() const;
|
||||
void AddFromStrings(const TWatchesStr& bps);
|
||||
|
||||
bool IsAddressWatch(u32 _iAddress) const;
|
||||
|
||||
// Add BreakPoint
|
||||
void Add(u32 em_address);
|
||||
void Add(const TWatch& bp);
|
||||
|
||||
void Update(int count, u32 em_address);
|
||||
void UpdateName(int count, const std::string name);
|
||||
|
||||
// Remove Breakpoint
|
||||
void Remove(u32 _iAddress);
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
TWatches m_Watches;
|
||||
};
|
@ -8,10 +8,10 @@
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
|
||||
#include "Common/BreakPoints.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "Core/Debugger/PPCDebugInterface.h"
|
||||
#include "Core/PowerPC/BreakPoints.h"
|
||||
#include "Core/PowerPC/Gekko.h"
|
||||
#include "Core/PowerPC/PPCCache.h"
|
||||
|
||||
|
Reference in New Issue
Block a user