mirror of https://github.com/PCSX2/pcsx2.git
Merge pull request #5 from Kingcom/master
More debugger enhancements and fixes
This commit is contained in:
commit
2fbac107ca
|
@ -0,0 +1,40 @@
|
||||||
|
disassembly view:
|
||||||
|
|
||||||
|
ctrg+g goto
|
||||||
|
ctrl+e edit breakpoint
|
||||||
|
ctrl+d enable/disable breakpoint
|
||||||
|
ctrl+b add breakpoint
|
||||||
|
right follow branch/position memory view to accessed address
|
||||||
|
left go back one branch level/goto pc
|
||||||
|
up move cursor up one line
|
||||||
|
down move cursor down one line
|
||||||
|
page up move visible area up one page
|
||||||
|
page down move visible area down one page
|
||||||
|
f10 step over
|
||||||
|
f11 step into
|
||||||
|
tab toggle display symbols
|
||||||
|
left click select line/toggle breakpoint if line is already highlighted
|
||||||
|
right click open context menu
|
||||||
|
|
||||||
|
memory view:
|
||||||
|
|
||||||
|
ctrg+g goto
|
||||||
|
ctrl+b add breakpoint
|
||||||
|
left move cursor back one byte/nibble
|
||||||
|
right move cursor ahead one byte/nibble
|
||||||
|
up move cursor up one line
|
||||||
|
down move cursor down one line
|
||||||
|
page up move cursor up one page
|
||||||
|
page down move cursor down one page
|
||||||
|
0-9,A-F overwrite hex nibble
|
||||||
|
any overwrite ansi byte
|
||||||
|
left click select byte/nibble
|
||||||
|
right click open context menu
|
||||||
|
|
||||||
|
breakpoint list:
|
||||||
|
|
||||||
|
up select previous item
|
||||||
|
down select next item
|
||||||
|
delete remove selected breakpoint
|
||||||
|
return edit selected breakpoint
|
||||||
|
space toggle enable state of selected breakpoint
|
|
@ -33,6 +33,9 @@
|
||||||
#include "CDVDisoReader.h"
|
#include "CDVDisoReader.h"
|
||||||
#include "Utilities/ScopedPtr.h"
|
#include "Utilities/ScopedPtr.h"
|
||||||
|
|
||||||
|
#include "DebugTools/SymbolMap.h"
|
||||||
|
#include "AppConfig.h"
|
||||||
|
|
||||||
const wxChar* CDVD_SourceLabels[] =
|
const wxChar* CDVD_SourceLabels[] =
|
||||||
{
|
{
|
||||||
L"Iso",
|
L"Iso",
|
||||||
|
@ -287,6 +290,21 @@ static CDVD_SourceType m_CurrentSourceType = CDVDsrc_NoDisc;
|
||||||
void CDVDsys_SetFile( CDVD_SourceType srctype, const wxString& newfile )
|
void CDVDsys_SetFile( CDVD_SourceType srctype, const wxString& newfile )
|
||||||
{
|
{
|
||||||
m_SourceFilename[srctype] = newfile;
|
m_SourceFilename[srctype] = newfile;
|
||||||
|
|
||||||
|
// look for symbol file
|
||||||
|
if (g_Conf->EmuOptions.Debugger.EnableDebugger && symbolMap.IsEmpty())
|
||||||
|
{
|
||||||
|
wxString symName;
|
||||||
|
int n = newfile.Last('.');
|
||||||
|
if (n == wxNOT_FOUND)
|
||||||
|
symName = newfile + L".sym";
|
||||||
|
else
|
||||||
|
symName = newfile.substr(0,n) + L".sym";
|
||||||
|
|
||||||
|
wxCharBuffer buf = symName.ToUTF8();
|
||||||
|
symbolMap.LoadNocashSym(buf);
|
||||||
|
symbolMap.UpdateActiveSymbols();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const wxString& CDVDsys_GetFile( CDVD_SourceType srctype )
|
const wxString& CDVDsys_GetFile( CDVD_SourceType srctype )
|
||||||
|
|
|
@ -326,6 +326,7 @@ set(pcsx2GuiSources
|
||||||
gui/Debugger/CtrlDisassemblyView.cpp
|
gui/Debugger/CtrlDisassemblyView.cpp
|
||||||
gui/Debugger/CtrlRegisterList.cpp
|
gui/Debugger/CtrlRegisterList.cpp
|
||||||
gui/Debugger/CtrlMemView.cpp
|
gui/Debugger/CtrlMemView.cpp
|
||||||
|
gui/Debugger/DebuggerLists.cpp
|
||||||
gui/Debugger/DisassemblyDialog.cpp
|
gui/Debugger/DisassemblyDialog.cpp
|
||||||
gui/Debugger/DebugEvents.cpp
|
gui/Debugger/DebugEvents.cpp
|
||||||
gui/ExecutorThread.cpp
|
gui/ExecutorThread.cpp
|
||||||
|
@ -381,6 +382,7 @@ set(pcsx2GuiHeaders
|
||||||
gui/Debugger/CtrlDisassemblyView.h
|
gui/Debugger/CtrlDisassemblyView.h
|
||||||
gui/Debugger/CtrlRegisterList.h
|
gui/Debugger/CtrlRegisterList.h
|
||||||
gui/Debugger/CtrlMemView.h
|
gui/Debugger/CtrlMemView.h
|
||||||
|
gui/Debugger/DebuggerLists.h
|
||||||
gui/Debugger/DisassemblyDialog.h
|
gui/Debugger/DisassemblyDialog.h
|
||||||
gui/Debugger/DebugEvents.h
|
gui/Debugger/DebugEvents.h
|
||||||
gui/i18n.h
|
gui/i18n.h
|
||||||
|
|
|
@ -404,6 +404,31 @@ struct Pcsx2Config
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DebugOptions
|
||||||
|
{
|
||||||
|
BITFIELD32()
|
||||||
|
bool
|
||||||
|
EnableDebugger :1,
|
||||||
|
ShowDebuggerOnStart :1;
|
||||||
|
BITFIELD_END
|
||||||
|
|
||||||
|
u8 FontWidth;
|
||||||
|
u8 FontHeight;
|
||||||
|
|
||||||
|
DebugOptions();
|
||||||
|
void LoadSave( IniInterface& conf );
|
||||||
|
|
||||||
|
bool operator ==( const DebugOptions& right ) const
|
||||||
|
{
|
||||||
|
return OpEqu( bitset ) && OpEqu( FontWidth ) && OpEqu( FontHeight );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator !=( const DebugOptions& right ) const
|
||||||
|
{
|
||||||
|
return !this->operator ==( right );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
BITFIELD32()
|
BITFIELD32()
|
||||||
bool
|
bool
|
||||||
CdvdVerboseReads :1, // enables cdvd read activity verbosely dumped to the console
|
CdvdVerboseReads :1, // enables cdvd read activity verbosely dumped to the console
|
||||||
|
@ -429,6 +454,7 @@ struct Pcsx2Config
|
||||||
SpeedhackOptions Speedhacks;
|
SpeedhackOptions Speedhacks;
|
||||||
GamefixOptions Gamefixes;
|
GamefixOptions Gamefixes;
|
||||||
ProfilerOptions Profiler;
|
ProfilerOptions Profiler;
|
||||||
|
DebugOptions Debugger;
|
||||||
|
|
||||||
TraceLogFilters Trace;
|
TraceLogFilters Trace;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,9 @@ u32 CBreakPoints::breakSkipFirstAt_ = 0;
|
||||||
u64 CBreakPoints::breakSkipFirstTicks_ = 0;
|
u64 CBreakPoints::breakSkipFirstTicks_ = 0;
|
||||||
std::vector<MemCheck> CBreakPoints::memChecks_;
|
std::vector<MemCheck> CBreakPoints::memChecks_;
|
||||||
std::vector<MemCheck *> CBreakPoints::cleanupMemChecks_;
|
std::vector<MemCheck *> CBreakPoints::cleanupMemChecks_;
|
||||||
|
bool CBreakPoints::breakpointTriggered_ = false;
|
||||||
|
|
||||||
|
int addressMask = 0x1FFFFFFF;
|
||||||
|
|
||||||
MemCheck::MemCheck()
|
MemCheck::MemCheck()
|
||||||
{
|
{
|
||||||
|
@ -82,9 +85,11 @@ void MemCheck::JitCleanup()
|
||||||
|
|
||||||
size_t CBreakPoints::FindBreakpoint(u32 addr, bool matchTemp, bool temp)
|
size_t CBreakPoints::FindBreakpoint(u32 addr, bool matchTemp, bool temp)
|
||||||
{
|
{
|
||||||
|
addr &= addressMask;
|
||||||
|
|
||||||
for (size_t i = 0; i < breakPoints_.size(); ++i)
|
for (size_t i = 0; i < breakPoints_.size(); ++i)
|
||||||
{
|
{
|
||||||
if (breakPoints_[i].addr == addr && (!matchTemp || breakPoints_[i].temporary == temp))
|
if ((breakPoints_[i].addr & addressMask) == addr && (!matchTemp || breakPoints_[i].temporary == temp))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,9 +98,11 @@ size_t CBreakPoints::FindBreakpoint(u32 addr, bool matchTemp, bool temp)
|
||||||
|
|
||||||
size_t CBreakPoints::FindMemCheck(u32 start, u32 end)
|
size_t CBreakPoints::FindMemCheck(u32 start, u32 end)
|
||||||
{
|
{
|
||||||
|
start &= addressMask;
|
||||||
|
end &= addressMask;
|
||||||
for (size_t i = 0; i < memChecks_.size(); ++i)
|
for (size_t i = 0; i < memChecks_.size(); ++i)
|
||||||
{
|
{
|
||||||
if (memChecks_[i].start == start && memChecks_[i].end == end)
|
if ((memChecks_[i].start & addressMask) == start && (memChecks_[i].end & addressMask) == end)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +298,8 @@ static inline u32 NotCached(u32 val)
|
||||||
|
|
||||||
MemCheck *CBreakPoints::GetMemCheck(u32 address, int size)
|
MemCheck *CBreakPoints::GetMemCheck(u32 address, int size)
|
||||||
{
|
{
|
||||||
|
address &= addressMask;
|
||||||
|
|
||||||
std::vector<MemCheck>::iterator iter;
|
std::vector<MemCheck>::iterator iter;
|
||||||
for (iter = memChecks_.begin(); iter != memChecks_.end(); ++iter)
|
for (iter = memChecks_.begin(); iter != memChecks_.end(); ++iter)
|
||||||
{
|
{
|
||||||
|
@ -338,14 +347,16 @@ void CBreakPoints::ExecMemCheckJitCleanup()
|
||||||
|
|
||||||
void CBreakPoints::SetSkipFirst(u32 pc)
|
void CBreakPoints::SetSkipFirst(u32 pc)
|
||||||
{
|
{
|
||||||
breakSkipFirstAt_ = pc;
|
breakSkipFirstAt_ = pc & addressMask;
|
||||||
// breakSkipFirstTicks_ = CoreTiming::GetTicks();
|
breakSkipFirstTicks_ = r5900Debug.getCycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CBreakPoints::CheckSkipFirst(u32 cmpPc)
|
u32 CBreakPoints::CheckSkipFirst(u32 cmpPc)
|
||||||
{
|
{
|
||||||
|
cmpPc &= addressMask;
|
||||||
u32 pc = breakSkipFirstAt_;
|
u32 pc = breakSkipFirstAt_;
|
||||||
if (pc == cmpPc)
|
if (breakSkipFirstTicks_ == r5900Debug.getCycles())
|
||||||
return 1;
|
return pc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,6 +386,10 @@ const std::vector<BreakPoint> CBreakPoints::GetBreakpoints()
|
||||||
return breakPoints_;
|
return breakPoints_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// including them earlier causes some ambiguities
|
||||||
|
#include "App.h"
|
||||||
|
#include "Debugger/DisassemblyDialog.h"
|
||||||
|
|
||||||
void CBreakPoints::Update(u32 addr)
|
void CBreakPoints::Update(u32 addr)
|
||||||
{
|
{
|
||||||
bool resume = false;
|
bool resume = false;
|
||||||
|
@ -384,14 +399,13 @@ void CBreakPoints::Update(u32 addr)
|
||||||
resume = true;
|
resume = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr != 0)
|
// if (addr != 0)
|
||||||
Cpu->Clear(addr-4,8);
|
// Cpu->Clear(addr-4,8);
|
||||||
else
|
// else
|
||||||
SysClearExecutionCache();
|
SysClearExecutionCache();
|
||||||
|
|
||||||
if (resume)
|
if (resume)
|
||||||
r5900Debug.resumeCpu();
|
r5900Debug.resumeCpu();
|
||||||
|
|
||||||
// Redraw in order to show the breakpoint.
|
wxGetApp().GetDisassemblyPtr()->update();
|
||||||
// host->UpdateDisassembly();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,6 +150,9 @@ public:
|
||||||
|
|
||||||
static void Update(u32 addr = 0);
|
static void Update(u32 addr = 0);
|
||||||
|
|
||||||
|
static void SetBreakpointTriggered(bool b) { breakpointTriggered_ = b; };
|
||||||
|
static bool GetBreakpointTriggered() { return breakpointTriggered_; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static size_t FindBreakpoint(u32 addr, bool matchTemp = false, bool temp = false);
|
static size_t FindBreakpoint(u32 addr, bool matchTemp = false, bool temp = false);
|
||||||
// Finds exactly, not using a range check.
|
// Finds exactly, not using a range check.
|
||||||
|
@ -158,6 +161,7 @@ private:
|
||||||
static std::vector<BreakPoint> breakPoints_;
|
static std::vector<BreakPoint> breakPoints_;
|
||||||
static u32 breakSkipFirstAt_;
|
static u32 breakSkipFirstAt_;
|
||||||
static u64 breakSkipFirstTicks_;
|
static u64 breakSkipFirstTicks_;
|
||||||
|
static bool breakpointTriggered_;
|
||||||
|
|
||||||
static std::vector<MemCheck> memChecks_;
|
static std::vector<MemCheck> memChecks_;
|
||||||
static std::vector<MemCheck *> cleanupMemChecks_;
|
static std::vector<MemCheck *> cleanupMemChecks_;
|
||||||
|
|
|
@ -418,6 +418,44 @@ void R5900DebugInterface::setPc(u32 newPc)
|
||||||
cpuRegs.pc = newPc;
|
cpuRegs.pc = newPc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void R5900DebugInterface::setRegister(int cat, int num, u128 newValue)
|
||||||
|
{
|
||||||
|
switch (cat)
|
||||||
|
{
|
||||||
|
case EECAT_GPR:
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 32: // pc
|
||||||
|
cpuRegs.pc = newValue._u32[0];
|
||||||
|
break;
|
||||||
|
case 33: // hi
|
||||||
|
cpuRegs.HI.UQ = newValue;
|
||||||
|
break;
|
||||||
|
case 34: // lo
|
||||||
|
cpuRegs.LO.UQ = newValue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
cpuRegs.GPR.r[num].UQ = newValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EECAT_CP0:
|
||||||
|
cpuRegs.CP0.r[num] = newValue._u32[0];
|
||||||
|
break;
|
||||||
|
case EECAT_CP1:
|
||||||
|
fpuRegs.fpr[num].UL = newValue._u32[0];
|
||||||
|
break;
|
||||||
|
case EECAT_CP2F:
|
||||||
|
VU1.VF[num].UQ = newValue;
|
||||||
|
break;
|
||||||
|
case EECAT_CP2I:
|
||||||
|
VU1.VI[num].UL = newValue._u32[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string R5900DebugInterface::disasm(u32 address)
|
std::string R5900DebugInterface::disasm(u32 address)
|
||||||
{
|
{
|
||||||
std::string out;
|
std::string out;
|
||||||
|
@ -429,7 +467,7 @@ std::string R5900DebugInterface::disasm(u32 address)
|
||||||
|
|
||||||
bool R5900DebugInterface::isValidAddress(u32 addr)
|
bool R5900DebugInterface::isValidAddress(u32 addr)
|
||||||
{
|
{
|
||||||
if (addr < 0x100000)
|
if (addr < 0x80000)
|
||||||
return false;
|
return false;
|
||||||
if (addr >= 0x10000000 && addr < 0x10010000)
|
if (addr >= 0x10000000 && addr < 0x10010000)
|
||||||
return true;
|
return true;
|
||||||
|
@ -442,6 +480,11 @@ bool R5900DebugInterface::isValidAddress(u32 addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u32 R5900DebugInterface::getCycles()
|
||||||
|
{
|
||||||
|
return cpuRegs.cycle;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// R3000DebugInterface
|
// R3000DebugInterface
|
||||||
//
|
//
|
||||||
|
@ -617,6 +660,32 @@ void R3000DebugInterface::setPc(u32 newPc)
|
||||||
psxRegs.pc = newPc;
|
psxRegs.pc = newPc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void R3000DebugInterface::setRegister(int cat, int num, u128 newValue)
|
||||||
|
{
|
||||||
|
switch (cat)
|
||||||
|
{
|
||||||
|
case IOPCAT_GPR:
|
||||||
|
switch (num)
|
||||||
|
{
|
||||||
|
case 32: // pc
|
||||||
|
psxRegs.pc = newValue._u32[0];
|
||||||
|
break;
|
||||||
|
case 33: // hi
|
||||||
|
psxRegs.GPR.n.hi = newValue._u32[0];
|
||||||
|
break;
|
||||||
|
case 34: // lo
|
||||||
|
psxRegs.GPR.n.lo = newValue._u32[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
psxRegs.GPR.r[num] = newValue._u32[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string R3000DebugInterface::disasm(u32 address)
|
std::string R3000DebugInterface::disasm(u32 address)
|
||||||
{
|
{
|
||||||
std::string out;
|
std::string out;
|
||||||
|
@ -637,3 +706,8 @@ bool R3000DebugInterface::isValidAddress(u32 addr)
|
||||||
|
|
||||||
return !(addr & 0x40000000) && vtlb_GetPhyPtr(addr & 0x1FFFFFFF) != NULL;
|
return !(addr & 0x40000000) && vtlb_GetPhyPtr(addr & 0x1FFFFFFF) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 R3000DebugInterface::getCycles()
|
||||||
|
{
|
||||||
|
return psxRegs.cycle;
|
||||||
|
}
|
||||||
|
|
|
@ -27,9 +27,11 @@ public:
|
||||||
virtual u128 getLO() = 0;
|
virtual u128 getLO() = 0;
|
||||||
virtual u32 getPC() = 0;
|
virtual u32 getPC() = 0;
|
||||||
virtual void setPc(u32 newPc) = 0;
|
virtual void setPc(u32 newPc) = 0;
|
||||||
|
virtual void setRegister(int cat, int num, u128 newValue) = 0;
|
||||||
|
|
||||||
virtual std::string disasm(u32 address) = 0;
|
virtual std::string disasm(u32 address) = 0;
|
||||||
virtual bool isValidAddress(u32 address) = 0;
|
virtual bool isValidAddress(u32 address) = 0;
|
||||||
|
virtual u32 getCycles() = 0;
|
||||||
|
|
||||||
bool initExpression(const char* exp, PostfixExpression& dest);
|
bool initExpression(const char* exp, PostfixExpression& dest);
|
||||||
bool parseExpression(PostfixExpression& exp, u64& dest);
|
bool parseExpression(PostfixExpression& exp, u64& dest);
|
||||||
|
@ -62,9 +64,11 @@ public:
|
||||||
virtual u128 getLO();
|
virtual u128 getLO();
|
||||||
virtual u32 getPC();
|
virtual u32 getPC();
|
||||||
virtual void setPc(u32 newPc);
|
virtual void setPc(u32 newPc);
|
||||||
|
virtual void setRegister(int cat, int num, u128 newValue);
|
||||||
|
|
||||||
virtual std::string disasm(u32 address);
|
virtual std::string disasm(u32 address);
|
||||||
virtual bool isValidAddress(u32 address);
|
virtual bool isValidAddress(u32 address);
|
||||||
|
virtual u32 getCycles();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,9 +95,11 @@ public:
|
||||||
virtual u128 getLO();
|
virtual u128 getLO();
|
||||||
virtual u32 getPC();
|
virtual u32 getPC();
|
||||||
virtual void setPc(u32 newPc);
|
virtual void setPc(u32 newPc);
|
||||||
|
virtual void setRegister(int cat, int num, u128 newValue);
|
||||||
|
|
||||||
virtual std::string disasm(u32 address);
|
virtual std::string disasm(u32 address);
|
||||||
virtual bool isValidAddress(u32 address);
|
virtual bool isValidAddress(u32 address);
|
||||||
|
virtual u32 getCycles();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern R5900DebugInterface r5900Debug;
|
extern R5900DebugInterface r5900Debug;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "DebugInterface.h"
|
#include "DebugInterface.h"
|
||||||
#include "SymbolMap.h"
|
#include "SymbolMap.h"
|
||||||
#include "DebugInterface.h"
|
#include "DebugInterface.h"
|
||||||
|
#include "../R5900.h"
|
||||||
|
|
||||||
static std::vector<MIPSAnalyst::AnalyzedFunction> functions;
|
static std::vector<MIPSAnalyst::AnalyzedFunction> functions;
|
||||||
|
|
||||||
|
@ -114,6 +115,11 @@ namespace MIPSAnalyst
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if (end) {
|
if (end) {
|
||||||
|
// most functions are aligned to 8 or 16 bytes
|
||||||
|
// add the padding to this one
|
||||||
|
while (r5900Debug.read32(addr+8) == 0)
|
||||||
|
addr += 4;
|
||||||
|
|
||||||
currentFunction.end = addr + 4;
|
currentFunction.end = addr + 4;
|
||||||
currentFunction.isStraightLeaf = isStraightLeaf;
|
currentFunction.isStraightLeaf = isStraightLeaf;
|
||||||
functions.push_back(currentFunction);
|
functions.push_back(currentFunction);
|
||||||
|
@ -122,6 +128,7 @@ namespace MIPSAnalyst
|
||||||
looking = false;
|
looking = false;
|
||||||
end = false;
|
end = false;
|
||||||
isStraightLeaf = true;
|
isStraightLeaf = true;
|
||||||
|
|
||||||
currentFunction.start = addr+4;
|
currentFunction.start = addr+4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,6 +362,10 @@ namespace MIPSAnalyst
|
||||||
switch (MIPS_GET_OP(op)) {
|
switch (MIPS_GET_OP(op)) {
|
||||||
case 0: // special
|
case 0: // special
|
||||||
switch (MIPS_GET_FUNC(op)) {
|
switch (MIPS_GET_FUNC(op)) {
|
||||||
|
case 0x0C: // syscall
|
||||||
|
info.isSyscall = true;
|
||||||
|
info.branchTarget = 0x80000000+0x180;
|
||||||
|
break;
|
||||||
case 0x20: // add
|
case 0x20: // add
|
||||||
case 0x21: // addu
|
case 0x21: // addu
|
||||||
info.hasRelevantAddress = true;
|
info.hasRelevantAddress = true;
|
||||||
|
@ -372,6 +383,27 @@ namespace MIPSAnalyst
|
||||||
info.hasRelevantAddress = true;
|
info.hasRelevantAddress = true;
|
||||||
info.releventAddress = cpu->getRegister(0,MIPS_GET_RS(op))._u32[0]+((s16)(op & 0xFFFF));
|
info.releventAddress = cpu->getRegister(0,MIPS_GET_RS(op))._u32[0]+((s16)(op & 0xFFFF));
|
||||||
break;
|
break;
|
||||||
|
case 0x10: // cop0
|
||||||
|
switch (MIPS_GET_RS(op))
|
||||||
|
{
|
||||||
|
case 0x10: // tlb
|
||||||
|
switch (MIPS_GET_FUNC(op))
|
||||||
|
{
|
||||||
|
case 0x18: // eret
|
||||||
|
info.isBranch = true;
|
||||||
|
info.isConditional = false;
|
||||||
|
|
||||||
|
// probably shouldn't be hard coded like this...
|
||||||
|
if (cpuRegs.CP0.n.Status.b.ERL) {
|
||||||
|
info.branchTarget = cpuRegs.CP0.n.ErrorEPC;
|
||||||
|
} else {
|
||||||
|
info.branchTarget = cpuRegs.CP0.n.EPC;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rest
|
// TODO: rest
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace MIPSAnalyst
|
||||||
|
|
||||||
// branches
|
// branches
|
||||||
u32 branchTarget;
|
u32 branchTarget;
|
||||||
|
bool isSyscall;
|
||||||
bool isBranch;
|
bool isBranch;
|
||||||
bool isLinkedBranch;
|
bool isLinkedBranch;
|
||||||
bool isLikelyBranch;
|
bool isLikelyBranch;
|
||||||
|
|
|
@ -80,7 +80,7 @@ public:
|
||||||
static const u32 INVALID_ADDRESS = (u32)-1;
|
static const u32 INVALID_ADDRESS = (u32)-1;
|
||||||
|
|
||||||
void UpdateActiveSymbols();
|
void UpdateActiveSymbols();
|
||||||
|
bool IsEmpty() const { return activeFunctions.empty() && activeLabels.empty() && activeData.empty(); };
|
||||||
private:
|
private:
|
||||||
void AssignFunctionIndices();
|
void AssignFunctionIndices();
|
||||||
const char *GetLabelName(u32 address) const;
|
const char *GetLabelName(u32 address) const;
|
||||||
|
|
|
@ -63,6 +63,7 @@ namespace PathDefs
|
||||||
extern wxDirName GetLangs();
|
extern wxDirName GetLangs();
|
||||||
extern wxDirName GetCheats();
|
extern wxDirName GetCheats();
|
||||||
extern wxDirName GetCheatsWS();
|
extern wxDirName GetCheatsWS();
|
||||||
|
extern wxDirName GetDocs();
|
||||||
|
|
||||||
extern wxDirName Get( FoldersEnum_t folderidx );
|
extern wxDirName Get( FoldersEnum_t folderidx );
|
||||||
|
|
||||||
|
@ -81,6 +82,7 @@ namespace PathDefs
|
||||||
extern const wxDirName& Langs();
|
extern const wxDirName& Langs();
|
||||||
extern const wxDirName& Cheats();
|
extern const wxDirName& Cheats();
|
||||||
extern const wxDirName& CheatsWS();
|
extern const wxDirName& CheatsWS();
|
||||||
|
extern const wxDirName& Docs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -371,6 +371,28 @@ void Pcsx2Config::GamefixOptions::LoadSave( IniInterface& ini )
|
||||||
IniBitBool( FMVinSoftwareHack );
|
IniBitBool( FMVinSoftwareHack );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Pcsx2Config::DebugOptions::DebugOptions()
|
||||||
|
{
|
||||||
|
EnableDebugger = false;
|
||||||
|
ShowDebuggerOnStart = false;
|
||||||
|
FontWidth = 8;
|
||||||
|
FontHeight = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pcsx2Config::DebugOptions::LoadSave( IniInterface& ini )
|
||||||
|
{
|
||||||
|
ScopedIniGroup path( ini, L"Debugger" );
|
||||||
|
|
||||||
|
IniBitBool( EnableDebugger );
|
||||||
|
IniBitBool( ShowDebuggerOnStart );
|
||||||
|
IniBitfield(FontWidth);
|
||||||
|
IniBitfield(FontHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Pcsx2Config::Pcsx2Config()
|
Pcsx2Config::Pcsx2Config()
|
||||||
{
|
{
|
||||||
bitset = 0;
|
bitset = 0;
|
||||||
|
@ -405,6 +427,7 @@ void Pcsx2Config::LoadSave( IniInterface& ini )
|
||||||
Gamefixes .LoadSave( ini );
|
Gamefixes .LoadSave( ini );
|
||||||
Profiler .LoadSave( ini );
|
Profiler .LoadSave( ini );
|
||||||
|
|
||||||
|
Debugger .LoadSave( ini );
|
||||||
Trace .LoadSave( ini );
|
Trace .LoadSave( ini );
|
||||||
|
|
||||||
ini.Flush();
|
ini.Flush();
|
||||||
|
|
|
@ -230,11 +230,12 @@ void SysCoreThread::GameStartingInThread()
|
||||||
{
|
{
|
||||||
GetMTGS().SendGameCRC(ElfCRC);
|
GetMTGS().SendGameCRC(ElfCRC);
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
if (EmuConfig.Debugger.EnableDebugger)
|
||||||
|
{
|
||||||
MIPSAnalyst::ScanForFunctions(ElfTextRange.first,ElfTextRange.first+ElfTextRange.second,true);
|
MIPSAnalyst::ScanForFunctions(ElfTextRange.first,ElfTextRange.first+ElfTextRange.second,true);
|
||||||
symbolMap.UpdateActiveSymbols();
|
symbolMap.UpdateActiveSymbols();
|
||||||
sApp.PostAppMethod(&Pcsx2App::resetDebugger);
|
sApp.PostAppMethod(&Pcsx2App::resetDebugger);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
if (EmuConfig.EnablePatches) ApplyPatch(0);
|
if (EmuConfig.EnablePatches) ApplyPatch(0);
|
||||||
if (EmuConfig.EnableCheats) ApplyCheat(0);
|
if (EmuConfig.EnableCheats) ApplyCheat(0);
|
||||||
|
|
|
@ -95,6 +95,12 @@ namespace PathDefs
|
||||||
static const wxDirName retval( L"themes" );
|
static const wxDirName retval( L"themes" );
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const wxDirName& Docs()
|
||||||
|
{
|
||||||
|
static const wxDirName retval( L"docs" );
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Specifies the root folder for the application install.
|
// Specifies the root folder for the application install.
|
||||||
|
@ -191,6 +197,11 @@ namespace PathDefs
|
||||||
return GetDocuments() + Base::CheatsWS();
|
return GetDocuments() + Base::CheatsWS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxDirName GetDocs()
|
||||||
|
{
|
||||||
|
return AppRoot() + Base::Docs();
|
||||||
|
}
|
||||||
|
|
||||||
wxDirName GetSavestates()
|
wxDirName GetSavestates()
|
||||||
{
|
{
|
||||||
return GetDocuments() + Base::Savestates();
|
return GetDocuments() + Base::Savestates();
|
||||||
|
|
|
@ -88,9 +88,22 @@ void Pcsx2App::OpenMainFrame()
|
||||||
MainEmuFrame* mainFrame = new MainEmuFrame( NULL, pxGetAppName() );
|
MainEmuFrame* mainFrame = new MainEmuFrame( NULL, pxGetAppName() );
|
||||||
m_id_MainFrame = mainFrame->GetId();
|
m_id_MainFrame = mainFrame->GetId();
|
||||||
|
|
||||||
|
#ifndef PCSX2_DEVBUILD
|
||||||
|
if (g_Conf->EmuOptions.Debugger.EnableDebugger)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
DisassemblyDialog* disassembly = new DisassemblyDialog( mainFrame );
|
DisassemblyDialog* disassembly = new DisassemblyDialog( mainFrame );
|
||||||
m_id_Disassembler = disassembly->GetId();
|
m_id_Disassembler = disassembly->GetId();
|
||||||
|
|
||||||
|
if (g_Conf->EmuOptions.Debugger.ShowDebuggerOnStart)
|
||||||
|
disassembly->Show();
|
||||||
|
}
|
||||||
|
#ifndef PCSX2_DEVBUILD
|
||||||
|
else {
|
||||||
|
m_id_Disassembler = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
PostIdleAppMethod( &Pcsx2App::OpenProgramLog );
|
PostIdleAppMethod( &Pcsx2App::OpenProgramLog );
|
||||||
|
|
||||||
SetTopWindow( mainFrame ); // not really needed...
|
SetTopWindow( mainFrame ); // not really needed...
|
||||||
|
|
|
@ -1043,6 +1043,7 @@ protected:
|
||||||
DbgCon.WriteLn( Color_Gray, "(SysExecute) received." );
|
DbgCon.WriteLn( Color_Gray, "(SysExecute) received." );
|
||||||
|
|
||||||
CoreThread.ResetQuick();
|
CoreThread.ResetQuick();
|
||||||
|
symbolMap.Clear();
|
||||||
|
|
||||||
CDVDsys_SetFile( CDVDsrc_Iso, g_Conf->CurrentIso );
|
CDVDsys_SetFile( CDVDsrc_Iso, g_Conf->CurrentIso );
|
||||||
if( m_UseCDVDsrc )
|
if( m_UseCDVDsrc )
|
||||||
|
|
|
@ -229,10 +229,10 @@ bool BreakpointWindow::fetchDialogData()
|
||||||
onChange = checkOnChange->GetValue();
|
onChange = checkOnChange->GetValue();
|
||||||
|
|
||||||
// parse address
|
// parse address
|
||||||
wxCharBuffer addressText = editAddress->GetLabel().ToUTF8();
|
wxCharBuffer addressText = editAddress->GetValue().ToUTF8();
|
||||||
if (cpu->initExpression(addressText,exp) == false)
|
if (cpu->initExpression(addressText,exp) == false)
|
||||||
{
|
{
|
||||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editAddress->GetLabel().wchar_str().data());
|
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editAddress->GetValue().wchar_str().data());
|
||||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ bool BreakpointWindow::fetchDialogData()
|
||||||
u64 value;
|
u64 value;
|
||||||
if (cpu->parseExpression(exp,value) == false)
|
if (cpu->parseExpression(exp,value) == false)
|
||||||
{
|
{
|
||||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editAddress->GetLabel().wchar_str().data());
|
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editAddress->GetValue().wchar_str().data());
|
||||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -249,17 +249,17 @@ bool BreakpointWindow::fetchDialogData()
|
||||||
if (memory)
|
if (memory)
|
||||||
{
|
{
|
||||||
// parse size
|
// parse size
|
||||||
wxCharBuffer sizeText = editSize->GetLabel().ToUTF8();
|
wxCharBuffer sizeText = editSize->GetValue().ToUTF8();
|
||||||
if (cpu->initExpression(sizeText,exp) == false)
|
if (cpu->initExpression(sizeText,exp) == false)
|
||||||
{
|
{
|
||||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editSize->GetLabel().wchar_str().data());
|
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editSize->GetValue().wchar_str().data());
|
||||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpu->parseExpression(exp,value) == false)
|
if (cpu->parseExpression(exp,value) == false)
|
||||||
{
|
{
|
||||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editSize->GetLabel().wchar_str().data());
|
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editSize->GetValue().wchar_str().data());
|
||||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,7 @@ bool BreakpointWindow::fetchDialogData()
|
||||||
}
|
}
|
||||||
|
|
||||||
// condition
|
// condition
|
||||||
wxCharBuffer conditionText = editCondition->GetLabel().ToUTF8();
|
wxCharBuffer conditionText = editCondition->GetValue().ToUTF8();
|
||||||
strncpy(condition,conditionText,sizeof(condition));
|
strncpy(condition,conditionText,sizeof(condition));
|
||||||
condition[sizeof(condition)-1] = 0;
|
condition[sizeof(condition)-1] = 0;
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ bool BreakpointWindow::fetchDialogData()
|
||||||
{
|
{
|
||||||
if (cpu->initExpression(condition,compiledCondition) == false)
|
if (cpu->initExpression(condition,compiledCondition) == false)
|
||||||
{
|
{
|
||||||
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editCondition->GetLabel().wchar_str().data());
|
swprintf(errorMessage,512,L"Invalid expression \"%s\".",editCondition->GetValue().wchar_str().data());
|
||||||
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
wxMessageBox(errorMessage,L"Error",wxICON_ERROR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "DebugEvents.h"
|
#include "DebugEvents.h"
|
||||||
#include "BreakpointWindow.h"
|
#include "BreakpointWindow.h"
|
||||||
|
#include "AppConfig.h"
|
||||||
|
|
||||||
#include <wx/mstream.h>
|
#include <wx/mstream.h>
|
||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
|
@ -65,8 +66,8 @@ CtrlDisassemblyView::CtrlDisassemblyView(wxWindow* parent, DebugInterface* _cpu)
|
||||||
{
|
{
|
||||||
manager.setCpu(cpu);
|
manager.setCpu(cpu);
|
||||||
windowStart = 0x100000;
|
windowStart = 0x100000;
|
||||||
rowHeight = 14;
|
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight+2;
|
||||||
charWidth = 8;
|
charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
||||||
displaySymbols = true;
|
displaySymbols = true;
|
||||||
visibleRows = 1;
|
visibleRows = 1;
|
||||||
|
|
||||||
|
@ -105,9 +106,13 @@ WXLRESULT CtrlDisassemblyView::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPA
|
||||||
switch (nMsg)
|
switch (nMsg)
|
||||||
{
|
{
|
||||||
case 0x0104: // WM_SYSKEYDOWN, make f10 usable
|
case 0x0104: // WM_SYSKEYDOWN, make f10 usable
|
||||||
|
if (wParam == 0x79) // f10
|
||||||
|
{
|
||||||
postEvent(debEVT_STEPOVER,0);
|
postEvent(debEVT_STEPOVER,0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return wxWindow::MSWWindowProc(nMsg,wParam,lParam);
|
return wxWindow::MSWWindowProc(nMsg,wParam,lParam);
|
||||||
}
|
}
|
||||||
|
@ -684,7 +689,10 @@ void CtrlDisassemblyView::keydownEvent(wxKeyEvent& evt)
|
||||||
break;
|
break;
|
||||||
case WXK_F10:
|
case WXK_F10:
|
||||||
postEvent(debEVT_STEPOVER,0);
|
postEvent(debEVT_STEPOVER,0);
|
||||||
break;
|
return;
|
||||||
|
case WXK_F11:
|
||||||
|
postEvent(debEVT_STEPINTO,0);
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
evt.Skip();
|
evt.Skip();
|
||||||
break;
|
break;
|
||||||
|
@ -1051,3 +1059,11 @@ void CtrlDisassemblyView::editBreakpoint()
|
||||||
postEvent(debEVT_UPDATE,0);
|
postEvent(debEVT_UPDATE,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CtrlDisassemblyView::getOpcodeText(u32 address, char* dest)
|
||||||
|
{
|
||||||
|
DisassemblyLineInfo line;
|
||||||
|
address = manager.getStartAddress(address);
|
||||||
|
manager.getLine(address,displaySymbols,line);
|
||||||
|
sprintf(dest,"%s %s",line.name.c_str(),line.params.c_str());
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ public:
|
||||||
void scanFunctions();
|
void scanFunctions();
|
||||||
void clearFunctions() { manager.clear(); };
|
void clearFunctions() { manager.clear(); };
|
||||||
void redraw();
|
void redraw();
|
||||||
|
void getOpcodeText(u32 address, char* dest);
|
||||||
|
|
||||||
u32 getInstructionSizeAt(u32 address)
|
u32 getInstructionSizeAt(u32 address)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
#include "CtrlMemView.h"
|
#include "CtrlMemView.h"
|
||||||
#include "DebugTools/Debug.h"
|
#include "DebugTools/Debug.h"
|
||||||
|
#include "AppConfig.h"
|
||||||
|
|
||||||
#include "BreakpointWindow.h"
|
#include "BreakpointWindow.h"
|
||||||
#include "DebugEvents.h"
|
#include "DebugEvents.h"
|
||||||
|
@ -35,8 +36,8 @@ enum MemoryViewMenuIdentifiers
|
||||||
CtrlMemView::CtrlMemView(wxWindow* parent, DebugInterface* _cpu)
|
CtrlMemView::CtrlMemView(wxWindow* parent, DebugInterface* _cpu)
|
||||||
: wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS), cpu(_cpu)
|
: wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS), cpu(_cpu)
|
||||||
{
|
{
|
||||||
rowHeight = 12;
|
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight;
|
||||||
charWidth = 8;
|
charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
||||||
windowStart = 0x480000;
|
windowStart = 0x480000;
|
||||||
curAddress = windowStart;
|
curAddress = windowStart;
|
||||||
rowSize = 16;
|
rowSize = 16;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "DebugTools/Debug.h"
|
#include "DebugTools/Debug.h"
|
||||||
|
|
||||||
#include "DebugEvents.h"
|
#include "DebugEvents.h"
|
||||||
|
#include "AppConfig.h"
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(CtrlRegisterList, wxWindow)
|
BEGIN_EVENT_TABLE(CtrlRegisterList, wxWindow)
|
||||||
EVT_PAINT(CtrlRegisterList::paintEvent)
|
EVT_PAINT(CtrlRegisterList::paintEvent)
|
||||||
|
@ -18,14 +19,17 @@ enum DisassemblyMenuIdentifiers
|
||||||
ID_REGISTERLIST_DISPLAY32 = 1,
|
ID_REGISTERLIST_DISPLAY32 = 1,
|
||||||
ID_REGISTERLIST_DISPLAY64,
|
ID_REGISTERLIST_DISPLAY64,
|
||||||
ID_REGISTERLIST_DISPLAY128,
|
ID_REGISTERLIST_DISPLAY128,
|
||||||
|
ID_REGISTERLIST_CHANGELOWER,
|
||||||
|
ID_REGISTERLIST_CHANGEUPPER,
|
||||||
|
ID_REGISTERLIST_CHANGEVALUE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu)
|
CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu)
|
||||||
: wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxBORDER), cpu(_cpu)
|
: wxWindow(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS|wxBORDER), cpu(_cpu)
|
||||||
{
|
{
|
||||||
rowHeight = 14;
|
rowHeight = g_Conf->EmuOptions.Debugger.FontHeight+2;
|
||||||
charWidth = 8;
|
charWidth = g_Conf->EmuOptions.Debugger.FontWidth;
|
||||||
category = 0;
|
category = 0;
|
||||||
maxBits = 128;
|
maxBits = 128;
|
||||||
|
|
||||||
|
@ -48,12 +52,6 @@ CtrlRegisterList::CtrlRegisterList(wxWindow* parent, DebugInterface* _cpu)
|
||||||
currentRows.push_back(0);
|
currentRows.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
|
|
||||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
|
|
||||||
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128, L"Display 128 bit");
|
|
||||||
menu.Check(ID_REGISTERLIST_DISPLAY128,true);
|
|
||||||
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&CtrlRegisterList::onPopupClick, NULL, this);
|
|
||||||
|
|
||||||
SetDoubleBuffered(true);
|
SetDoubleBuffered(true);
|
||||||
SetInitialBestSize(ClientToWindowSize(GetMinClientSize()));
|
SetInitialBestSize(ClientToWindowSize(GetMinClientSize()));
|
||||||
}
|
}
|
||||||
|
@ -297,6 +295,46 @@ void CtrlRegisterList::render(wxDC& dc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CtrlRegisterList::changeValue(RegisterChangeMode mode)
|
||||||
|
{
|
||||||
|
wchar_t str[64];
|
||||||
|
|
||||||
|
u128 oldValue = cpu->getRegister(category,currentRows[category]);
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case LOWER64:
|
||||||
|
swprintf(str,64,L"0x%016llX",oldValue._u64[0]);
|
||||||
|
break;
|
||||||
|
case UPPER64:
|
||||||
|
swprintf(str,64,L"0x%016llX",oldValue._u64[1]);
|
||||||
|
break;
|
||||||
|
case CHANGE32:
|
||||||
|
swprintf(str,64,L"0x%08X",oldValue._u32[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 newValue;
|
||||||
|
if (executeExpressionWindow(this,cpu,newValue,str))
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case LOWER64:
|
||||||
|
oldValue._u64[0] = newValue;
|
||||||
|
break;
|
||||||
|
case UPPER64:
|
||||||
|
oldValue._u64[1] = newValue;
|
||||||
|
break;
|
||||||
|
case CHANGE32:
|
||||||
|
oldValue._u32[0] = newValue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu->setRegister(category,currentRows[category],oldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
|
void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
switch (evt.GetId())
|
switch (evt.GetId())
|
||||||
|
@ -319,6 +357,21 @@ void CtrlRegisterList::onPopupClick(wxCommandEvent& evt)
|
||||||
postEvent(debEVT_UPDATELAYOUT,0);
|
postEvent(debEVT_UPDATELAYOUT,0);
|
||||||
Refresh();
|
Refresh();
|
||||||
break;
|
break;
|
||||||
|
case ID_REGISTERLIST_CHANGELOWER:
|
||||||
|
changeValue(LOWER64);
|
||||||
|
Refresh();
|
||||||
|
break;
|
||||||
|
case ID_REGISTERLIST_CHANGEUPPER:
|
||||||
|
changeValue(UPPER64);
|
||||||
|
Refresh();
|
||||||
|
break;
|
||||||
|
case ID_REGISTERLIST_CHANGEVALUE:
|
||||||
|
if (cpu->getRegisterSize(category) == 32)
|
||||||
|
changeValue(CHANGE32);
|
||||||
|
else
|
||||||
|
changeValue(LOWER64);
|
||||||
|
Refresh();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
wxMessageBox( L"Unimplemented.", L"Unimplemented.", wxICON_INFORMATION);
|
wxMessageBox( L"Unimplemented.", L"Unimplemented.", wxICON_INFORMATION);
|
||||||
break;
|
break;
|
||||||
|
@ -374,6 +427,36 @@ void CtrlRegisterList::mouseEvent(wxMouseEvent& evt)
|
||||||
setCurrentRow(row);
|
setCurrentRow(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxMenu menu;
|
||||||
|
int bits = cpu->getRegisterSize(category);
|
||||||
|
|
||||||
|
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY32, L"Display 32 bit");
|
||||||
|
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY64, L"Display 64 bit");
|
||||||
|
menu.AppendRadioItem(ID_REGISTERLIST_DISPLAY128, L"Display 128 bit");
|
||||||
|
menu.AppendSeparator();
|
||||||
|
|
||||||
|
if (bits >= 64)
|
||||||
|
{
|
||||||
|
menu.Append(ID_REGISTERLIST_CHANGELOWER, L"Change lower 64 bit");
|
||||||
|
menu.Append(ID_REGISTERLIST_CHANGEUPPER, L"Change upper 64 bit");
|
||||||
|
} else {
|
||||||
|
menu.Append(ID_REGISTERLIST_CHANGEVALUE, L"Change value");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (maxBits)
|
||||||
|
{
|
||||||
|
case 128:
|
||||||
|
menu.Check(ID_REGISTERLIST_DISPLAY128,true);
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
menu.Check(ID_REGISTERLIST_DISPLAY64,true);
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
menu.Check(ID_REGISTERLIST_DISPLAY32,true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.Connect(wxEVT_COMMAND_MENU_SELECTED, (wxObjectEventFunction)&CtrlRegisterList::onPopupClick, NULL, this);
|
||||||
PopupMenu(&menu,evt.GetPosition());
|
PopupMenu(&menu,evt.GetPosition());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,9 +46,12 @@ public:
|
||||||
return GetMinClientSize();
|
return GetMinClientSize();
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
enum RegisterChangeMode { LOWER64, UPPER64, CHANGE32 };
|
||||||
|
|
||||||
void render(wxDC& dc);
|
void render(wxDC& dc);
|
||||||
void refreshChangedRegs();
|
void refreshChangedRegs();
|
||||||
void setCurrentRow(int row);
|
void setCurrentRow(int row);
|
||||||
|
void changeValue(RegisterChangeMode mode);
|
||||||
|
|
||||||
void postEvent(wxEventType type, wxString text);
|
void postEvent(wxEventType type, wxString text);
|
||||||
void postEvent(wxEventType type, int value);
|
void postEvent(wxEventType type, int value);
|
||||||
|
@ -68,5 +71,4 @@ private:
|
||||||
u32 lastPc;
|
u32 lastPc;
|
||||||
int category;
|
int category;
|
||||||
int maxBits;
|
int maxBits;
|
||||||
wxMenu menu;
|
|
||||||
};
|
};
|
|
@ -8,6 +8,7 @@ DEFINE_LOCAL_EVENT_TYPE( debEVT_GOTOINDISASM )
|
||||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_RUNTOPOS )
|
DEFINE_LOCAL_EVENT_TYPE( debEVT_RUNTOPOS )
|
||||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_MAPLOADED )
|
DEFINE_LOCAL_EVENT_TYPE( debEVT_MAPLOADED )
|
||||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_STEPOVER )
|
DEFINE_LOCAL_EVENT_TYPE( debEVT_STEPOVER )
|
||||||
|
DEFINE_LOCAL_EVENT_TYPE( debEVT_STEPINTO )
|
||||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_UPDATE )
|
DEFINE_LOCAL_EVENT_TYPE( debEVT_UPDATE )
|
||||||
|
|
||||||
bool parseExpression(const char* exp, DebugInterface* cpu, u64& dest)
|
bool parseExpression(const char* exp, DebugInterface* cpu, u64& dest)
|
||||||
|
@ -22,9 +23,9 @@ void displayExpressionError(wxWindow* parent)
|
||||||
wxMessageBox(wxString(getExpressionError(),wxConvUTF8),L"Invalid expression",wxICON_ERROR);
|
wxMessageBox(wxString(getExpressionError(),wxConvUTF8),L"Invalid expression",wxICON_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest)
|
bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest, const wxString& defaultValue)
|
||||||
{
|
{
|
||||||
wxString result = wxGetTextFromUser(L"Enter expression",L"Expression",wxEmptyString,parent);
|
wxString result = wxGetTextFromUser(L"Enter expression",L"Expression",defaultValue,parent);
|
||||||
if (result.empty())
|
if (result.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ DECLARE_LOCAL_EVENT_TYPE( debEVT_GOTOINDISASM, wxNewEventType() )
|
||||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_RUNTOPOS, wxNewEventType() )
|
DECLARE_LOCAL_EVENT_TYPE( debEVT_RUNTOPOS, wxNewEventType() )
|
||||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_MAPLOADED, wxNewEventType() )
|
DECLARE_LOCAL_EVENT_TYPE( debEVT_MAPLOADED, wxNewEventType() )
|
||||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_STEPOVER, wxNewEventType() )
|
DECLARE_LOCAL_EVENT_TYPE( debEVT_STEPOVER, wxNewEventType() )
|
||||||
|
DECLARE_LOCAL_EVENT_TYPE( debEVT_STEPINTO, wxNewEventType() )
|
||||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_UPDATE, wxNewEventType() )
|
DECLARE_LOCAL_EVENT_TYPE( debEVT_UPDATE, wxNewEventType() )
|
||||||
|
|
||||||
bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest);
|
bool executeExpressionWindow(wxWindow* parent, DebugInterface* cpu, u64& dest, const wxString& defaultValue = wxEmptyString);
|
||||||
|
|
|
@ -0,0 +1,334 @@
|
||||||
|
#include "PrecompiledHeader.h"
|
||||||
|
#include "DebuggerLists.h"
|
||||||
|
#include "BreakpointWindow.h"
|
||||||
|
#include "DebugEvents.h"
|
||||||
|
|
||||||
|
void insertListViewColumns(wxListCtrl* list, GenericListViewColumn* columns, int count)
|
||||||
|
{
|
||||||
|
int totalWidth = list->GetSize().x;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
wxListItem column;
|
||||||
|
column.SetText(columns[i].name);
|
||||||
|
column.SetWidth(totalWidth * columns[i].size);
|
||||||
|
|
||||||
|
list->InsertColumn(i,column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resizeListViewColumns(wxListCtrl* list, GenericListViewColumn* columns, int count, int totalWidth)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
list->SetColumnWidth(i,totalWidth*columns[i].size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// BreakpointList
|
||||||
|
//
|
||||||
|
|
||||||
|
BEGIN_EVENT_TABLE(BreakpointList, wxWindow)
|
||||||
|
EVT_SIZE(BreakpointList::sizeEvent)
|
||||||
|
EVT_KEY_DOWN(BreakpointList::keydownEvent)
|
||||||
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
|
enum { BPL_TYPE, BPL_OFFSET, BPL_SIZELABEL, BPL_OPCODE, BPL_CONDITION, BPL_HITS, BPL_ENABLED, BPL_COLUMNCOUNT };
|
||||||
|
|
||||||
|
GenericListViewColumn breakpointColumns[BPL_COLUMNCOUNT] = {
|
||||||
|
{ L"Type", 0.12f },
|
||||||
|
{ L"Offset", 0.12f },
|
||||||
|
{ L"Size/Label", 0.18f },
|
||||||
|
{ L"Opcode", 0.28f },
|
||||||
|
{ L"Condition", 0.17f },
|
||||||
|
{ L"Hits", 0.05f },
|
||||||
|
{ L"Enabled", 0.08f }
|
||||||
|
};
|
||||||
|
|
||||||
|
BreakpointList::BreakpointList(wxWindow* parent, DebugInterface* _cpu, CtrlDisassemblyView* _disassembly)
|
||||||
|
: wxListView(parent,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxLC_VIRTUAL|wxLC_REPORT|wxLC_SINGLE_SEL|wxNO_BORDER), cpu(_cpu), disasm(_disassembly)
|
||||||
|
{
|
||||||
|
insertListViewColumns(this,breakpointColumns,BPL_COLUMNCOUNT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointList::sizeEvent(wxSizeEvent& evt)
|
||||||
|
{
|
||||||
|
resizeListViewColumns(this,breakpointColumns,BPL_COLUMNCOUNT,evt.GetSize().x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointList::update()
|
||||||
|
{
|
||||||
|
int newRows = getTotalBreakpointCount();
|
||||||
|
SetItemCount(newRows);
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BreakpointList::getTotalBreakpointCount()
|
||||||
|
{
|
||||||
|
int count = (int)CBreakPoints::GetMemChecks().size();
|
||||||
|
for (size_t i = 0; i < CBreakPoints::GetBreakpoints().size(); i++)
|
||||||
|
{
|
||||||
|
if (!displayedBreakPoints_[i].temporary) count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString BreakpointList::OnGetItemText(long item, long col) const
|
||||||
|
{
|
||||||
|
wchar_t dest[256];
|
||||||
|
bool isMemory;
|
||||||
|
int index = getBreakpointIndex(item,isMemory);
|
||||||
|
if (index == -1) return L"Invalid";
|
||||||
|
|
||||||
|
switch (col)
|
||||||
|
{
|
||||||
|
case BPL_TYPE:
|
||||||
|
{
|
||||||
|
if (isMemory) {
|
||||||
|
switch ((int)displayedMemChecks_[index].cond) {
|
||||||
|
case MEMCHECK_READ:
|
||||||
|
wcscpy(dest,L"Read");
|
||||||
|
break;
|
||||||
|
case MEMCHECK_WRITE:
|
||||||
|
wcscpy(dest,L"Write");
|
||||||
|
break;
|
||||||
|
case MEMCHECK_READWRITE:
|
||||||
|
wcscpy(dest,L"Read/Write");
|
||||||
|
break;
|
||||||
|
case MEMCHECK_WRITE | MEMCHECK_WRITE_ONCHANGE:
|
||||||
|
wcscpy(dest,L"Write Change");
|
||||||
|
break;
|
||||||
|
case MEMCHECK_READWRITE | MEMCHECK_WRITE_ONCHANGE:
|
||||||
|
wcscpy(dest,L"Read/Write Change");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wcscpy(dest,L"Execute");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BPL_OFFSET:
|
||||||
|
{
|
||||||
|
if (isMemory) {
|
||||||
|
swprintf(dest,256,L"0x%08X",displayedMemChecks_[index].start);
|
||||||
|
} else {
|
||||||
|
swprintf(dest,256,L"0x%08X",displayedBreakPoints_[index].addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BPL_SIZELABEL:
|
||||||
|
{
|
||||||
|
if (isMemory) {
|
||||||
|
auto mc = displayedMemChecks_[index];
|
||||||
|
if (mc.end == 0)
|
||||||
|
swprintf(dest,256,L"0x%08X",1);
|
||||||
|
else
|
||||||
|
swprintf(dest,256,L"0x%08X",mc.end-mc.start);
|
||||||
|
} else {
|
||||||
|
const std::string sym = symbolMap.GetLabelString(displayedBreakPoints_[index].addr);
|
||||||
|
if (!sym.empty())
|
||||||
|
{
|
||||||
|
swprintf(dest,256,L"%S",sym.c_str());
|
||||||
|
} else {
|
||||||
|
wcscpy(dest,L"-");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BPL_OPCODE:
|
||||||
|
{
|
||||||
|
if (isMemory) {
|
||||||
|
wcscpy(dest,L"-");
|
||||||
|
} else {
|
||||||
|
char temp[256];
|
||||||
|
disasm->getOpcodeText(displayedBreakPoints_[index].addr, temp);
|
||||||
|
swprintf(dest,256,L"%S",temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BPL_CONDITION:
|
||||||
|
{
|
||||||
|
if (isMemory || displayedBreakPoints_[index].hasCond == false) {
|
||||||
|
wcscpy(dest,L"-");
|
||||||
|
} else {
|
||||||
|
swprintf(dest,256,L"%S",displayedBreakPoints_[index].cond.expressionString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BPL_HITS:
|
||||||
|
{
|
||||||
|
if (isMemory) {
|
||||||
|
swprintf(dest,256,L"%d",displayedMemChecks_[index].numHits);
|
||||||
|
} else {
|
||||||
|
swprintf(dest,256,L"-");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BPL_ENABLED:
|
||||||
|
{
|
||||||
|
if (isMemory) {
|
||||||
|
swprintf(dest,256,L"%S",displayedMemChecks_[index].cond & MEMCHECK_BREAK ? "true" : "false");
|
||||||
|
} else {
|
||||||
|
swprintf(dest,256,L"%S",displayedBreakPoints_[index].enabled ? "true" : "false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return L"Invalid";
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointList::keydownEvent(wxKeyEvent& evt)
|
||||||
|
{
|
||||||
|
int sel = GetFirstSelected();
|
||||||
|
switch (evt.GetKeyCode())
|
||||||
|
{
|
||||||
|
case WXK_DELETE:
|
||||||
|
if (sel+1 == GetItemCount())
|
||||||
|
Select(sel-1);
|
||||||
|
removeBreakpoint(sel);
|
||||||
|
break;
|
||||||
|
case WXK_UP:
|
||||||
|
if (sel > 0)
|
||||||
|
Select(sel-1);
|
||||||
|
break;
|
||||||
|
case WXK_DOWN:
|
||||||
|
if (sel+1 < GetItemCount())
|
||||||
|
Select(sel+1);
|
||||||
|
break;
|
||||||
|
case WXK_RETURN:
|
||||||
|
editBreakpoint(sel);
|
||||||
|
break;
|
||||||
|
case WXK_SPACE:
|
||||||
|
toggleEnabled(sel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int BreakpointList::getBreakpointIndex(int itemIndex, bool& isMemory) const
|
||||||
|
{
|
||||||
|
// memory breakpoints first
|
||||||
|
if (itemIndex < (int)displayedMemChecks_.size())
|
||||||
|
{
|
||||||
|
isMemory = true;
|
||||||
|
return itemIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemIndex -= (int)displayedMemChecks_.size();
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < displayedBreakPoints_.size())
|
||||||
|
{
|
||||||
|
if (displayedBreakPoints_[i].temporary)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the index is 0 when there are no more breakpoints to skip
|
||||||
|
if (itemIndex == 0)
|
||||||
|
{
|
||||||
|
isMemory = false;
|
||||||
|
return (int)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
itemIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointList::reloadBreakpoints()
|
||||||
|
{
|
||||||
|
// Update the items we're displaying from the debugger.
|
||||||
|
displayedBreakPoints_ = CBreakPoints::GetBreakpoints();
|
||||||
|
displayedMemChecks_= CBreakPoints::GetMemChecks();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointList::editBreakpoint(int itemIndex)
|
||||||
|
{
|
||||||
|
bool isMemory;
|
||||||
|
int index = getBreakpointIndex(itemIndex, isMemory);
|
||||||
|
if (index == -1) return;
|
||||||
|
|
||||||
|
BreakpointWindow win(this,cpu);
|
||||||
|
if (isMemory)
|
||||||
|
{
|
||||||
|
auto mem = displayedMemChecks_[index];
|
||||||
|
win.loadFromMemcheck(mem);
|
||||||
|
if (win.ShowModal() == wxID_OK)
|
||||||
|
{
|
||||||
|
CBreakPoints::RemoveMemCheck(mem.start,mem.end);
|
||||||
|
win.addBreakpoint();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto bp = displayedBreakPoints_[index];
|
||||||
|
win.loadFromBreakpoint(bp);
|
||||||
|
if (win.ShowModal() == wxID_OK)
|
||||||
|
{
|
||||||
|
CBreakPoints::RemoveBreakPoint(bp.addr);
|
||||||
|
win.addBreakpoint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointList::toggleEnabled(int itemIndex)
|
||||||
|
{
|
||||||
|
bool isMemory;
|
||||||
|
int index = getBreakpointIndex(itemIndex, isMemory);
|
||||||
|
if (index == -1) return;
|
||||||
|
|
||||||
|
if (isMemory) {
|
||||||
|
MemCheck mcPrev = displayedMemChecks_[index];
|
||||||
|
CBreakPoints::ChangeMemCheck(mcPrev.start, mcPrev.end, mcPrev.cond, MemCheckResult(mcPrev.result ^ MEMCHECK_BREAK));
|
||||||
|
} else {
|
||||||
|
BreakPoint bpPrev = displayedBreakPoints_[index];
|
||||||
|
CBreakPoints::ChangeBreakPoint(bpPrev.addr, !bpPrev.enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointList::gotoBreakpointAddress(int itemIndex)
|
||||||
|
{
|
||||||
|
bool isMemory;
|
||||||
|
int index = getBreakpointIndex(itemIndex,isMemory);
|
||||||
|
if (index == -1) return;
|
||||||
|
|
||||||
|
if (isMemory)
|
||||||
|
{
|
||||||
|
u32 address = displayedMemChecks_[index].start;
|
||||||
|
postEvent(debEVT_GOTOINMEMORYVIEW,address);
|
||||||
|
} else {
|
||||||
|
u32 address = displayedBreakPoints_[index].addr;
|
||||||
|
postEvent(debEVT_GOTOINDISASM,address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointList::removeBreakpoint(int itemIndex)
|
||||||
|
{
|
||||||
|
bool isMemory;
|
||||||
|
int index = getBreakpointIndex(itemIndex,isMemory);
|
||||||
|
if (index == -1) return;
|
||||||
|
|
||||||
|
if (isMemory)
|
||||||
|
{
|
||||||
|
auto mc = displayedMemChecks_[index];
|
||||||
|
CBreakPoints::RemoveMemCheck(mc.start, mc.end);
|
||||||
|
} else {
|
||||||
|
u32 address = displayedBreakPoints_[index].addr;
|
||||||
|
CBreakPoints::RemoveBreakPoint(address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointList::postEvent(wxEventType type, int value)
|
||||||
|
{
|
||||||
|
wxCommandEvent event( type, GetId() );
|
||||||
|
event.SetEventObject(this);
|
||||||
|
event.SetInt(value);
|
||||||
|
wxPostEvent(this,event);
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
#include <wx/listctrl.h>
|
||||||
|
#include "DebugTools/DebugInterface.h"
|
||||||
|
#include "DebugTools/Breakpoints.h"
|
||||||
|
#include "CtrlDisassemblyView.h"
|
||||||
|
|
||||||
|
struct GenericListViewColumn
|
||||||
|
{
|
||||||
|
wchar_t *name;
|
||||||
|
float size;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BreakpointList: public wxListView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BreakpointList(wxWindow* parent, DebugInterface* _cpu, CtrlDisassemblyView* _disassembly);
|
||||||
|
void reloadBreakpoints();
|
||||||
|
void update();
|
||||||
|
DECLARE_EVENT_TABLE()
|
||||||
|
protected:
|
||||||
|
wxString OnGetItemText(long item, long col) const;
|
||||||
|
|
||||||
|
void sizeEvent(wxSizeEvent& evt);
|
||||||
|
void keydownEvent(wxKeyEvent& evt);
|
||||||
|
private:
|
||||||
|
int getBreakpointIndex(int itemIndex, bool& isMemory) const;
|
||||||
|
int getTotalBreakpointCount();
|
||||||
|
void editBreakpoint(int itemIndex);
|
||||||
|
void toggleEnabled(int itemIndex);
|
||||||
|
void gotoBreakpointAddress(int itemIndex);
|
||||||
|
void removeBreakpoint(int itemIndex);
|
||||||
|
void postEvent(wxEventType type, int value);
|
||||||
|
|
||||||
|
std::vector<BreakPoint> displayedBreakPoints_;
|
||||||
|
std::vector<MemCheck> displayedMemChecks_;
|
||||||
|
DebugInterface* cpu;
|
||||||
|
CtrlDisassemblyView* disasm;
|
||||||
|
};
|
|
@ -5,6 +5,11 @@
|
||||||
#include "DebugTools/DisassemblyManager.h"
|
#include "DebugTools/DisassemblyManager.h"
|
||||||
#include "DebugTools/Breakpoints.h"
|
#include "DebugTools/Breakpoints.h"
|
||||||
#include "BreakpointWindow.h"
|
#include "BreakpointWindow.h"
|
||||||
|
#include "PathDefs.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(DisassemblyDialog, wxFrame)
|
BEGIN_EVENT_TABLE(DisassemblyDialog, wxFrame)
|
||||||
EVT_COMMAND( wxID_ANY, debEVT_SETSTATUSBARTEXT, DisassemblyDialog::onDebuggerEvent )
|
EVT_COMMAND( wxID_ANY, debEVT_SETSTATUSBARTEXT, DisassemblyDialog::onDebuggerEvent )
|
||||||
|
@ -13,9 +18,39 @@ BEGIN_EVENT_TABLE(DisassemblyDialog, wxFrame)
|
||||||
EVT_COMMAND( wxID_ANY, debEVT_RUNTOPOS, DisassemblyDialog::onDebuggerEvent )
|
EVT_COMMAND( wxID_ANY, debEVT_RUNTOPOS, DisassemblyDialog::onDebuggerEvent )
|
||||||
EVT_COMMAND( wxID_ANY, debEVT_GOTOINDISASM, DisassemblyDialog::onDebuggerEvent )
|
EVT_COMMAND( wxID_ANY, debEVT_GOTOINDISASM, DisassemblyDialog::onDebuggerEvent )
|
||||||
EVT_COMMAND( wxID_ANY, debEVT_STEPOVER, DisassemblyDialog::onDebuggerEvent )
|
EVT_COMMAND( wxID_ANY, debEVT_STEPOVER, DisassemblyDialog::onDebuggerEvent )
|
||||||
|
EVT_COMMAND( wxID_ANY, debEVT_STEPINTO, DisassemblyDialog::onDebuggerEvent )
|
||||||
EVT_COMMAND( wxID_ANY, debEVT_UPDATE, DisassemblyDialog::onDebuggerEvent )
|
EVT_COMMAND( wxID_ANY, debEVT_UPDATE, DisassemblyDialog::onDebuggerEvent )
|
||||||
|
EVT_CLOSE( DisassemblyDialog::onClose )
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
DebuggerHelpDialog::DebuggerHelpDialog(wxWindow* parent)
|
||||||
|
: wxDialog(parent,wxID_ANY,L"Help")
|
||||||
|
{
|
||||||
|
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
|
wxTextCtrl* textControl = new wxTextCtrl(this,wxID_ANY,L"",wxDefaultPosition,wxDefaultSize,
|
||||||
|
wxTE_MULTILINE|wxTE_READONLY);
|
||||||
|
textControl->SetMinSize(wxSize(400,300));
|
||||||
|
auto fileName = PathDefs::GetDocs().ToString()+L"/debugger.txt";
|
||||||
|
wxTextFile file(fileName);
|
||||||
|
if (file.Open())
|
||||||
|
{
|
||||||
|
wxString text = file.GetFirstLine();
|
||||||
|
while (!file.Eof())
|
||||||
|
{
|
||||||
|
text += file.GetNextLine()+L"\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
textControl->SetLabel(text);
|
||||||
|
textControl->SetSelection(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sizer->Add(textControl,1,wxEXPAND);
|
||||||
|
SetSizerAndFit(sizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CpuTabPage::CpuTabPage(wxWindow* parent, DebugInterface* _cpu)
|
CpuTabPage::CpuTabPage(wxWindow* parent, DebugInterface* _cpu)
|
||||||
: wxPanel(parent), cpu(_cpu)
|
: wxPanel(parent), cpu(_cpu)
|
||||||
{
|
{
|
||||||
|
@ -39,11 +74,34 @@ CpuTabPage::CpuTabPage(wxWindow* parent, DebugInterface* _cpu)
|
||||||
|
|
||||||
// create bottom section
|
// create bottom section
|
||||||
bottomTabs->AddPage(memory,L"Memory");
|
bottomTabs->AddPage(memory,L"Memory");
|
||||||
|
|
||||||
|
breakpointList = new BreakpointList(bottomTabs,cpu,disassembly);
|
||||||
|
bottomTabs->AddPage(breakpointList,L"Breakpoints");
|
||||||
|
|
||||||
mainSizer->Add(bottomTabs,1,wxEXPAND);
|
mainSizer->Add(bottomTabs,1,wxEXPAND);
|
||||||
|
|
||||||
mainSizer->Layout();
|
mainSizer->Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CpuTabPage::setBottomTabPage(wxWindow* win)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < bottomTabs->GetPageCount(); i++)
|
||||||
|
{
|
||||||
|
if (bottomTabs->GetPage(i) == win)
|
||||||
|
{
|
||||||
|
bottomTabs->SetSelection(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CpuTabPage::update()
|
||||||
|
{
|
||||||
|
breakpointList->reloadBreakpoints();
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
|
DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
|
||||||
wxFrame( parent, wxID_ANY, L"Debugger", wxDefaultPosition,wxDefaultSize,wxRESIZE_BORDER|wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU ),
|
wxFrame( parent, wxID_ANY, L"Debugger", wxDefaultPosition,wxDefaultSize,wxRESIZE_BORDER|wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU ),
|
||||||
currentCpu(NULL)
|
currentCpu(NULL)
|
||||||
|
@ -63,6 +121,7 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
|
||||||
|
|
||||||
stepIntoButton = new wxButton( panel, wxID_ANY, L"Step Into" );
|
stepIntoButton = new wxButton( panel, wxID_ANY, L"Step Into" );
|
||||||
stepIntoButton->Enable(false);
|
stepIntoButton->Enable(false);
|
||||||
|
Connect( stepIntoButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DisassemblyDialog::onStepIntoClicked ) );
|
||||||
topRowSizer->Add(stepIntoButton,0,wxBOTTOM,2);
|
topRowSizer->Add(stepIntoButton,0,wxBOTTOM,2);
|
||||||
|
|
||||||
stepOverButton = new wxButton( panel, wxID_ANY, L"Step Over" );
|
stepOverButton = new wxButton( panel, wxID_ANY, L"Step Over" );
|
||||||
|
@ -99,11 +158,43 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
|
||||||
setDebugMode(true);
|
setDebugMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
WXLRESULT DisassemblyDialog::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (nMsg)
|
||||||
|
{
|
||||||
|
case WM_SHOWWINDOW:
|
||||||
|
{
|
||||||
|
WXHWND hwnd = GetHWND();
|
||||||
|
|
||||||
|
u32 style = GetWindowLong((HWND)hwnd,GWL_STYLE);
|
||||||
|
style &= ~(WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
|
||||||
|
SetWindowLong((HWND)hwnd,GWL_STYLE,style);
|
||||||
|
|
||||||
|
u32 exStyle = GetWindowLong((HWND)hwnd,GWL_EXSTYLE);
|
||||||
|
exStyle |= (WS_EX_CONTEXTHELP);
|
||||||
|
SetWindowLong((HWND)hwnd,GWL_EXSTYLE,exStyle);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WM_SYSCOMMAND:
|
||||||
|
if (wParam == SC_CONTEXTHELP)
|
||||||
|
{
|
||||||
|
DebuggerHelpDialog help(this);
|
||||||
|
help.ShowModal();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxFrame::MSWWindowProc(nMsg,wParam,lParam);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void DisassemblyDialog::onBreakRunClicked(wxCommandEvent& evt)
|
void DisassemblyDialog::onBreakRunClicked(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
if (r5900Debug.isCpuPaused())
|
if (r5900Debug.isCpuPaused())
|
||||||
{
|
{
|
||||||
if (CBreakPoints::IsAddressBreakPoint(r5900Debug.getPC()))
|
// If the current PC is on a breakpoint, the user doesn't want to do nothing.
|
||||||
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
CBreakPoints::SetSkipFirst(r5900Debug.getPC());
|
||||||
r5900Debug.resumeCpu();
|
r5900Debug.resumeCpu();
|
||||||
} else
|
} else
|
||||||
|
@ -115,6 +206,11 @@ void DisassemblyDialog::onStepOverClicked(wxCommandEvent& evt)
|
||||||
stepOver();
|
stepOver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisassemblyDialog::onStepIntoClicked(wxCommandEvent& evt)
|
||||||
|
{
|
||||||
|
stepInto();
|
||||||
|
}
|
||||||
|
|
||||||
void DisassemblyDialog::onPageChanging(wxCommandEvent& evt)
|
void DisassemblyDialog::onPageChanging(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
wxNotebook* notebook = (wxNotebook*)wxWindow::FindWindowById(evt.GetId());
|
wxNotebook* notebook = (wxNotebook*)wxWindow::FindWindowById(evt.GetId());
|
||||||
|
@ -130,7 +226,7 @@ void DisassemblyDialog::onPageChanging(wxCommandEvent& evt)
|
||||||
if (currentCpu != NULL)
|
if (currentCpu != NULL)
|
||||||
{
|
{
|
||||||
currentCpu->getDisassembly()->SetFocus();
|
currentCpu->getDisassembly()->SetFocus();
|
||||||
currentCpu->Refresh();
|
currentCpu->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +277,48 @@ void DisassemblyDialog::stepOver()
|
||||||
r5900Debug.resumeCpu();
|
r5900Debug.resumeCpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DisassemblyDialog::stepInto()
|
||||||
|
{
|
||||||
|
if (!r5900Debug.isAlive() || !r5900Debug.isCpuPaused() || currentCpu == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// todo: breakpoints for iop
|
||||||
|
if (currentCpu != eeTab)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
MIPSAnalyst::MipsOpcodeInfo info = MIPSAnalyst::GetOpcodeInfo(&r5900Debug,r5900Debug.getPC());
|
||||||
|
u32 breakpointAddress = currentPc+disassembly->getInstructionSizeAt(currentPc);
|
||||||
|
if (info.isBranch)
|
||||||
|
{
|
||||||
|
if (info.isConditional == false)
|
||||||
|
{
|
||||||
|
breakpointAddress = info.branchTarget;
|
||||||
|
} else {
|
||||||
|
if (info.conditionMet)
|
||||||
|
{
|
||||||
|
breakpointAddress = info.branchTarget;
|
||||||
|
} else {
|
||||||
|
breakpointAddress = currentPc+2*4;
|
||||||
|
disassembly->scrollStepping(breakpointAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.isSyscall)
|
||||||
|
breakpointAddress = info.branchTarget;
|
||||||
|
|
||||||
|
CBreakPoints::AddBreakPoint(breakpointAddress,true);
|
||||||
|
r5900Debug.resumeCpu();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DisassemblyDialog::onBreakpointClick(wxCommandEvent& evt)
|
void DisassemblyDialog::onBreakpointClick(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
if (currentCpu == NULL)
|
if (currentCpu == NULL)
|
||||||
|
@ -209,7 +347,11 @@ void DisassemblyDialog::onDebuggerEvent(wxCommandEvent& evt)
|
||||||
} else if (type == debEVT_GOTOINMEMORYVIEW)
|
} else if (type == debEVT_GOTOINMEMORYVIEW)
|
||||||
{
|
{
|
||||||
if (currentCpu != NULL)
|
if (currentCpu != NULL)
|
||||||
|
{
|
||||||
|
currentCpu->showMemoryView();
|
||||||
currentCpu->getMemoryView()->gotoAddress(evt.GetInt());
|
currentCpu->getMemoryView()->gotoAddress(evt.GetInt());
|
||||||
|
currentCpu->getDisassembly()->SetFocus();
|
||||||
|
}
|
||||||
} else if (type == debEVT_RUNTOPOS)
|
} else if (type == debEVT_RUNTOPOS)
|
||||||
{
|
{
|
||||||
// todo: breakpoints for iop
|
// todo: breakpoints for iop
|
||||||
|
@ -229,19 +371,28 @@ void DisassemblyDialog::onDebuggerEvent(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
if (currentCpu != NULL)
|
if (currentCpu != NULL)
|
||||||
stepOver();
|
stepOver();
|
||||||
|
} else if (type == debEVT_STEPINTO)
|
||||||
|
{
|
||||||
|
if (currentCpu != NULL)
|
||||||
|
stepInto();
|
||||||
} else if (type == debEVT_UPDATE)
|
} else if (type == debEVT_UPDATE)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisassemblyDialog::onClose(wxCloseEvent& evt)
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
|
||||||
void DisassemblyDialog::update()
|
void DisassemblyDialog::update()
|
||||||
{
|
{
|
||||||
if (currentCpu != NULL)
|
if (currentCpu != NULL)
|
||||||
{
|
{
|
||||||
stepOverButton->Enable(true);
|
stepOverButton->Enable(true);
|
||||||
breakpointButton->Enable(true);
|
breakpointButton->Enable(true);
|
||||||
currentCpu->Refresh();
|
currentCpu->update();
|
||||||
} else {
|
} else {
|
||||||
stepOverButton->Enable(false);
|
stepOverButton->Enable(false);
|
||||||
breakpointButton->Enable(false);
|
breakpointButton->Enable(false);
|
||||||
|
@ -269,13 +420,17 @@ void DisassemblyDialog::setDebugMode(bool debugMode)
|
||||||
breakRunButton->SetLabel(L"Run");
|
breakRunButton->SetLabel(L"Run");
|
||||||
|
|
||||||
stepOverButton->Enable(true);
|
stepOverButton->Enable(true);
|
||||||
|
stepIntoButton->Enable(true);
|
||||||
|
|
||||||
eeTab->getDisassembly()->gotoPc();
|
eeTab->getDisassembly()->gotoPc();
|
||||||
iopTab->getDisassembly()->gotoPc();
|
iopTab->getDisassembly()->gotoPc();
|
||||||
|
|
||||||
// Defocuses main window even when not debugging, causing savestate hotkeys to fail
|
if (CBreakPoints::GetBreakpointTriggered())
|
||||||
/*if (currentCpu != NULL)
|
{
|
||||||
currentCpu->getDisassembly()->SetFocus();*/
|
if (currentCpu != NULL)
|
||||||
|
currentCpu->getDisassembly()->SetFocus();
|
||||||
|
CBreakPoints::SetBreakpointTriggered(false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
breakRunButton->SetLabel(L"Break");
|
breakRunButton->SetLabel(L"Break");
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,13 @@
|
||||||
#include "CtrlRegisterList.h"
|
#include "CtrlRegisterList.h"
|
||||||
#include "CtrlMemView.h"
|
#include "CtrlMemView.h"
|
||||||
#include "DebugEvents.h"
|
#include "DebugEvents.h"
|
||||||
|
#include "DebuggerLists.h"
|
||||||
|
|
||||||
|
class DebuggerHelpDialog: public wxDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DebuggerHelpDialog(wxWindow* parent);
|
||||||
|
};
|
||||||
|
|
||||||
class CpuTabPage: public wxPanel
|
class CpuTabPage: public wxPanel
|
||||||
{
|
{
|
||||||
|
@ -17,12 +24,16 @@ public:
|
||||||
CtrlRegisterList* getRegisterList() { return registerList; };
|
CtrlRegisterList* getRegisterList() { return registerList; };
|
||||||
CtrlMemView* getMemoryView() { return memory; };
|
CtrlMemView* getMemoryView() { return memory; };
|
||||||
wxNotebook* getBottomTabs() { return bottomTabs; };
|
wxNotebook* getBottomTabs() { return bottomTabs; };
|
||||||
|
void update();
|
||||||
|
void showMemoryView() { setBottomTabPage(memory); };
|
||||||
private:
|
private:
|
||||||
|
void setBottomTabPage(wxWindow* win);
|
||||||
DebugInterface* cpu;
|
DebugInterface* cpu;
|
||||||
CtrlDisassemblyView* disassembly;
|
CtrlDisassemblyView* disassembly;
|
||||||
CtrlRegisterList* registerList;
|
CtrlRegisterList* registerList;
|
||||||
CtrlMemView* memory;
|
CtrlMemView* memory;
|
||||||
wxNotebook* bottomTabs;
|
wxNotebook* bottomTabs;
|
||||||
|
BreakpointList* breakpointList;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DisassemblyDialog : public wxFrame
|
class DisassemblyDialog : public wxFrame
|
||||||
|
@ -38,14 +49,21 @@ public:
|
||||||
void reset();
|
void reset();
|
||||||
void setDebugMode(bool debugMode);
|
void setDebugMode(bool debugMode);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
|
||||||
|
#endif
|
||||||
|
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
protected:
|
protected:
|
||||||
void onBreakRunClicked(wxCommandEvent& evt);
|
void onBreakRunClicked(wxCommandEvent& evt);
|
||||||
void onStepOverClicked(wxCommandEvent& evt);
|
void onStepOverClicked(wxCommandEvent& evt);
|
||||||
|
void onStepIntoClicked(wxCommandEvent& evt);
|
||||||
void onDebuggerEvent(wxCommandEvent& evt);
|
void onDebuggerEvent(wxCommandEvent& evt);
|
||||||
void onPageChanging(wxCommandEvent& evt);
|
void onPageChanging(wxCommandEvent& evt);
|
||||||
void onBreakpointClick(wxCommandEvent& evt);
|
void onBreakpointClick(wxCommandEvent& evt);
|
||||||
|
void onClose(wxCloseEvent& evt);
|
||||||
void stepOver();
|
void stepOver();
|
||||||
|
void stepInto();
|
||||||
private:
|
private:
|
||||||
CpuTabPage* eeTab;
|
CpuTabPage* eeTab;
|
||||||
CpuTabPage* iopTab;
|
CpuTabPage* iopTab;
|
||||||
|
|
|
@ -339,9 +339,14 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
|
||||||
m_menubar.Append( &m_menuCDVD, _("CD&VD") );
|
m_menubar.Append( &m_menuCDVD, _("CD&VD") );
|
||||||
m_menubar.Append( &m_menuConfig, _("&Config") );
|
m_menubar.Append( &m_menuConfig, _("&Config") );
|
||||||
m_menubar.Append( &m_menuMisc, _("&Misc") );
|
m_menubar.Append( &m_menuMisc, _("&Misc") );
|
||||||
#ifdef PCSX2_DEVBUILD
|
|
||||||
m_menubar.Append( &m_menuDebug, _("&Debug") );
|
#ifndef PCSX2_DEVBUILD
|
||||||
|
if (g_Conf->EmuOptions.Debugger.EnableDebugger)
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
m_menubar.Append( &m_menuDebug, _("&Debug") );
|
||||||
|
}
|
||||||
|
|
||||||
SetMenuBar( &m_menubar );
|
SetMenuBar( &m_menubar );
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -507,11 +512,15 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
|
||||||
m_menuMisc.AppendSeparator();
|
m_menuMisc.AppendSeparator();
|
||||||
m_menuMisc.Append( MenuId_ChangeLang, L"Change Language" ); // Always in English
|
m_menuMisc.Append( MenuId_ChangeLang, L"Change Language" ); // Always in English
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifndef PCSX2_DEVBUILD
|
||||||
|
if (g_Conf->EmuOptions.Debugger.EnableDebugger)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
m_menuDebug.Append(MenuId_Debug_Open, _("Open Debug Window..."), wxEmptyString);
|
m_menuDebug.Append(MenuId_Debug_Open, _("Open Debug Window..."), wxEmptyString);
|
||||||
//m_menuDebug.Append(MenuId_Debug_MemoryDump, _("Memory Dump..."), wxEmptyString);
|
//m_menuDebug.Append(MenuId_Debug_MemoryDump, _("Memory Dump..."), wxEmptyString);
|
||||||
m_menuDebug.Append(MenuId_Debug_Logging, _("Logging..."), wxEmptyString);
|
m_menuDebug.Append(MenuId_Debug_Logging, _("Logging..."), wxEmptyString);
|
||||||
#endif
|
}
|
||||||
|
|
||||||
m_MenuItem_Console.Check( g_Conf->ProgLogBox.Visible );
|
m_MenuItem_Console.Check( g_Conf->ProgLogBox.Visible );
|
||||||
|
|
||||||
ConnectMenus();
|
ConnectMenus();
|
||||||
|
|
|
@ -178,6 +178,8 @@
|
||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Devel|Win32'">%(RootDir)%(Directory)\%(Filename).h</Outputs>
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Devel|Win32'">%(RootDir)%(Directory)\%(Filename).h</Outputs>
|
||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(RootDir)%(Directory)\%(Filename).h</Outputs>
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(RootDir)%(Directory)\%(Filename).h</Outputs>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<None Include="..\..\gui\Debugger\DebuggerLists.cpp" />
|
||||||
|
<None Include="..\..\gui\Debugger\DebuggerLists.h" />
|
||||||
<None Include="..\..\Utilities\folderdesc.txt" />
|
<None Include="..\..\Utilities\folderdesc.txt" />
|
||||||
<None Include="..\..\Docs\License.txt" />
|
<None Include="..\..\Docs\License.txt" />
|
||||||
<None Include="..\..\x86\aVUzerorec.S" />
|
<None Include="..\..\x86\aVUzerorec.S" />
|
||||||
|
|
|
@ -207,6 +207,12 @@
|
||||||
<None Include="..\..\gui\Dialogs\BaseConfigurationDialog.inl">
|
<None Include="..\..\gui\Dialogs\BaseConfigurationDialog.inl">
|
||||||
<Filter>AppHost\Dialogs</Filter>
|
<Filter>AppHost\Dialogs</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="..\..\gui\Debugger\DebuggerLists.cpp">
|
||||||
|
<Filter>AppHost\Debugger</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="..\..\gui\Debugger\DebuggerLists.h">
|
||||||
|
<Filter>AppHost\Debugger</Filter>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\Patch.cpp">
|
<ClCompile Include="..\..\Patch.cpp">
|
||||||
|
|
|
@ -424,6 +424,7 @@
|
||||||
<ClCompile Include="..\..\gui\Debugger\CtrlMemView.cpp" />
|
<ClCompile Include="..\..\gui\Debugger\CtrlMemView.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Debugger\CtrlRegisterList.cpp" />
|
<ClCompile Include="..\..\gui\Debugger\CtrlRegisterList.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Debugger\DebugEvents.cpp" />
|
<ClCompile Include="..\..\gui\Debugger\DebugEvents.cpp" />
|
||||||
|
<ClCompile Include="..\..\gui\Debugger\DebuggerLists.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Debugger\DisassemblyDialog.cpp" />
|
<ClCompile Include="..\..\gui\Debugger\DisassemblyDialog.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Dialogs\GameDatabaseDialog.cpp" />
|
<ClCompile Include="..\..\gui\Dialogs\GameDatabaseDialog.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Dialogs\McdConfigDialog.cpp" />
|
<ClCompile Include="..\..\gui\Dialogs\McdConfigDialog.cpp" />
|
||||||
|
@ -708,6 +709,7 @@
|
||||||
<ClInclude Include="..\..\gui\Debugger\CtrlMemView.h" />
|
<ClInclude Include="..\..\gui\Debugger\CtrlMemView.h" />
|
||||||
<ClInclude Include="..\..\gui\Debugger\CtrlRegisterList.h" />
|
<ClInclude Include="..\..\gui\Debugger\CtrlRegisterList.h" />
|
||||||
<ClInclude Include="..\..\gui\Debugger\DebugEvents.h" />
|
<ClInclude Include="..\..\gui\Debugger\DebugEvents.h" />
|
||||||
|
<ClInclude Include="..\..\gui\Debugger\DebuggerLists.h" />
|
||||||
<ClInclude Include="..\..\gui\Debugger\DisassemblyDialog.h" />
|
<ClInclude Include="..\..\gui\Debugger\DisassemblyDialog.h" />
|
||||||
<ClInclude Include="..\..\gui\Panels\MemoryCardPanels.h" />
|
<ClInclude Include="..\..\gui\Panels\MemoryCardPanels.h" />
|
||||||
<ClInclude Include="..\..\IPU\IPUdma.h" />
|
<ClInclude Include="..\..\IPU\IPUdma.h" />
|
||||||
|
|
|
@ -844,13 +844,15 @@
|
||||||
<ClCompile Include="..\..\DebugTools\SymbolMap.cpp">
|
<ClCompile Include="..\..\DebugTools\SymbolMap.cpp">
|
||||||
<Filter>System\Ps2\Debug</Filter>
|
<Filter>System\Ps2\Debug</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\gui\Debugger\DebuggerLists.cpp">
|
||||||
|
<Filter>AppHost\Debugger</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\sif2.cpp">
|
<ClCompile Include="..\..\sif2.cpp">
|
||||||
<Filter>System\Ps2\EmotionEngine\DMAC\Sif</Filter>
|
<Filter>System\Ps2\EmotionEngine\DMAC\Sif</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\Gte.cpp">
|
<ClCompile Include="..\..\Gte.cpp">
|
||||||
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
||||||
</ClCompile>
|
</ClCompile> </ItemGroup>
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\Patch.h">
|
<ClInclude Include="..\..\Patch.h">
|
||||||
<Filter>Misc</Filter>
|
<Filter>Misc</Filter>
|
||||||
|
@ -1255,10 +1257,12 @@
|
||||||
<ClInclude Include="..\..\DebugTools\SymbolMap.h">
|
<ClInclude Include="..\..\DebugTools\SymbolMap.h">
|
||||||
<Filter>System\Ps2\Debug</Filter>
|
<Filter>System\Ps2\Debug</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\gui\Debugger\DebuggerLists.h">
|
||||||
|
<Filter>AppHost\Debugger</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\Gte.h">
|
<ClInclude Include="..\..\Gte.h">
|
||||||
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
||||||
</ClInclude>
|
</ClInclude> </ItemGroup>
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">
|
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">
|
||||||
<Filter>AppHost\Resources</Filter>
|
<Filter>AppHost\Resources</Filter>
|
||||||
|
|
|
@ -424,6 +424,7 @@
|
||||||
<ClCompile Include="..\..\gui\Debugger\CtrlMemView.cpp" />
|
<ClCompile Include="..\..\gui\Debugger\CtrlMemView.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Debugger\CtrlRegisterList.cpp" />
|
<ClCompile Include="..\..\gui\Debugger\CtrlRegisterList.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Debugger\DebugEvents.cpp" />
|
<ClCompile Include="..\..\gui\Debugger\DebugEvents.cpp" />
|
||||||
|
<ClCompile Include="..\..\gui\Debugger\DebuggerLists.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Debugger\DisassemblyDialog.cpp" />
|
<ClCompile Include="..\..\gui\Debugger\DisassemblyDialog.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Dialogs\GameDatabaseDialog.cpp" />
|
<ClCompile Include="..\..\gui\Dialogs\GameDatabaseDialog.cpp" />
|
||||||
<ClCompile Include="..\..\gui\Dialogs\McdConfigDialog.cpp" />
|
<ClCompile Include="..\..\gui\Dialogs\McdConfigDialog.cpp" />
|
||||||
|
@ -708,6 +709,7 @@
|
||||||
<ClInclude Include="..\..\gui\Debugger\CtrlMemView.h" />
|
<ClInclude Include="..\..\gui\Debugger\CtrlMemView.h" />
|
||||||
<ClInclude Include="..\..\gui\Debugger\CtrlRegisterList.h" />
|
<ClInclude Include="..\..\gui\Debugger\CtrlRegisterList.h" />
|
||||||
<ClInclude Include="..\..\gui\Debugger\DebugEvents.h" />
|
<ClInclude Include="..\..\gui\Debugger\DebugEvents.h" />
|
||||||
|
<ClInclude Include="..\..\gui\Debugger\DebuggerLists.h" />
|
||||||
<ClInclude Include="..\..\gui\Debugger\DisassemblyDialog.h" />
|
<ClInclude Include="..\..\gui\Debugger\DisassemblyDialog.h" />
|
||||||
<ClInclude Include="..\..\gui\Panels\MemoryCardPanels.h" />
|
<ClInclude Include="..\..\gui\Panels\MemoryCardPanels.h" />
|
||||||
<ClInclude Include="..\..\IPU\IPUdma.h" />
|
<ClInclude Include="..\..\IPU\IPUdma.h" />
|
||||||
|
|
|
@ -850,7 +850,9 @@
|
||||||
<ClCompile Include="..\..\Gte.cpp">
|
<ClCompile Include="..\..\Gte.cpp">
|
||||||
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
<ClCompile Include="..\..\gui\Debugger\DebuggerLists.cpp">
|
||||||
|
<Filter>AppHost\Debugger</Filter>
|
||||||
|
</ClCompile> </ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\Patch.h">
|
<ClInclude Include="..\..\Patch.h">
|
||||||
<Filter>Misc</Filter>
|
<Filter>Misc</Filter>
|
||||||
|
@ -1258,7 +1260,9 @@
|
||||||
<ClInclude Include="..\..\Gte.h">
|
<ClInclude Include="..\..\Gte.h">
|
||||||
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
<Filter>System\Ps2\Iop\PS1 Components</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
<ClInclude Include="..\..\gui\Debugger\DebuggerLists.h">
|
||||||
|
<Filter>AppHost\Debugger</Filter>
|
||||||
|
</ClInclude> </ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">
|
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">
|
||||||
<Filter>AppHost\Resources</Filter>
|
<Filter>AppHost\Resources</Filter>
|
||||||
|
|
|
@ -1271,20 +1271,76 @@ int cop2flags(u32 code)
|
||||||
void dynarecCheckBreakpoint()
|
void dynarecCheckBreakpoint()
|
||||||
{
|
{
|
||||||
u32 pc = cpuRegs.pc;
|
u32 pc = cpuRegs.pc;
|
||||||
if (CBreakPoints::CheckSkipFirst(pc))
|
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||||
{
|
|
||||||
CBreakPoints::SetSkipFirst(0xFFFFFFFF);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
auto cond = CBreakPoints::GetBreakPointCondition(pc);
|
auto cond = CBreakPoints::GetBreakPointCondition(pc);
|
||||||
if (cond && !cond->Evaluate())
|
if (cond && !cond->Evaluate())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
CBreakPoints::SetBreakpointTriggered(true);
|
||||||
GetCoreThread().PauseSelf();
|
GetCoreThread().PauseSelf();
|
||||||
recExitExecution();
|
recExitExecution();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dynarecMemcheck()
|
||||||
|
{
|
||||||
|
u32 pc = cpuRegs.pc;
|
||||||
|
if (CBreakPoints::CheckSkipFirst(pc) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
iFlushCall(FLUSH_INTERPRETER);
|
||||||
|
CBreakPoints::SetBreakpointTriggered(true);
|
||||||
|
GetCoreThread().PauseSelf();
|
||||||
|
recExitExecution();
|
||||||
|
}
|
||||||
|
|
||||||
|
void recMemcheck(u32 bits, bool store)
|
||||||
|
{
|
||||||
|
iFlushCall(FLUSH_INTERPRETER);
|
||||||
|
|
||||||
|
// compute accessed address
|
||||||
|
_eeMoveGPRtoR(ECX, _Rs_);
|
||||||
|
if (_Imm_ != 0)
|
||||||
|
xADD(ecx, _Imm_);
|
||||||
|
if (bits == 128)
|
||||||
|
xAND(ecx, ~0x0F);
|
||||||
|
|
||||||
|
xMOV(edx,ecx);
|
||||||
|
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].cond & MEMCHECK_BREAK) == 0)
|
||||||
|
continue;
|
||||||
|
if ((checks[i].cond & MEMCHECK_WRITE) == 0 && store == true)
|
||||||
|
continue;
|
||||||
|
if ((checks[i].cond & MEMCHECK_READ) == 0 && store == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// logic: memAddress < bpEnd && bpStart < memAddress+memSize
|
||||||
|
|
||||||
|
xMOV(eax,checks[i].end);
|
||||||
|
xCMP(ecx,eax); // address < end
|
||||||
|
xForwardJGE8 next1; // if address >= end then goto next1
|
||||||
|
|
||||||
|
xMOV(eax,checks[i].start);
|
||||||
|
xCMP(eax,edx); // start < address+size
|
||||||
|
xForwardJGE8 next2; // if start >= address+size then goto next2
|
||||||
|
|
||||||
|
// hit the breakpoint
|
||||||
|
xCALL(&dynarecMemcheck);
|
||||||
|
|
||||||
|
next1.SetTarget();
|
||||||
|
next2.SetTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void recompileNextInstruction(int delayslot)
|
void recompileNextInstruction(int delayslot)
|
||||||
{
|
{
|
||||||
static u8 s_bFlushReg = 1;
|
static u8 s_bFlushReg = 1;
|
||||||
|
@ -1304,6 +1360,54 @@ void recompileNextInstruction(int delayslot)
|
||||||
MOV32ItoR(EAX, pc); // acts as a tag for delimiting recompiled instructions when viewing x86 disasm.
|
MOV32ItoR(EAX, pc); // acts as a tag for delimiting recompiled instructions when viewing x86 disasm.
|
||||||
|
|
||||||
cpuRegs.code = *(int *)s_pCode;
|
cpuRegs.code = *(int *)s_pCode;
|
||||||
|
|
||||||
|
if (CBreakPoints::GetMemChecks().size() != 0)
|
||||||
|
{
|
||||||
|
switch (cpuRegs.code >> 26)
|
||||||
|
{
|
||||||
|
case 0x20: // lb
|
||||||
|
case 0x24: // lbu
|
||||||
|
recMemcheck(8,false);
|
||||||
|
break;
|
||||||
|
case 0x28: // sb
|
||||||
|
recMemcheck(8,true);
|
||||||
|
break;
|
||||||
|
case 0x21: // lh
|
||||||
|
case 0x25: // lhu
|
||||||
|
recMemcheck(16,false);
|
||||||
|
break;
|
||||||
|
case 0x22: // lwl
|
||||||
|
case 0x23: // lw
|
||||||
|
case 0x26: // lwr
|
||||||
|
recMemcheck(32,false);
|
||||||
|
break;
|
||||||
|
case 0x29: // sh
|
||||||
|
recMemcheck(16,true);
|
||||||
|
break;
|
||||||
|
case 0x2A: // swl
|
||||||
|
case 0x2B: // sw
|
||||||
|
case 0x2E: // swr
|
||||||
|
recMemcheck(32,true);
|
||||||
|
break;
|
||||||
|
case 0x37: // ld
|
||||||
|
case 0x1B: // ldr
|
||||||
|
case 0x1A: // ldl
|
||||||
|
recMemcheck(64,false);
|
||||||
|
break;
|
||||||
|
case 0x3F: // sd
|
||||||
|
case 0x3D: // sdr
|
||||||
|
case 0x2C: // sdl
|
||||||
|
recMemcheck(64,true);
|
||||||
|
break;
|
||||||
|
case 0x1E: // lq
|
||||||
|
recMemcheck(128,false);
|
||||||
|
break;
|
||||||
|
case 0x1F: // sq
|
||||||
|
recMemcheck(128,true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!delayslot) {
|
if (!delayslot) {
|
||||||
pc += 4;
|
pc += 4;
|
||||||
g_cpuFlushedPC = false;
|
g_cpuFlushedPC = false;
|
||||||
|
@ -1554,6 +1658,44 @@ bool skipMPEG_By_Pattern(u32 sPC) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool needsBreakpoint(u32 pc)
|
||||||
|
{
|
||||||
|
if (CBreakPoints::IsAddressBreakPoint(pc))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (CBreakPoints::GetMemChecks().size() == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
u32 op = memRead32(pc);
|
||||||
|
|
||||||
|
switch (op >> 26)
|
||||||
|
{
|
||||||
|
case 0x20: // lb
|
||||||
|
case 0x21: // lh
|
||||||
|
case 0x22: // lwl
|
||||||
|
case 0x23: // lw
|
||||||
|
case 0x24: // lbu
|
||||||
|
case 0x25: // lhu
|
||||||
|
case 0x26: // lwr
|
||||||
|
case 0x28: // sb
|
||||||
|
case 0x29: // sh
|
||||||
|
case 0x2A: // swl
|
||||||
|
case 0x2B: // sw
|
||||||
|
case 0x2E: // swr
|
||||||
|
case 0x37: // ld
|
||||||
|
case 0x1B: // ldr
|
||||||
|
case 0x3F: // sd
|
||||||
|
case 0x3D: // sdr
|
||||||
|
case 0x1A: // ldl
|
||||||
|
case 0x2C: // sdl
|
||||||
|
case 0x1E: // lq
|
||||||
|
case 0x1F: // sq
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void __fastcall recRecompile( const u32 startpc )
|
static void __fastcall recRecompile( const u32 startpc )
|
||||||
{
|
{
|
||||||
u32 i = 0;
|
u32 i = 0;
|
||||||
|
@ -1634,7 +1776,7 @@ static void __fastcall recRecompile( const u32 startpc )
|
||||||
s_branchTo = -1;
|
s_branchTo = -1;
|
||||||
|
|
||||||
// compile breakpoints as individual blocks
|
// compile breakpoints as individual blocks
|
||||||
if (CBreakPoints::IsAddressBreakPoint(i))
|
if (needsBreakpoint(i))
|
||||||
{
|
{
|
||||||
s_nEndBlock = i + 4;
|
s_nEndBlock = i + 4;
|
||||||
goto StartRecomp;
|
goto StartRecomp;
|
||||||
|
@ -1644,7 +1786,7 @@ static void __fastcall recRecompile( const u32 startpc )
|
||||||
BASEBLOCK* pblock = PC_GETBLOCK(i);
|
BASEBLOCK* pblock = PC_GETBLOCK(i);
|
||||||
|
|
||||||
// stop before breakpoints
|
// stop before breakpoints
|
||||||
if (CBreakPoints::IsAddressBreakPoint(i))
|
if (needsBreakpoint(i))
|
||||||
{
|
{
|
||||||
s_nEndBlock = i;
|
s_nEndBlock = i;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue