mirror of https://github.com/PCSX2/pcsx2.git
parent
170d1cb94c
commit
7dbf01b024
|
@ -22,14 +22,24 @@
|
|||
#include "../System.h"
|
||||
|
||||
std::vector<BreakPoint> CBreakPoints::breakPoints_;
|
||||
u32 CBreakPoints::breakSkipFirstAt_ = 0;
|
||||
u64 CBreakPoints::breakSkipFirstTicks_ = 0;
|
||||
u32 CBreakPoints::breakSkipFirstAtEE_ = 0;
|
||||
u64 CBreakPoints::breakSkipFirstTicksEE_ = 0;
|
||||
u32 CBreakPoints::breakSkipFirstAtIop_ = 0;
|
||||
u64 CBreakPoints::breakSkipFirstTicksIop_ = 0;
|
||||
std::vector<MemCheck> CBreakPoints::memChecks_;
|
||||
std::vector<MemCheck *> CBreakPoints::cleanupMemChecks_;
|
||||
bool CBreakPoints::breakpointTriggered_ = false;
|
||||
|
||||
// called from the dynarec
|
||||
u32 __fastcall standardizeBreakpointAddress(u32 addr)
|
||||
u32 __fastcall standardizeBreakpointAddress(BreakPointCpu cpu, u32 addr)
|
||||
{
|
||||
if (cpu == BREAKPOINT_IOP)
|
||||
return standardizeBreakpointAddressIop(addr);
|
||||
else
|
||||
return standardizeBreakpointAddressEE(addr);
|
||||
}
|
||||
|
||||
u32 __fastcall standardizeBreakpointAddressEE(u32 addr)
|
||||
{
|
||||
if (addr >= 0xFFFF8000)
|
||||
return addr;
|
||||
|
@ -38,14 +48,19 @@ u32 __fastcall standardizeBreakpointAddress(u32 addr)
|
|||
addr &= 0x1FFFFFFF;
|
||||
|
||||
addr &= 0x7FFFFFFF;
|
||||
|
||||
|
||||
if ((addr >> 28) == 2 || (addr >> 28) == 3)
|
||||
addr &= ~(0xF << 28);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
u32 __fastcall standardizeBreakpointAddressIop(u32 addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
MemCheck::MemCheck() :
|
||||
cpu(BREAKPOINT_EE),
|
||||
start(0),
|
||||
end(0),
|
||||
cond(MEMCHECK_READWRITE),
|
||||
|
@ -120,104 +135,105 @@ void MemCheck::JitCleanup()
|
|||
host->SetDebugMode(true);*/
|
||||
}
|
||||
|
||||
size_t CBreakPoints::FindBreakpoint(u32 addr, bool matchTemp, bool temp)
|
||||
size_t CBreakPoints::FindBreakpoint(BreakPointCpu cpu, u32 addr, bool matchTemp, bool temp)
|
||||
{
|
||||
addr = standardizeBreakpointAddress(addr);
|
||||
addr = standardizeBreakpointAddress(cpu, addr);
|
||||
|
||||
for (size_t i = 0; i < breakPoints_.size(); ++i)
|
||||
{
|
||||
u32 cmp = standardizeBreakpointAddress(breakPoints_[i].addr);
|
||||
if (cmp == addr && (!matchTemp || breakPoints_[i].temporary == temp))
|
||||
u32 cmp = standardizeBreakpointAddress(cpu, breakPoints_[i].addr);
|
||||
if (cpu == breakPoints_[i].cpu && cmp == addr && (!matchTemp || breakPoints_[i].temporary == temp))
|
||||
return i;
|
||||
}
|
||||
|
||||
return INVALID_BREAKPOINT;
|
||||
}
|
||||
|
||||
size_t CBreakPoints::FindMemCheck(u32 start, u32 end)
|
||||
size_t CBreakPoints::FindMemCheck(BreakPointCpu cpu, u32 start, u32 end)
|
||||
{
|
||||
start = standardizeBreakpointAddress(start);
|
||||
end = standardizeBreakpointAddress(end);
|
||||
start = standardizeBreakpointAddress(cpu, start);
|
||||
end = standardizeBreakpointAddress(cpu, end);
|
||||
|
||||
for (size_t i = 0; i < memChecks_.size(); ++i)
|
||||
{
|
||||
u32 cmpStart = standardizeBreakpointAddress(memChecks_[i].start);
|
||||
u32 cmpEnd = standardizeBreakpointAddress(memChecks_[i].end);
|
||||
if (cmpStart == start && cmpEnd == end)
|
||||
u32 cmpStart = standardizeBreakpointAddress(cpu, memChecks_[i].start);
|
||||
u32 cmpEnd = standardizeBreakpointAddress(cpu, memChecks_[i].end);
|
||||
if (memChecks_[i].cpu == cpu && cmpStart == start && cmpEnd == end)
|
||||
return i;
|
||||
}
|
||||
|
||||
return INVALID_MEMCHECK;
|
||||
}
|
||||
|
||||
bool CBreakPoints::IsAddressBreakPoint(u32 addr)
|
||||
bool CBreakPoints::IsAddressBreakPoint(BreakPointCpu cpu, u32 addr)
|
||||
{
|
||||
size_t bp = FindBreakpoint(addr);
|
||||
size_t bp = FindBreakpoint(cpu, addr);
|
||||
if (bp != INVALID_BREAKPOINT && breakPoints_[bp].enabled)
|
||||
return true;
|
||||
// Check again for overlapping temp breakpoint
|
||||
bp = FindBreakpoint(addr, true, true);
|
||||
bp = FindBreakpoint(cpu, addr, true, true);
|
||||
return bp != INVALID_BREAKPOINT && breakPoints_[bp].enabled;
|
||||
}
|
||||
|
||||
bool CBreakPoints::IsAddressBreakPoint(u32 addr, bool* enabled)
|
||||
bool CBreakPoints::IsAddressBreakPoint(BreakPointCpu cpu, u32 addr, bool* enabled)
|
||||
{
|
||||
size_t bp = FindBreakpoint(addr);
|
||||
size_t bp = FindBreakpoint(cpu, addr);
|
||||
if (bp == INVALID_BREAKPOINT) return false;
|
||||
if (enabled != NULL) *enabled = breakPoints_[bp].enabled;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBreakPoints::IsTempBreakPoint(u32 addr)
|
||||
bool CBreakPoints::IsTempBreakPoint(BreakPointCpu cpu, u32 addr)
|
||||
{
|
||||
size_t bp = FindBreakpoint(addr, true, true);
|
||||
size_t bp = FindBreakpoint(cpu, addr, true, true);
|
||||
return bp != INVALID_BREAKPOINT;
|
||||
}
|
||||
|
||||
void CBreakPoints::AddBreakPoint(u32 addr, bool temp)
|
||||
void CBreakPoints::AddBreakPoint(BreakPointCpu cpu, u32 addr, bool temp)
|
||||
{
|
||||
size_t bp = FindBreakpoint(addr, true, temp);
|
||||
size_t bp = FindBreakpoint(cpu, addr, true, temp);
|
||||
if (bp == INVALID_BREAKPOINT)
|
||||
{
|
||||
BreakPoint pt;
|
||||
pt.enabled = true;
|
||||
pt.temporary = temp;
|
||||
pt.addr = addr;
|
||||
pt.cpu = cpu;
|
||||
|
||||
breakPoints_.push_back(pt);
|
||||
Update(addr);
|
||||
Update(cpu, addr);
|
||||
}
|
||||
else if (!breakPoints_[bp].enabled)
|
||||
{
|
||||
breakPoints_[bp].enabled = true;
|
||||
breakPoints_[bp].hasCond = false;
|
||||
Update(addr);
|
||||
Update(cpu, addr);
|
||||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::RemoveBreakPoint(u32 addr)
|
||||
void CBreakPoints::RemoveBreakPoint(BreakPointCpu cpu, u32 addr)
|
||||
{
|
||||
size_t bp = FindBreakpoint(addr);
|
||||
size_t bp = FindBreakpoint(cpu, addr);
|
||||
if (bp != INVALID_BREAKPOINT)
|
||||
{
|
||||
breakPoints_.erase(breakPoints_.begin() + bp);
|
||||
|
||||
// Check again, there might've been an overlapping temp breakpoint.
|
||||
bp = FindBreakpoint(addr);
|
||||
bp = FindBreakpoint(cpu, addr);
|
||||
if (bp != INVALID_BREAKPOINT)
|
||||
breakPoints_.erase(breakPoints_.begin() + bp);
|
||||
|
||||
Update(addr);
|
||||
Update(cpu, addr);
|
||||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::ChangeBreakPoint(u32 addr, bool status)
|
||||
void CBreakPoints::ChangeBreakPoint(BreakPointCpu cpu, u32 addr, bool status)
|
||||
{
|
||||
size_t bp = FindBreakpoint(addr);
|
||||
size_t bp = FindBreakpoint(cpu, addr);
|
||||
if (bp != INVALID_BREAKPOINT)
|
||||
{
|
||||
breakPoints_[bp].enabled = status;
|
||||
Update(addr);
|
||||
Update(cpu, addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,15 +255,15 @@ void CBreakPoints::ClearTemporaryBreakPoints()
|
|||
{
|
||||
if (breakPoints_[i].temporary)
|
||||
{
|
||||
Update(breakPoints_[i].addr);
|
||||
Update(breakPoints_[i].cpu, breakPoints_[i].addr);
|
||||
breakPoints_.erase(breakPoints_.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::ChangeBreakPointAddCond(u32 addr, const BreakPointCond &cond)
|
||||
void CBreakPoints::ChangeBreakPointAddCond(BreakPointCpu cpu, u32 addr, const BreakPointCond &cond)
|
||||
{
|
||||
size_t bp = FindBreakpoint(addr, true, false);
|
||||
size_t bp = FindBreakpoint(cpu, addr, true, false);
|
||||
if (bp != INVALID_BREAKPOINT)
|
||||
{
|
||||
breakPoints_[bp].hasCond = true;
|
||||
|
@ -256,9 +272,9 @@ void CBreakPoints::ChangeBreakPointAddCond(u32 addr, const BreakPointCond &cond)
|
|||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::ChangeBreakPointRemoveCond(u32 addr)
|
||||
void CBreakPoints::ChangeBreakPointRemoveCond(BreakPointCpu cpu, u32 addr)
|
||||
{
|
||||
size_t bp = FindBreakpoint(addr, true, false);
|
||||
size_t bp = FindBreakpoint(cpu, addr, true, false);
|
||||
if (bp != INVALID_BREAKPOINT)
|
||||
{
|
||||
breakPoints_[bp].hasCond = false;
|
||||
|
@ -266,25 +282,25 @@ void CBreakPoints::ChangeBreakPointRemoveCond(u32 addr)
|
|||
}
|
||||
}
|
||||
|
||||
BreakPointCond *CBreakPoints::GetBreakPointCondition(u32 addr)
|
||||
BreakPointCond *CBreakPoints::GetBreakPointCondition(BreakPointCpu cpu, u32 addr)
|
||||
{
|
||||
size_t bp = FindBreakpoint(addr, true, true);
|
||||
size_t bp = FindBreakpoint(cpu, addr, true, true);
|
||||
//temp breakpoints are unconditional
|
||||
if (bp != INVALID_BREAKPOINT)
|
||||
return NULL;
|
||||
|
||||
bp = FindBreakpoint(addr, true, false);
|
||||
bp = FindBreakpoint(cpu, addr, true, false);
|
||||
if (bp != INVALID_BREAKPOINT && breakPoints_[bp].hasCond)
|
||||
return &breakPoints_[bp].cond;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CBreakPoints::AddMemCheck(u32 start, u32 end, MemCheckCondition cond, MemCheckResult result)
|
||||
void CBreakPoints::AddMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result)
|
||||
{
|
||||
// This will ruin any pending memchecks.
|
||||
cleanupMemChecks_.clear();
|
||||
|
||||
size_t mc = FindMemCheck(start, end);
|
||||
size_t mc = FindMemCheck(cpu, start, end);
|
||||
if (mc == INVALID_MEMCHECK)
|
||||
{
|
||||
MemCheck check;
|
||||
|
@ -292,39 +308,40 @@ void CBreakPoints::AddMemCheck(u32 start, u32 end, MemCheckCondition cond, MemCh
|
|||
check.end = end;
|
||||
check.cond = cond;
|
||||
check.result = result;
|
||||
check.cpu = cpu;
|
||||
|
||||
memChecks_.push_back(check);
|
||||
Update();
|
||||
Update(cpu);
|
||||
}
|
||||
else
|
||||
{
|
||||
memChecks_[mc].cond = (MemCheckCondition)(memChecks_[mc].cond | cond);
|
||||
memChecks_[mc].result = (MemCheckResult)(memChecks_[mc].result | result);
|
||||
Update();
|
||||
Update(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::RemoveMemCheck(u32 start, u32 end)
|
||||
void CBreakPoints::RemoveMemCheck(BreakPointCpu cpu, u32 start, u32 end)
|
||||
{
|
||||
// This will ruin any pending memchecks.
|
||||
cleanupMemChecks_.clear();
|
||||
|
||||
size_t mc = FindMemCheck(start, end);
|
||||
size_t mc = FindMemCheck(cpu, start, end);
|
||||
if (mc != INVALID_MEMCHECK)
|
||||
{
|
||||
memChecks_.erase(memChecks_.begin() + mc);
|
||||
Update();
|
||||
Update(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::ChangeMemCheck(u32 start, u32 end, MemCheckCondition cond, MemCheckResult result)
|
||||
void CBreakPoints::ChangeMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result)
|
||||
{
|
||||
size_t mc = FindMemCheck(start, end);
|
||||
size_t mc = FindMemCheck(cpu, start, end);
|
||||
if (mc != INVALID_MEMCHECK)
|
||||
{
|
||||
memChecks_[mc].cond = cond;
|
||||
memChecks_[mc].result = result;
|
||||
Update();
|
||||
Update(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,18 +357,27 @@ void CBreakPoints::ClearAllMemChecks()
|
|||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::SetSkipFirst(u32 pc)
|
||||
void CBreakPoints::SetSkipFirst(BreakPointCpu cpu, u32 pc)
|
||||
{
|
||||
breakSkipFirstAt_ = standardizeBreakpointAddress(pc);
|
||||
breakSkipFirstTicks_ = r5900Debug.getCycles();
|
||||
if (cpu == BREAKPOINT_EE)
|
||||
{
|
||||
breakSkipFirstAtEE_ = standardizeBreakpointAddress(cpu, pc);
|
||||
breakSkipFirstTicksEE_ = r5900Debug.getCycles();
|
||||
}
|
||||
else if (cpu == BREAKPOINT_IOP)
|
||||
{
|
||||
breakSkipFirstAtIop_ = standardizeBreakpointAddress(cpu, pc);
|
||||
breakSkipFirstTicksIop_ = r3000Debug.getCycles();
|
||||
}
|
||||
}
|
||||
|
||||
u32 CBreakPoints::CheckSkipFirst(u32 cmpPc)
|
||||
u32 CBreakPoints::CheckSkipFirst(BreakPointCpu cpu, u32 cmpPc)
|
||||
{
|
||||
cmpPc = standardizeBreakpointAddress(cmpPc);
|
||||
u32 pc = breakSkipFirstAt_;
|
||||
if (breakSkipFirstTicks_ == r5900Debug.getCycles())
|
||||
return pc;
|
||||
cmpPc = standardizeBreakpointAddress(cpu, cmpPc);
|
||||
if (cpu == BREAKPOINT_EE && breakSkipFirstTicksEE_ == r5900Debug.getCycles())
|
||||
return breakSkipFirstAtEE_;
|
||||
else if (cpu == BREAKPOINT_IOP && breakSkipFirstTicksIop_ == r3000Debug.getCycles())
|
||||
return breakSkipFirstAtIop_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -385,7 +411,7 @@ const std::vector<BreakPoint> CBreakPoints::GetBreakpoints()
|
|||
#include "App.h"
|
||||
#include "Debugger/DisassemblyDialog.h"
|
||||
|
||||
void CBreakPoints::Update(u32 addr)
|
||||
void CBreakPoints::Update(BreakPointCpu cpu, u32 addr)
|
||||
{
|
||||
bool resume = false;
|
||||
if (!r5900Debug.isCpuPaused())
|
||||
|
|
|
@ -52,6 +52,7 @@ struct BreakPoint
|
|||
|
||||
bool hasCond;
|
||||
BreakPointCond cond;
|
||||
BreakPointCpu cpu;
|
||||
|
||||
bool operator == (const BreakPoint &other) const {
|
||||
return addr == other.addr;
|
||||
|
@ -87,6 +88,7 @@ struct MemCheck
|
|||
|
||||
MemCheckCondition cond;
|
||||
MemCheckResult result;
|
||||
BreakPointCpu cpu;
|
||||
|
||||
u32 numHits;
|
||||
|
||||
|
@ -114,27 +116,27 @@ public:
|
|||
static const size_t INVALID_BREAKPOINT = -1;
|
||||
static const size_t INVALID_MEMCHECK = -1;
|
||||
|
||||
static bool IsAddressBreakPoint(u32 addr);
|
||||
static bool IsAddressBreakPoint(u32 addr, bool* enabled);
|
||||
static bool IsTempBreakPoint(u32 addr);
|
||||
static void AddBreakPoint(u32 addr, bool temp = false);
|
||||
static void RemoveBreakPoint(u32 addr);
|
||||
static void ChangeBreakPoint(u32 addr, bool enable);
|
||||
static bool IsAddressBreakPoint(BreakPointCpu cpu, u32 addr);
|
||||
static bool IsAddressBreakPoint(BreakPointCpu cpu, u32 addr, bool* enabled);
|
||||
static bool IsTempBreakPoint(BreakPointCpu cpu, u32 addr);
|
||||
static void AddBreakPoint(BreakPointCpu cpu, u32 addr, bool temp = false);
|
||||
static void RemoveBreakPoint(BreakPointCpu cpu, u32 addr);
|
||||
static void ChangeBreakPoint(BreakPointCpu cpu, u32 addr, bool enable);
|
||||
static void ClearAllBreakPoints();
|
||||
static void ClearTemporaryBreakPoints();
|
||||
|
||||
// Makes a copy. Temporary breakpoints can't have conditions.
|
||||
static void ChangeBreakPointAddCond(u32 addr, const BreakPointCond &cond);
|
||||
static void ChangeBreakPointRemoveCond(u32 addr);
|
||||
static BreakPointCond *GetBreakPointCondition(u32 addr);
|
||||
static void ChangeBreakPointAddCond(BreakPointCpu cpu, u32 addr, const BreakPointCond &cond);
|
||||
static void ChangeBreakPointRemoveCond(BreakPointCpu cpu, u32 addr);
|
||||
static BreakPointCond *GetBreakPointCondition(BreakPointCpu cpu, u32 addr);
|
||||
|
||||
static void AddMemCheck(u32 start, u32 end, MemCheckCondition cond, MemCheckResult result);
|
||||
static void RemoveMemCheck(u32 start, u32 end);
|
||||
static void ChangeMemCheck(u32 start, u32 end, MemCheckCondition cond, MemCheckResult result);
|
||||
static void AddMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result);
|
||||
static void RemoveMemCheck(BreakPointCpu cpu, u32 start, u32 end);
|
||||
static void ChangeMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result);
|
||||
static void ClearAllMemChecks();
|
||||
|
||||
static void SetSkipFirst(u32 pc);
|
||||
static u32 CheckSkipFirst(u32 pc);
|
||||
static void SetSkipFirst(BreakPointCpu cpu, u32 pc);
|
||||
static u32 CheckSkipFirst(BreakPointCpu cpu, u32 pc);
|
||||
|
||||
// Includes uncached addresses.
|
||||
static const std::vector<MemCheck> GetMemCheckRanges();
|
||||
|
@ -143,19 +145,22 @@ public:
|
|||
static const std::vector<BreakPoint> GetBreakpoints();
|
||||
static size_t GetNumMemchecks() { return memChecks_.size(); }
|
||||
|
||||
static void Update(u32 addr = 0);
|
||||
static void Update(BreakPointCpu cpu = BREAKPOINT_IOP_AND_EE, u32 addr = 0);
|
||||
|
||||
static void SetBreakpointTriggered(bool b) { breakpointTriggered_ = b; };
|
||||
static bool GetBreakpointTriggered() { return breakpointTriggered_; };
|
||||
|
||||
private:
|
||||
static size_t FindBreakpoint(u32 addr, bool matchTemp = false, bool temp = false);
|
||||
static size_t FindBreakpoint(BreakPointCpu cpu, u32 addr, bool matchTemp = false, bool temp = false);
|
||||
// Finds exactly, not using a range check.
|
||||
static size_t FindMemCheck(u32 start, u32 end);
|
||||
static size_t FindMemCheck(BreakPointCpu cpu, u32 start, u32 end);
|
||||
|
||||
static std::vector<BreakPoint> breakPoints_;
|
||||
static u32 breakSkipFirstAt_;
|
||||
static u64 breakSkipFirstTicks_;
|
||||
static u32 breakSkipFirstAtEE_;
|
||||
static u64 breakSkipFirstTicksEE_;
|
||||
static u32 breakSkipFirstAtIop_;
|
||||
static u64 breakSkipFirstTicksIop_;
|
||||
|
||||
static bool breakpointTriggered_;
|
||||
|
||||
static std::vector<MemCheck> memChecks_;
|
||||
|
@ -164,4 +169,6 @@ private:
|
|||
|
||||
|
||||
// called from the dynarec
|
||||
u32 __fastcall standardizeBreakpointAddress(u32 addr);
|
||||
u32 __fastcall standardizeBreakpointAddress(BreakPointCpu cpu, u32 addr);
|
||||
u32 __fastcall standardizeBreakpointAddressEE(u32 addr);
|
||||
u32 __fastcall standardizeBreakpointAddressIop(u32 addr);
|
||||
|
|
|
@ -232,6 +232,11 @@ bool DebugInterface::parseExpression(PostfixExpression& exp, u64& dest)
|
|||
// R5900DebugInterface
|
||||
//
|
||||
|
||||
BreakPointCpu R5900DebugInterface::getCpuType()
|
||||
{
|
||||
return BREAKPOINT_EE;
|
||||
}
|
||||
|
||||
u32 R5900DebugInterface::read8(u32 address)
|
||||
{
|
||||
if (!isValidAddress(address))
|
||||
|
@ -628,6 +633,11 @@ u32 R5900DebugInterface::getCycles()
|
|||
//
|
||||
|
||||
|
||||
BreakPointCpu R3000DebugInterface::getCpuType()
|
||||
{
|
||||
return BREAKPOINT_IOP;
|
||||
}
|
||||
|
||||
u32 R3000DebugInterface::read8(u32 address)
|
||||
{
|
||||
if (!isValidAddress(address))
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
|
||||
enum { EECAT_GPR, EECAT_CP0, EECAT_FPR, EECAT_FCR, EECAT_VU0F, EECAT_VU0I, EECAT_COUNT };
|
||||
enum { IOPCAT_GPR, IOPCAT_COUNT };
|
||||
enum BreakPointCpu
|
||||
{
|
||||
BREAKPOINT_EE = 0x01,
|
||||
BREAKPOINT_IOP = 0x02,
|
||||
BREAKPOINT_IOP_AND_EE = 0x03
|
||||
};
|
||||
|
||||
class DebugInterface
|
||||
{
|
||||
|
@ -51,6 +57,7 @@ public:
|
|||
virtual std::string disasm(u32 address, bool simplify) = 0;
|
||||
virtual bool isValidAddress(u32 address) = 0;
|
||||
virtual u32 getCycles() = 0;
|
||||
virtual BreakPointCpu getCpuType() = 0;
|
||||
|
||||
bool initExpression(const char* exp, PostfixExpression& dest);
|
||||
bool parseExpression(PostfixExpression& exp, u64& dest);
|
||||
|
@ -90,6 +97,7 @@ public:
|
|||
virtual std::string disasm(u32 address, bool simplify);
|
||||
virtual bool isValidAddress(u32 address);
|
||||
virtual u32 getCycles();
|
||||
virtual BreakPointCpu getCpuType();
|
||||
};
|
||||
|
||||
|
||||
|
@ -122,6 +130,7 @@ public:
|
|||
virtual std::string disasm(u32 address, bool simplify);
|
||||
virtual bool isValidAddress(u32 address);
|
||||
virtual u32 getCycles();
|
||||
virtual BreakPointCpu getCpuType();
|
||||
};
|
||||
|
||||
extern R5900DebugInterface r5900Debug;
|
||||
|
|
|
@ -49,12 +49,12 @@ static void debugI()
|
|||
void intBreakpoint(bool memcheck)
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_EE, pc) != 0)
|
||||
return;
|
||||
|
||||
if (!memcheck)
|
||||
{
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(pc);
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(BREAKPOINT_EE, pc);
|
||||
if (cond && !cond->Evaluate())
|
||||
return;
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ void intMemcheck(u32 op, u32 bits, bool store)
|
|||
if (bits == 128)
|
||||
start &= ~0x0F;
|
||||
|
||||
start = standardizeBreakpointAddress(start);
|
||||
start = standardizeBreakpointAddress(BREAKPOINT_EE, start);
|
||||
u32 end = start + bits/8;
|
||||
|
||||
auto checks = CBreakPoints::GetMemChecks();
|
||||
|
@ -81,6 +81,8 @@ void intMemcheck(u32 op, u32 bits, bool store)
|
|||
{
|
||||
auto& check = checks[i];
|
||||
|
||||
if (check.cpu != BREAKPOINT_EE)
|
||||
continue;
|
||||
if (check.result == 0)
|
||||
continue;
|
||||
if ((check.cond & MEMCHECK_WRITE) == 0 && store)
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "Sio.h"
|
||||
#include "Sif.h"
|
||||
#include "../DebugTools/Breakpoints.h"
|
||||
#include "R5900OpcodeTables.h"
|
||||
|
||||
using namespace R3000A;
|
||||
|
||||
|
@ -41,6 +43,8 @@ s32 iopBreak = 0;
|
|||
// control is returned to the EE.
|
||||
s32 iopCycleEE = -1;
|
||||
|
||||
bool iopBreakpoint = 0;
|
||||
|
||||
// Used to signal to the EE when important actions that need IOP-attention have
|
||||
// happened (hsyncs, vsyncs, IOP exceptions, etc). IOP runs code whenever this
|
||||
// is true, even if it's already running ahead a bit.
|
||||
|
@ -247,3 +251,45 @@ void iopTestIntc()
|
|||
psxSetNextBranchDelta( 2 );
|
||||
}
|
||||
|
||||
inline bool psxIsBranchOrJump(u32 addr)
|
||||
{
|
||||
u32 op = iopMemRead32(addr);
|
||||
const R5900::OPCODE& opcode = R5900::GetInstruction(op);
|
||||
|
||||
return (opcode.flags & IS_BRANCH) != 0;
|
||||
}
|
||||
|
||||
// The next two functions return 0 if no breakpoint is needed,
|
||||
// 1 if it's needed on the current pc, 2 if it's needed in the delay slot
|
||||
// 3 if needed in both
|
||||
|
||||
int psxIsBreakpointNeeded(u32 addr)
|
||||
{
|
||||
int bpFlags = 0;
|
||||
if (CBreakPoints::IsAddressBreakPoint(BREAKPOINT_IOP, addr))
|
||||
bpFlags += 1;
|
||||
|
||||
// there may be a breakpoint in the delay slot
|
||||
if (psxIsBranchOrJump(addr) && CBreakPoints::IsAddressBreakPoint(BREAKPOINT_IOP, addr + 4))
|
||||
bpFlags += 2;
|
||||
|
||||
return bpFlags;
|
||||
}
|
||||
|
||||
int psxIsMemcheckNeeded(u32 pc)
|
||||
{
|
||||
if (CBreakPoints::GetNumMemchecks() == 0)
|
||||
return 0;
|
||||
|
||||
u32 addr = pc;
|
||||
if (psxIsBranchOrJump(addr))
|
||||
addr += 4;
|
||||
|
||||
u32 op = iopMemRead32(addr);
|
||||
const R5900::OPCODE& opcode = R5900::GetInstruction(op);
|
||||
|
||||
if (opcode.flags & IS_MEMORY)
|
||||
return addr == pc ? 1 : 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ extern __aligned16 psxRegisters psxRegs;
|
|||
extern u32 g_iopNextEventCycle;
|
||||
extern s32 iopBreak; // used when the IOP execution is broken and control returned to the EE
|
||||
extern s32 iopCycleEE; // tracks IOP's current sych status with the EE
|
||||
extern bool iopBreakpoint;
|
||||
|
||||
#ifndef _PC_
|
||||
|
||||
|
@ -203,6 +204,9 @@ extern void __fastcall psxException(u32 code, u32 step);
|
|||
extern void iopEventTest();
|
||||
extern void psxMemReset();
|
||||
|
||||
int psxIsBreakpointNeeded(u32 addr);
|
||||
int psxIsMemcheckNeeded(u32 pc);
|
||||
|
||||
// Subsets
|
||||
extern void (*psxBSC[64])();
|
||||
extern void (*psxSPC[64])();
|
||||
|
|
|
@ -771,11 +771,11 @@ inline bool isBranchOrJump(u32 addr)
|
|||
int isBreakpointNeeded(u32 addr)
|
||||
{
|
||||
int bpFlags = 0;
|
||||
if (CBreakPoints::IsAddressBreakPoint(addr))
|
||||
if (CBreakPoints::IsAddressBreakPoint(BREAKPOINT_EE, addr))
|
||||
bpFlags += 1;
|
||||
|
||||
// there may be a breakpoint in the delay slot
|
||||
if (isBranchOrJump(addr) && CBreakPoints::IsAddressBreakPoint(addr+4))
|
||||
if (isBranchOrJump(addr) && CBreakPoints::IsAddressBreakPoint(BREAKPOINT_EE, addr+4))
|
||||
bpFlags += 2;
|
||||
|
||||
return bpFlags;
|
||||
|
|
|
@ -1147,7 +1147,8 @@ protected:
|
|||
|
||||
CoreThread.ResetQuick();
|
||||
symbolMap.Clear();
|
||||
CBreakPoints::SetSkipFirst(0);
|
||||
CBreakPoints::SetSkipFirst(BREAKPOINT_EE, 0);
|
||||
CBreakPoints::SetSkipFirst(BREAKPOINT_IOP, 0);
|
||||
|
||||
CDVDsys_SetFile(CDVD_SourceType::Iso, g_Conf->CurrentIso );
|
||||
if( m_UseCDVDsrc )
|
||||
|
|
|
@ -325,10 +325,10 @@ void BreakpointWindow::addBreakpoint()
|
|||
else if (enabled) result = MEMCHECK_BREAK;
|
||||
else result = MEMCHECK_IGNORE;
|
||||
|
||||
CBreakPoints::AddMemCheck(address, address + size, (MemCheckCondition)cond, result);
|
||||
CBreakPoints::AddMemCheck(cpu->getCpuType(), address, address + size, (MemCheckCondition)cond, result);
|
||||
} else {
|
||||
// add breakpoint
|
||||
CBreakPoints::AddBreakPoint(address,false);
|
||||
CBreakPoints::AddBreakPoint(cpu->getCpuType(), address,false);
|
||||
|
||||
if (condition[0] != 0)
|
||||
{
|
||||
|
@ -336,12 +336,12 @@ void BreakpointWindow::addBreakpoint()
|
|||
cond.debug = cpu;
|
||||
strcpy(cond.expressionString,condition);
|
||||
cond.expression = compiledCondition;
|
||||
CBreakPoints::ChangeBreakPointAddCond(address,cond);
|
||||
CBreakPoints::ChangeBreakPointAddCond(cpu->getCpuType(), address,cond);
|
||||
}
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
CBreakPoints::ChangeBreakPoint(address,false);
|
||||
CBreakPoints::ChangeBreakPoint(cpu->getCpuType(), address,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -525,7 +525,7 @@ void CtrlDisassemblyView::render(wxDC& dc)
|
|||
|
||||
// display address/symbol
|
||||
bool enabled;
|
||||
if (CBreakPoints::IsAddressBreakPoint(address,&enabled))
|
||||
if (CBreakPoints::IsAddressBreakPoint(cpu->getCpuType(),address,&enabled))
|
||||
{
|
||||
if (enabled)
|
||||
textColor = 0x0000FF;
|
||||
|
@ -933,26 +933,26 @@ void CtrlDisassemblyView::scrollbarEvent(wxScrollWinEvent& evt)
|
|||
void CtrlDisassemblyView::toggleBreakpoint(bool toggleEnabled)
|
||||
{
|
||||
bool enabled;
|
||||
if (CBreakPoints::IsAddressBreakPoint(curAddress,&enabled))
|
||||
if (CBreakPoints::IsAddressBreakPoint(cpu->getCpuType(), curAddress,&enabled))
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
// enable disabled breakpoints
|
||||
CBreakPoints::ChangeBreakPoint(curAddress,true);
|
||||
} else if (!toggleEnabled && CBreakPoints::GetBreakPointCondition(curAddress) != NULL)
|
||||
CBreakPoints::ChangeBreakPoint(cpu->getCpuType(), curAddress,true);
|
||||
} else if (!toggleEnabled && CBreakPoints::GetBreakPointCondition(cpu->getCpuType(), curAddress) != NULL)
|
||||
{
|
||||
// don't just delete a breakpoint with a custom condition
|
||||
CBreakPoints::RemoveBreakPoint(curAddress);
|
||||
CBreakPoints::RemoveBreakPoint(cpu->getCpuType(), curAddress);
|
||||
} else if (toggleEnabled)
|
||||
{
|
||||
// disable breakpoint
|
||||
CBreakPoints::ChangeBreakPoint(curAddress,false);
|
||||
CBreakPoints::ChangeBreakPoint(cpu->getCpuType(), curAddress,false);
|
||||
} else {
|
||||
// otherwise just remove breakpoint
|
||||
CBreakPoints::RemoveBreakPoint(curAddress);
|
||||
CBreakPoints::RemoveBreakPoint(cpu->getCpuType(), curAddress);
|
||||
}
|
||||
} else {
|
||||
CBreakPoints::AddBreakPoint(curAddress);
|
||||
CBreakPoints::AddBreakPoint(cpu->getCpuType(), curAddress);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1266,7 +1266,7 @@ void CtrlDisassemblyView::editBreakpoint()
|
|||
BreakpointWindow win(this,cpu);
|
||||
|
||||
bool exists = false;
|
||||
if (CBreakPoints::IsAddressBreakPoint(curAddress))
|
||||
if (CBreakPoints::IsAddressBreakPoint(cpu->getCpuType(), curAddress))
|
||||
{
|
||||
auto breakpoints = CBreakPoints::GetBreakpoints();
|
||||
for (size_t i = 0; i < breakpoints.size(); i++)
|
||||
|
@ -1286,7 +1286,7 @@ void CtrlDisassemblyView::editBreakpoint()
|
|||
if (win.ShowModal() == wxID_OK)
|
||||
{
|
||||
if (exists)
|
||||
CBreakPoints::RemoveBreakPoint(curAddress);
|
||||
CBreakPoints::RemoveBreakPoint(cpu->getCpuType(), curAddress);
|
||||
win.addBreakpoint();
|
||||
postEvent(debEVT_UPDATE,0);
|
||||
}
|
||||
|
|
|
@ -189,10 +189,14 @@ BreakpointList::BreakpointList(wxWindow* parent, DebugInterface* _cpu, CtrlDisas
|
|||
|
||||
int BreakpointList::getRowCount()
|
||||
{
|
||||
int count = (int)CBreakPoints::GetMemChecks().size();
|
||||
int count = 0;
|
||||
for (size_t i = 0; i < CBreakPoints::GetMemChecks().size(); i++)
|
||||
{
|
||||
if (displayedMemChecks_[i].cpu == cpu->getCpuType()) count++;
|
||||
}
|
||||
for (size_t i = 0; i < CBreakPoints::GetBreakpoints().size(); i++)
|
||||
{
|
||||
if (!displayedBreakPoints_[i].temporary) count++;
|
||||
if (!displayedBreakPoints_[i].temporary && displayedBreakPoints_[i].cpu == cpu->getCpuType()) count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
|
@ -327,18 +331,21 @@ void BreakpointList::onKeyDown(int key)
|
|||
int BreakpointList::getBreakpointIndex(int itemIndex, bool& isMemory) const
|
||||
{
|
||||
// memory breakpoints first
|
||||
if (itemIndex < (int)displayedMemChecks_.size())
|
||||
for (size_t i = 0; i < displayedMemChecks_.size(); i++)
|
||||
{
|
||||
isMemory = true;
|
||||
return itemIndex;
|
||||
if (displayedMemChecks_[i].cpu != cpu->getCpuType()) continue;
|
||||
if (itemIndex == 0)
|
||||
{
|
||||
isMemory = true;
|
||||
return (int)i;
|
||||
}
|
||||
itemIndex--;
|
||||
}
|
||||
|
||||
itemIndex -= (int)displayedMemChecks_.size();
|
||||
|
||||
size_t i = 0;
|
||||
while (i < displayedBreakPoints_.size())
|
||||
{
|
||||
if (displayedBreakPoints_[i].temporary)
|
||||
if (displayedBreakPoints_[i].temporary || displayedBreakPoints_[i].cpu != cpu->getCpuType())
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
|
@ -379,7 +386,7 @@ void BreakpointList::editBreakpoint(int itemIndex)
|
|||
win.loadFromMemcheck(mem);
|
||||
if (win.ShowModal() == wxID_OK)
|
||||
{
|
||||
CBreakPoints::RemoveMemCheck(mem.start,mem.end);
|
||||
CBreakPoints::RemoveMemCheck(cpu->getCpuType(), mem.start,mem.end);
|
||||
win.addBreakpoint();
|
||||
}
|
||||
} else {
|
||||
|
@ -387,7 +394,7 @@ void BreakpointList::editBreakpoint(int itemIndex)
|
|||
win.loadFromBreakpoint(bp);
|
||||
if (win.ShowModal() == wxID_OK)
|
||||
{
|
||||
CBreakPoints::RemoveBreakPoint(bp.addr);
|
||||
CBreakPoints::RemoveBreakPoint(cpu->getCpuType(), bp.addr);
|
||||
win.addBreakpoint();
|
||||
}
|
||||
}
|
||||
|
@ -401,10 +408,10 @@ void BreakpointList::toggleEnabled(int itemIndex)
|
|||
|
||||
if (isMemory) {
|
||||
MemCheck mcPrev = displayedMemChecks_[index];
|
||||
CBreakPoints::ChangeMemCheck(mcPrev.start, mcPrev.end, mcPrev.cond, MemCheckResult(mcPrev.result ^ MEMCHECK_BREAK));
|
||||
CBreakPoints::ChangeMemCheck(cpu->getCpuType(), mcPrev.start, mcPrev.end, mcPrev.cond, MemCheckResult(mcPrev.result ^ MEMCHECK_BREAK));
|
||||
} else {
|
||||
BreakPoint bpPrev = displayedBreakPoints_[index];
|
||||
CBreakPoints::ChangeBreakPoint(bpPrev.addr, !bpPrev.enabled);
|
||||
CBreakPoints::ChangeBreakPoint(cpu->getCpuType(), bpPrev.addr, !bpPrev.enabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,10 +440,10 @@ void BreakpointList::removeBreakpoint(int itemIndex)
|
|||
if (isMemory)
|
||||
{
|
||||
auto mc = displayedMemChecks_[index];
|
||||
CBreakPoints::RemoveMemCheck(mc.start, mc.end);
|
||||
CBreakPoints::RemoveMemCheck(cpu->getCpuType(), mc.start, mc.end);
|
||||
} else {
|
||||
u32 address = displayedBreakPoints_[index].addr;
|
||||
CBreakPoints::RemoveBreakPoint(address);
|
||||
CBreakPoints::RemoveBreakPoint(displayedBreakPoints_[index].cpu, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -309,7 +309,8 @@ void DisassemblyDialog::onBreakRunClicked(wxCommandEvent& evt)
|
|||
if (r5900Debug.isCpuPaused())
|
||||
{
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||
CBreakPoints::SetSkipFirst(BREAKPOINT_EE, r5900Debug.getPC());
|
||||
CBreakPoints::SetSkipFirst(BREAKPOINT_IOP, r3000Debug.getPC());
|
||||
r5900Debug.resumeCpu();
|
||||
} else {
|
||||
r5900Debug.pauseCpu();
|
||||
|
@ -361,19 +362,15 @@ void DisassemblyDialog::stepOver()
|
|||
{
|
||||
if (!r5900Debug.isAlive() || !r5900Debug.isCpuPaused() || currentCpu == NULL)
|
||||
return;
|
||||
|
||||
|
||||
// todo: breakpoints for iop
|
||||
if (currentCpu != eeTab)
|
||||
return;
|
||||
DebugInterface *debug = currentCpu->getCpu();
|
||||
|
||||
CtrlDisassemblyView* disassembly = currentCpu->getDisassembly();
|
||||
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||
u32 currentPc = r5900Debug.getPC();
|
||||
CBreakPoints::SetSkipFirst(debug->getCpuType(), debug->getPC());
|
||||
u32 currentPc = debug->getPC();
|
||||
|
||||
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(&r5900Debug,r5900Debug.getPC());
|
||||
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debug,debug->getPC());
|
||||
u32 breakpointAddress = currentPc+disassembly->getInstructionSizeAt(currentPc);
|
||||
if (info.isBranch)
|
||||
{
|
||||
|
@ -400,7 +397,7 @@ void DisassemblyDialog::stepOver()
|
|||
disassembly->scrollStepping(breakpointAddress);
|
||||
}
|
||||
|
||||
CBreakPoints::AddBreakPoint(breakpointAddress,true);
|
||||
CBreakPoints::AddBreakPoint(debug->getCpuType(), breakpointAddress,true);
|
||||
r5900Debug.resumeCpu();
|
||||
}
|
||||
|
||||
|
@ -410,17 +407,14 @@ void DisassemblyDialog::stepInto()
|
|||
if (!r5900Debug.isAlive() || !r5900Debug.isCpuPaused() || currentCpu == NULL)
|
||||
return;
|
||||
|
||||
// todo: breakpoints for iop
|
||||
if (currentCpu != eeTab)
|
||||
return;
|
||||
|
||||
DebugInterface *debug = currentCpu->getCpu();
|
||||
CtrlDisassemblyView* disassembly = currentCpu->getDisassembly();
|
||||
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||
u32 currentPc = r5900Debug.getPC();
|
||||
CBreakPoints::SetSkipFirst(debug->getCpuType(), debug->getPC());
|
||||
u32 currentPc = debug->getPC();
|
||||
|
||||
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(&r5900Debug,r5900Debug.getPC());
|
||||
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(debug,debug->getPC());
|
||||
u32 breakpointAddress = currentPc+disassembly->getInstructionSizeAt(currentPc);
|
||||
if (info.isBranch)
|
||||
{
|
||||
|
@ -441,7 +435,7 @@ void DisassemblyDialog::stepInto()
|
|||
if (info.isSyscall)
|
||||
breakpointAddress = info.branchTarget;
|
||||
|
||||
CBreakPoints::AddBreakPoint(breakpointAddress,true);
|
||||
CBreakPoints::AddBreakPoint(debug->getCpuType(), breakpointAddress,true);
|
||||
r5900Debug.resumeCpu();
|
||||
}
|
||||
|
||||
|
@ -449,14 +443,15 @@ void DisassemblyDialog::stepOut()
|
|||
{
|
||||
if (!r5900Debug.isAlive() || !r5900Debug.isCpuPaused() || currentCpu == NULL)
|
||||
return;
|
||||
DebugInterface *debug = currentCpu->getCpu();
|
||||
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||
CBreakPoints::SetSkipFirst(debug->getCpuType(), debug->getPC());
|
||||
|
||||
u32 addr = currentCpu->getStepOutAddress();
|
||||
if (addr == (u32)-1)
|
||||
return;
|
||||
|
||||
CBreakPoints::AddBreakPoint(addr,true);
|
||||
CBreakPoints::AddBreakPoint(debug->getCpuType(), addr,true);
|
||||
r5900Debug.resumeCpu();
|
||||
}
|
||||
|
||||
|
@ -505,10 +500,7 @@ void DisassemblyDialog::onDebuggerEvent(wxCommandEvent& evt)
|
|||
}
|
||||
} else if (type == debEVT_RUNTOPOS)
|
||||
{
|
||||
// todo: breakpoints for iop
|
||||
if (currentCpu != eeTab)
|
||||
return;
|
||||
CBreakPoints::AddBreakPoint(evt.GetInt(),true);
|
||||
CBreakPoints::AddBreakPoint(currentCpu->getCpu()->getCpuType(), evt.GetInt(),true);
|
||||
currentCpu->getCpu()->resumeCpu();
|
||||
} else if (type == debEVT_GOTOINDISASM)
|
||||
{
|
||||
|
@ -633,7 +625,8 @@ void DisassemblyDialog::setDebugMode(bool debugMode, bool switchPC)
|
|||
if (currentCpu != NULL)
|
||||
currentCpu->getDisassembly()->SetFocus();
|
||||
CBreakPoints::SetBreakpointTriggered(false);
|
||||
CBreakPoints::SetSkipFirst(0);
|
||||
CBreakPoints::SetSkipFirst(BREAKPOINT_EE, 0);
|
||||
CBreakPoints::SetSkipFirst(BREAKPOINT_IOP, 0);
|
||||
}
|
||||
|
||||
if (currentCpu != NULL)
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "iR3000A.h"
|
||||
#include "BaseblockEx.h"
|
||||
#include "System/RecTypes.h"
|
||||
#include "System/SysThreads.h"
|
||||
#include "R5900OpcodeTables.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
@ -36,6 +38,7 @@
|
|||
#include "AppConfig.h"
|
||||
|
||||
#include "Utilities/Perf.h"
|
||||
#include "../DebugTools/Breakpoints.h"
|
||||
|
||||
using namespace x86Emitter;
|
||||
|
||||
|
@ -434,6 +437,11 @@ void _psxFlushCall(int flushtype)
|
|||
_freeX86reg( ecx );
|
||||
_freeX86reg( edx );
|
||||
|
||||
if ((flushtype & FLUSH_PC)/*&& !g_cpuFlushedPC*/) {
|
||||
xMOV(ptr32[&psxRegs.pc], psxpc);
|
||||
//g_cpuFlushedPC = true;
|
||||
}
|
||||
|
||||
if( flushtype & FLUSH_CACHED_REGS )
|
||||
_psxFlushConstRegs();
|
||||
}
|
||||
|
@ -1030,11 +1038,167 @@ void rpsxBREAK()
|
|||
//if (!psxbranch) psxbranch = 2;
|
||||
}
|
||||
|
||||
void psxDynarecCheckBreakpoint()
|
||||
{
|
||||
u32 pc = psxRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_IOP, pc) == pc)
|
||||
return;
|
||||
|
||||
int bpFlags = psxIsBreakpointNeeded(pc);
|
||||
bool hit = false;
|
||||
//check breakpoint at current pc
|
||||
if (bpFlags & 1) {
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(BREAKPOINT_IOP, pc);
|
||||
if (cond == NULL || cond->Evaluate()) {
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
//check breakpoint in delay slot
|
||||
if (bpFlags & 2) {
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(BREAKPOINT_IOP, pc + 4);
|
||||
if (cond == NULL || cond->Evaluate())
|
||||
hit = true;
|
||||
}
|
||||
|
||||
if (!hit)
|
||||
return;
|
||||
|
||||
CBreakPoints::SetBreakpointTriggered(true);
|
||||
GetCoreThread().PauseSelfDebug();
|
||||
iopBreakpoint = true;
|
||||
}
|
||||
|
||||
void psxDynarecMemcheck()
|
||||
{
|
||||
u32 pc = psxRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_IOP, pc) == pc)
|
||||
return;
|
||||
|
||||
CBreakPoints::SetBreakpointTriggered(true);
|
||||
GetCoreThread().PauseSelfDebug();
|
||||
iopBreakpoint = true;
|
||||
}
|
||||
|
||||
void __fastcall psxDynarecMemLogcheck(u32 start, bool store)
|
||||
{
|
||||
if (store)
|
||||
DevCon.WriteLn("Hit store breakpoint @0x%x", start);
|
||||
else
|
||||
DevCon.WriteLn("Hit load breakpoint @0x%x", start);
|
||||
}
|
||||
|
||||
void psxRecMemcheck(u32 op, u32 bits, bool store)
|
||||
{
|
||||
_psxFlushCall(FLUSH_EVERYTHING | FLUSH_PC);
|
||||
|
||||
// compute accessed address
|
||||
_psxMoveGPRtoR(ecx, (op >> 21) & 0x1F);
|
||||
if ((s16)op != 0)
|
||||
xADD(ecx, (s16)op);
|
||||
if (bits == 128)
|
||||
xAND(ecx, ~0x0F);
|
||||
|
||||
xFastCall((void*)standardizeBreakpointAddressIop, ecx);
|
||||
xMOV(ecx, eax);
|
||||
xMOV(edx, eax);
|
||||
xADD(edx, bits / 8);
|
||||
|
||||
// ecx = access address
|
||||
// edx = access address+size
|
||||
|
||||
auto checks = CBreakPoints::GetMemChecks();
|
||||
for (size_t i = 0; i < checks.size(); i++)
|
||||
{
|
||||
if (checks[i].cpu != BREAKPOINT_IOP)
|
||||
continue;
|
||||
if (checks[i].result == 0)
|
||||
continue;
|
||||
if ((checks[i].cond & MEMCHECK_WRITE) == 0 && store)
|
||||
continue;
|
||||
if ((checks[i].cond & MEMCHECK_READ) == 0 && !store)
|
||||
continue;
|
||||
|
||||
// logic: memAddress < bpEnd && bpStart < memAddress+memSize
|
||||
|
||||
xMOV(eax, standardizeBreakpointAddress(BREAKPOINT_IOP, checks[i].end));
|
||||
xCMP(ecx, eax); // address < end
|
||||
xForwardJGE8 next1; // if address >= end then goto next1
|
||||
|
||||
xMOV(eax, standardizeBreakpointAddress(BREAKPOINT_IOP, checks[i].start));
|
||||
xCMP(eax, edx); // start < address+size
|
||||
xForwardJGE8 next2; // if start >= address+size then goto next2
|
||||
|
||||
// hit the breakpoint
|
||||
if (checks[i].result & MEMCHECK_LOG) {
|
||||
xMOV(edx, store);
|
||||
xFastCall((void*)psxDynarecMemLogcheck, ecx, edx);
|
||||
}
|
||||
if (checks[i].result & MEMCHECK_BREAK) {
|
||||
xFastCall((void*)psxDynarecMemcheck);
|
||||
}
|
||||
|
||||
next1.SetTarget();
|
||||
next2.SetTarget();
|
||||
}
|
||||
// get out of here
|
||||
xCMP(ptr8[&iopBreakpoint], 0);
|
||||
xJNE(iopExitRecompiledCode);
|
||||
}
|
||||
|
||||
void psxEncodeBreakpoint()
|
||||
{
|
||||
if (psxIsBreakpointNeeded(psxpc) != 0)
|
||||
{
|
||||
_psxFlushCall(FLUSH_EVERYTHING | FLUSH_PC);
|
||||
xFastCall((void*)psxDynarecCheckBreakpoint);
|
||||
// get out of here
|
||||
xCMP(ptr8[&iopBreakpoint], 0);
|
||||
xJNE(iopExitRecompiledCode);
|
||||
}
|
||||
}
|
||||
|
||||
void psxEncodeMemcheck()
|
||||
{
|
||||
int needed = psxIsMemcheckNeeded(psxpc);
|
||||
if (needed == 0)
|
||||
return;
|
||||
|
||||
u32 op = iopMemRead32(needed == 2 ? psxpc + 4 : psxpc);
|
||||
const R5900::OPCODE& opcode = R5900::GetInstruction(op);
|
||||
|
||||
bool store = (opcode.flags & IS_STORE) != 0;
|
||||
switch (opcode.flags & MEMTYPE_MASK)
|
||||
{
|
||||
case MEMTYPE_BYTE:
|
||||
psxRecMemcheck(op, 8, store);
|
||||
break;
|
||||
case MEMTYPE_HALF:
|
||||
psxRecMemcheck(op, 16, store);
|
||||
break;
|
||||
case MEMTYPE_WORD:
|
||||
psxRecMemcheck(op, 32, store);
|
||||
break;
|
||||
case MEMTYPE_DWORD:
|
||||
psxRecMemcheck(op, 64, store);
|
||||
break;
|
||||
case MEMTYPE_QWORD:
|
||||
psxRecMemcheck(op, 128, store);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void psxRecompileNextInstruction(int delayslot)
|
||||
{
|
||||
// pblock isn't used elsewhere in this function.
|
||||
//BASEBLOCK* pblock = PSX_GETBLOCK(psxpc);
|
||||
|
||||
// add breakpoint
|
||||
if (!delayslot)
|
||||
{
|
||||
psxEncodeBreakpoint();
|
||||
psxEncodeMemcheck();
|
||||
}
|
||||
|
||||
if( IsDebugBuild ) {
|
||||
xNOP();
|
||||
xMOV(eax, psxpc);
|
||||
|
|
|
@ -113,6 +113,7 @@ static u32 dumplog = 0;
|
|||
static void iBranchTest(u32 newpc = 0xffffffff);
|
||||
static void ClearRecLUT(BASEBLOCK* base, int count);
|
||||
static u32 scaleblockcycles();
|
||||
static void recExitExecution();
|
||||
|
||||
void _eeFlushAllUnused()
|
||||
{
|
||||
|
@ -336,6 +337,11 @@ static DynGenFunc* DispatchPageReset = NULL;
|
|||
static void recEventTest()
|
||||
{
|
||||
_cpuEventTest_Shared();
|
||||
|
||||
if (iopBreakpoint) {
|
||||
iopBreakpoint = false;
|
||||
recExitExecution();
|
||||
}
|
||||
}
|
||||
|
||||
// The address for all cleared blocks. It recompiles the current pc and then
|
||||
|
@ -1167,21 +1173,21 @@ int cop2flags(u32 code)
|
|||
void dynarecCheckBreakpoint()
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_EE, pc) != 0)
|
||||
return;
|
||||
|
||||
int bpFlags = isBreakpointNeeded(pc);
|
||||
bool hit = false;
|
||||
//check breakpoint at current pc
|
||||
if (bpFlags & 1) {
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(pc);
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(BREAKPOINT_EE, pc);
|
||||
if (cond == NULL || cond->Evaluate()) {
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
//check breakpoint in delay slot
|
||||
if (bpFlags & 2) {
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(pc + 4);
|
||||
auto cond = CBreakPoints::GetBreakPointCondition(BREAKPOINT_EE, pc + 4);
|
||||
if (cond == NULL || cond->Evaluate())
|
||||
hit = true;
|
||||
}
|
||||
|
@ -1197,7 +1203,7 @@ void dynarecCheckBreakpoint()
|
|||
void dynarecMemcheck()
|
||||
{
|
||||
u32 pc = cpuRegs.pc;
|
||||
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||
if (CBreakPoints::CheckSkipFirst(BREAKPOINT_EE, pc) != 0)
|
||||
return;
|
||||
|
||||
CBreakPoints::SetBreakpointTriggered(true);
|
||||
|
@ -1224,7 +1230,7 @@ void recMemcheck(u32 op, u32 bits, bool store)
|
|||
if (bits == 128)
|
||||
xAND(ecx, ~0x0F);
|
||||
|
||||
xFastCall((void*)standardizeBreakpointAddress, ecx);
|
||||
xFastCall((void*)standardizeBreakpointAddressEE, ecx);
|
||||
xMOV(ecx,eax);
|
||||
xMOV(edx,eax);
|
||||
xADD(edx,bits/8);
|
||||
|
@ -1235,6 +1241,8 @@ void recMemcheck(u32 op, u32 bits, bool store)
|
|||
auto checks = CBreakPoints::GetMemChecks();
|
||||
for (size_t i = 0; i < checks.size(); i++)
|
||||
{
|
||||
if (checks[i].cpu != BREAKPOINT_EE)
|
||||
continue;
|
||||
if (checks[i].result == 0)
|
||||
continue;
|
||||
if ((checks[i].cond & MEMCHECK_WRITE) == 0 && store)
|
||||
|
@ -1244,11 +1252,11 @@ void recMemcheck(u32 op, u32 bits, bool store)
|
|||
|
||||
// logic: memAddress < bpEnd && bpStart < memAddress+memSize
|
||||
|
||||
xMOV(eax,standardizeBreakpointAddress(checks[i].end));
|
||||
xMOV(eax,standardizeBreakpointAddress(BREAKPOINT_EE, checks[i].end));
|
||||
xCMP(ecx,eax); // address < end
|
||||
xForwardJGE8 next1; // if address >= end then goto next1
|
||||
|
||||
xMOV(eax,standardizeBreakpointAddress(checks[i].start));
|
||||
xMOV(eax,standardizeBreakpointAddress(BREAKPOINT_EE, checks[i].start));
|
||||
xCMP(eax,edx); // start < address+size
|
||||
xForwardJGE8 next2; // if start >= address+size then goto next2
|
||||
|
||||
|
|
Loading…
Reference in New Issue