Fixed single stepping, added support for vCont packets and ranged stepping (faster), initial work to support other breakpoint types
This commit is contained in:
parent
0107435a73
commit
13f3c8281f
|
@ -85,11 +85,20 @@ public:
|
|||
|
||||
void step()
|
||||
{
|
||||
bool restoreBreakpoint = removeMatchpoint(0, Sh4cntx.pc, 2);
|
||||
bool restoreBreakpoint = removeMatchpoint(Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK, Sh4cntx.pc, 2);
|
||||
u32 savedPc = Sh4cntx.pc;
|
||||
emu.step();
|
||||
if (restoreBreakpoint)
|
||||
insertMatchpoint(0, savedPc, 2);
|
||||
insertMatchpoint(Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK, savedPc, 2);
|
||||
}
|
||||
|
||||
void stepRange(u32 from, u32 to)
|
||||
{
|
||||
bool restoreBreakpoint = removeMatchpoint(Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK, Sh4cntx.pc, 2);
|
||||
u32 savedPc = Sh4cntx.pc;
|
||||
emu.stepRange(from, to);
|
||||
if (restoreBreakpoint)
|
||||
insertMatchpoint(Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK, savedPc, 2);
|
||||
}
|
||||
|
||||
int readAllRegs(u32 **regs)
|
||||
|
@ -200,10 +209,10 @@ public:
|
|||
return false;
|
||||
}
|
||||
// TODO other matchpoint types
|
||||
if (breakpoints.find(addr) != breakpoints.end())
|
||||
if (breakpoints[type].find(addr) != breakpoints[type].end())
|
||||
return true;
|
||||
breakpoints[addr] = Breakpoint(type, addr);
|
||||
breakpoints[addr].savedOp = ReadMem16_nommu(addr);
|
||||
breakpoints[type][addr] = Breakpoint(type, addr);
|
||||
breakpoints[type][addr].savedOp = ReadMem16_nommu(addr);
|
||||
WriteMem16_nommu(addr, 0xC308); // trapa #0x20
|
||||
return true;
|
||||
}
|
||||
|
@ -213,11 +222,11 @@ public:
|
|||
WARN_LOG(COMMON, "removeMatchpoint: length != 2: %d", len);
|
||||
return false;
|
||||
}
|
||||
auto it = breakpoints.find(addr);
|
||||
if (it == breakpoints.end())
|
||||
auto it = breakpoints[type].find(addr);
|
||||
if (it == breakpoints[type].end())
|
||||
return false;
|
||||
WriteMem16_nommu(addr, it->second.savedOp);
|
||||
breakpoints.erase(it);
|
||||
breakpoints[type].erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -319,12 +328,22 @@ public:
|
|||
u32 exception = 0;
|
||||
|
||||
struct Breakpoint {
|
||||
enum Type
|
||||
{
|
||||
BP_TYPE_SOFTWARE_BREAK,
|
||||
BP_TYPE_HARDWARE_BREAK,
|
||||
BP_TYPE_WRITE_WATCHPOINT,
|
||||
BP_TYPE_READ_WATCHPOINT,
|
||||
BP_TYPE_ACCESS_WATCHPOINT,
|
||||
BP_TYPE_COUNT
|
||||
};
|
||||
|
||||
Breakpoint() = default;
|
||||
Breakpoint(u16 type, u32 addr) : addr(addr), type(type) { }
|
||||
u32 addr = 0;
|
||||
u16 type = 0;
|
||||
u16 savedOp = 0;
|
||||
};
|
||||
std::map<u32, Breakpoint> breakpoints;
|
||||
std::map<u32, Breakpoint> breakpoints[Breakpoint::Type::BP_TYPE_COUNT];
|
||||
std::vector<std::pair<u32, u32>> stack;
|
||||
};
|
||||
|
|
|
@ -535,9 +535,13 @@ private:
|
|||
sendPacket("");
|
||||
}
|
||||
else if (pkt.rfind("qSupported", 0) == 0)
|
||||
{
|
||||
// Tell the remote stub about features supported by GDB,
|
||||
// and query the stub for features it supports
|
||||
sendPacket("PacketSize=10000");
|
||||
char qsupported[128];
|
||||
sprintf_s(qsupported, 128, "PacketSize=%i;vContSupported+", MAX_PACKET_LEN);
|
||||
sendPacket(qsupported);
|
||||
}
|
||||
else if (pkt.rfind("qSymbol:", 0) == 0)
|
||||
// Notify the target that GDB is prepared to serve symbol lookup requests
|
||||
sendPacket("OK");
|
||||
|
@ -590,11 +594,41 @@ private:
|
|||
if (pkt.rfind("vAttach;", 0) == 0)
|
||||
sendPacket("S05");
|
||||
else if (pkt.rfind("vCont?", 0) == 0)
|
||||
// not supported
|
||||
sendPacket("vCont;s;c");
|
||||
// supported vCont actions - (c)ontinue, (C)ontinue with signal, (s)tep, (S)tep with signal, (r)ange-step
|
||||
sendPacket("vCont;c;C;s;S;t;r");
|
||||
else if (pkt.rfind("vCont", 0) == 0)
|
||||
// not supported
|
||||
WARN_LOG(COMMON, "vCont not supported %s", pkt.c_str());
|
||||
{
|
||||
std::string vContCmd = pkt.substr(strlen("vCont;"));
|
||||
switch (vContCmd[0])
|
||||
{
|
||||
case 'c':
|
||||
case 'C':
|
||||
sendContinue(vContCmd);
|
||||
break;
|
||||
case 's':
|
||||
step(EXCEPT_NONE);
|
||||
break;
|
||||
case 'S':
|
||||
step();
|
||||
case 'r':
|
||||
{
|
||||
u32 from, to;
|
||||
if (sscanf(vContCmd.c_str(), "r%x,%x", &from, &to) == 2)
|
||||
{
|
||||
stepRange(from, to);
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN_LOG(COMMON, "Unsupported vCont:r format %s", pkt.c_str());
|
||||
sendContinue("c");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WARN_LOG(COMMON, "vCont action not supported %s", pkt[6], pkt.c_str());
|
||||
}
|
||||
}
|
||||
else if (pkt.rfind("vFile:", 0) == 0)
|
||||
// not supported
|
||||
sendPacket("");
|
||||
|
@ -637,6 +671,13 @@ private:
|
|||
sendPacket("S05");
|
||||
}
|
||||
|
||||
void stepRange(u32 from, u32 to)
|
||||
{
|
||||
sendPacket("OK");
|
||||
agent.stepRange(from, to);
|
||||
sendPacket("S05");
|
||||
}
|
||||
|
||||
void insertMatchpoint(const std::string& pkt)
|
||||
{
|
||||
u32 type;
|
||||
|
@ -647,22 +688,22 @@ private:
|
|||
sendPacket("E01");
|
||||
}
|
||||
switch (type) {
|
||||
case 0: // soft bp
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_SOFTWARE_BREAK: // soft bp
|
||||
if (agent.insertMatchpoint(0, addr, len))
|
||||
sendPacket("OK");
|
||||
else
|
||||
sendPacket("E01");
|
||||
break;
|
||||
case 1: // hardware bp
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_HARDWARE_BREAK: // hardware bp
|
||||
sendPacket("");
|
||||
break;
|
||||
case 2: // write watchpoint
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_WRITE_WATCHPOINT: // write watchpoint
|
||||
sendPacket("");
|
||||
break;
|
||||
case 3: // read watchpoint
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_READ_WATCHPOINT: // read watchpoint
|
||||
sendPacket("");
|
||||
break;
|
||||
case 4: // access watchpoint
|
||||
case DebugAgent::Breakpoint::Type::BP_TYPE_ACCESS_WATCHPOINT: // access watchpoint
|
||||
sendPacket("");
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -587,8 +587,16 @@ void Emulator::runInternal()
|
|||
{
|
||||
if (singleStep)
|
||||
{
|
||||
singleStep = false;
|
||||
sh4_cpu.Step();
|
||||
singleStep = false;
|
||||
}
|
||||
else if(stepRangeTo != 0)
|
||||
{
|
||||
while (Sh4cntx.pc >= stepRangeFrom && Sh4cntx.pc <= stepRangeTo)
|
||||
sh4_cpu.Step();
|
||||
|
||||
stepRangeFrom = 0;
|
||||
stepRangeTo = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -652,7 +660,8 @@ void Emulator::stop() {
|
|||
rend_cancel_emu_wait();
|
||||
try {
|
||||
auto future = threadResult;
|
||||
future.get();
|
||||
if(future.valid())
|
||||
future.get();
|
||||
} catch (const FlycastException& e) {
|
||||
WARN_LOG(COMMON, "%s", e.what());
|
||||
}
|
||||
|
@ -719,6 +728,14 @@ void Emulator::step()
|
|||
stop();
|
||||
}
|
||||
|
||||
void Emulator::stepRange(u32 from, u32 to)
|
||||
{
|
||||
stepRangeFrom = from;
|
||||
stepRangeTo = to;
|
||||
start();
|
||||
stop();
|
||||
}
|
||||
|
||||
void dc_loadstate(Deserializer& deser)
|
||||
{
|
||||
custom_texture.Terminate();
|
||||
|
@ -826,7 +843,7 @@ void Emulator::start()
|
|||
InitAudio();
|
||||
|
||||
try {
|
||||
while (state == Running)
|
||||
while (state == Running || singleStep || stepRangeTo != 0)
|
||||
{
|
||||
startTime = sh4_sched_now64();
|
||||
renderTimeout = false;
|
||||
|
@ -855,9 +872,13 @@ void Emulator::start()
|
|||
bool Emulator::checkStatus()
|
||||
{
|
||||
try {
|
||||
if (threadResult.wait_for(std::chrono::seconds(0)) == std::future_status::timeout)
|
||||
return true;
|
||||
threadResult.get();
|
||||
if (threadResult.valid())
|
||||
{
|
||||
auto result = threadResult.wait_for(std::chrono::seconds(0));
|
||||
if (result == std::future_status::timeout)
|
||||
return true;
|
||||
threadResult.get();
|
||||
}
|
||||
return false;
|
||||
} catch (...) {
|
||||
EventManager::event(Event::Pause);
|
||||
|
|
|
@ -130,6 +130,10 @@ public:
|
|||
* Execute a single instruction.
|
||||
*/
|
||||
void step();
|
||||
/**
|
||||
* Execute instructions while PC is with range.
|
||||
*/
|
||||
void stepRange(u32 from, u32 to);
|
||||
/**
|
||||
* Return whether the emulator is currently running.
|
||||
*/
|
||||
|
@ -171,6 +175,8 @@ private:
|
|||
bool singleStep = false;
|
||||
u64 startTime = 0;
|
||||
bool renderTimeout = false;
|
||||
u32 stepRangeFrom = 0;
|
||||
u32 stepRangeTo = 0;
|
||||
};
|
||||
extern Emulator emu;
|
||||
|
||||
|
|
Loading…
Reference in New Issue