Update to v073r07 release.

byuu says:

I give up for now. This WIP doesn't really improve uPD any, but it does
have major fixes to the debugger.
Debugger is still Linux-only for want of a HexEditor widget, but the
Linux one is now usable.
Before it'd trace and search for breakpoint at sub-1fps. Fixed it to not
break out of core for simple things and it'll run at near-fullspeed for
BPs, half-speed for tracing to file (lots of I/O.)
This commit is contained in:
Tim Allen 2011-01-10 23:21:57 +11:00
parent 73113da41e
commit 92da6bde26
15 changed files with 70 additions and 69 deletions

View File

@ -7,11 +7,21 @@ namespace SNES {
#include "serialization.cpp" #include "serialization.cpp"
void uPDcore::exec() { void uPDcore::exec() {
//static uint16 lastpc = 0xffff; #if 0
//if(lastpc != regs.pc) { static uint16 lastpc = 0xffff;
// print("A:", hex<4>((uint16)regs.a), " B:", hex<4>((uint16)regs.b), " DR:", hex<4>(regs.dr), " SR:", hex<4>(regs.sr), " FA:", hex<2>(regs.flaga), " FB:", hex<2>(regs.flagb), "\n"); if(lastpc != regs.pc) {
// print(disassemble(lastpc = regs.pc), "\n"); print(
//} "A:", hex<4>((uint16)regs.a), " B:", hex<4>((uint16)regs.b),
" DR:", hex<4>(regs.dr), " SR:", hex<4>(regs.sr),
" FA:", hex<2>(regs.flaga), " FB:", hex<2>(regs.flagb),
" RP:", hex<4>(regs.rp), " DP:", hex<4>(regs.dp), " SO:", hex<4>(regs.so), "\n",
"K: ", hex<4>((uint16)regs.k), " L:", hex<4>((uint16)regs.l),
" M:", hex<4>((uint16)regs.m), " N:", hex<4>((uint16)regs.n),
" TR:", hex<4>(regs.tr), " TRB:", hex<4>(regs.trb), " [DP15]:", hex<4>(dataRAM[0x15]), "\n"
);
print(disassemble(lastpc = regs.pc), "\n");
}
#endif
uint24 opcode = programROM[regs.pc]; uint24 opcode = programROM[regs.pc];
regs.pc = regs.pc + 1; regs.pc = regs.pc + 1;
@ -163,9 +173,6 @@ void uPDcore::exec_jp(uint24 opcode) {
uint16 jps = (regs.pc & 0x3800) | (na << 0); uint16 jps = (regs.pc & 0x3800) | (na << 0);
uint16 jpl = (regs.pc & 0x2000) | (bank << 11) | (na << 0); uint16 jpl = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
bool lj = false;
ljmp:
switch(brch) { switch(brch) {
case 0x080: if(regs.flaga.c == 0) regs.pc = jps; return; //JNCA case 0x080: if(regs.flaga.c == 0) regs.pc = jps; return; //JNCA
case 0x082: if(regs.flaga.c == 1) regs.pc = jps; return; //JCA case 0x082: if(regs.flaga.c == 1) regs.pc = jps; return; //JCA
@ -209,24 +216,14 @@ void uPDcore::exec_jp(uint24 opcode) {
case 0x140: stack_push(); regs.pc = jps; return; //CALL case 0x140: stack_push(); regs.pc = jps; return; //CALL
} }
if(brch == 0x000) { switch(brch) {
regs.pc = regs.so; case 0x000: regs.pc = regs.so; return;
return;
case 0x081: if(regs.flaga.c == 1) regs.pc = jpl; return;
case 0x0bf: if(regs.sr.rqm == 1) regs.pc = jpl; return;
} }
if(lj == false) {
lj = true;
brch &= ~1;
jps = jpl;
goto ljmp;
}
/*switch(brch) {
case 0x081: if(regs.flaga.c == 0) regs.pc = jpl; return; //LJNCA
case 0x0bf: if(regs.sr.rqm == 1) regs.pc = jpl; return; //LJRQM
}*/
print(hex<4>(regs.pc - 1), ": unknown jump ", hex<3>(brch), "\n"); print(hex<4>(regs.pc - 1), ": unknown jump ", hex<3>(brch), "\n");
/*bool r = false; /*bool r = false;

View File

@ -8,13 +8,11 @@ void CPUDebugger::op_step() {
opcode_pc = regs.pc; opcode_pc = regs.pc;
opcode_edge = true; opcode_edge = true;
if(debugger.step_cpu) { debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
if(step_event && step_event() == true) {
debugger.break_event = Debugger::BreakEvent::CPUStep; debugger.break_event = Debugger::BreakEvent::CPUStep;
scheduler.exit(Scheduler::ExitReason::DebuggerEvent); scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
} else {
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
} }
if(step_event) step_event();
opcode_edge = false; opcode_edge = false;
CPU::op_step(); CPU::op_step();

View File

@ -2,7 +2,7 @@ class CPUDebugger : public CPU, public ChipDebugger {
public: public:
bool property(unsigned id, string &name, string &value); bool property(unsigned id, string &name, string &value);
function<void ()> step_event; function<bool ()> step_event;
enum Usage { enum Usage {
UsageRead = 0x80, UsageRead = 0x80,

View File

@ -103,9 +103,6 @@ Debugger::Debugger() {
breakpoint[n].counter = 0; breakpoint[n].counter = 0;
} }
breakpoint_hit = 0; breakpoint_hit = 0;
step_cpu = false;
step_smp = false;
} }
#endif #endif

View File

@ -19,9 +19,6 @@ public:
unsigned breakpoint_hit; unsigned breakpoint_hit;
void breakpoint_test(Breakpoint::Source source, Breakpoint::Mode mode, unsigned addr, uint8 data); void breakpoint_test(Breakpoint::Source source, Breakpoint::Mode mode, unsigned addr, uint8 data);
bool step_cpu;
bool step_smp;
enum class MemorySource : unsigned { CPUBus, APUBus, APURAM, VRAM, OAM, CGRAM }; enum class MemorySource : unsigned { CPUBus, APUBus, APURAM, VRAM, OAM, CGRAM };
uint8 read(MemorySource, unsigned addr); uint8 read(MemorySource, unsigned addr);
void write(MemorySource, unsigned addr, uint8 data); void write(MemorySource, unsigned addr, uint8 data);

View File

@ -7,13 +7,11 @@ void SMPDebugger::op_step() {
opcode_pc = regs.pc; opcode_pc = regs.pc;
opcode_edge = true; opcode_edge = true;
if(debugger.step_smp) { debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
if(step_event && step_event() == true) {
debugger.break_event = Debugger::BreakEvent::SMPStep; debugger.break_event = Debugger::BreakEvent::SMPStep;
scheduler.exit(Scheduler::ExitReason::DebuggerEvent); scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
} else {
debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
} }
if(step_event) step_event();
opcode_edge = false; opcode_edge = false;
SMP::op_step(); SMP::op_step();

View File

@ -2,7 +2,7 @@ class SMPDebugger : public SMP, public ChipDebugger {
public: public:
bool property(unsigned id, string &name, string &value); bool property(unsigned id, string &name, string &value);
function<void ()> step_event; function<bool ()> step_event;
enum Usage { enum Usage {
UsageRead = 0x80, UsageRead = 0x80,

View File

@ -1,7 +1,7 @@
namespace SNES { namespace SNES {
namespace Info { namespace Info {
static const char Name[] = "bsnes"; static const char Name[] = "bsnes";
static const char Version[] = "073.06"; static const char Version[] = "073.07";
static const unsigned SerializerVersion = 16; static const unsigned SerializerVersion = 16;
} }
} }

View File

@ -33,12 +33,13 @@ void Console::create() {
}; };
} }
void Console::write(const string &text) { void Console::write(const string &text, bool echo) {
if(traceToConsole.checked()) { if(traceToConsole.checked() || echo) {
if(buffer != "") buffer.append("\n"); if(buffer != "") buffer.append("\n");
buffer.append(text); buffer.append(text);
output.setText(buffer); output.setText(buffer);
output.setCursorPosition(~0); output.setCursorPosition(~0);
OS::run();
} }
if(traceToFile.checked() && logfile.open()) { if(traceToFile.checked() && logfile.open()) {
logfile.print(string(text, "\n")); logfile.print(string(text, "\n"));
@ -55,20 +56,21 @@ void Console::tracerEnable(bool state) {
} }
void Console::eventBreakpoint() { void Console::eventBreakpoint() {
if(traceToConsole.checked() == false) return;
unsigned n = SNES::debugger.breakpoint_hit; unsigned n = SNES::debugger.breakpoint_hit;
write({ "Breakpoint ", n + 1, " hit." }); write({ "Breakpoint ", n + 1, " hit." }, true);
if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::CPUBus) { if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::CPUBus) {
eventTraceCPU(); eventTraceCPU();
cpuDebugger.refreshDisassembly();
} else if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::APURAM) { } else if(SNES::debugger.breakpoint[n].source == SNES::Debugger::Breakpoint::Source::APURAM) {
eventTraceSMP(); eventTraceSMP();
smpDebugger.refreshDisassembly();
} }
} }
void Console::eventTraceCPU() { void Console::eventTraceCPU() {
if(traceCPU.checked() == false) return; if(traceCPU.checked() == false) return;
if(traceToConsole.checked() == false && traceToFile.checked() == false) return;
char text[256]; char text[256];
SNES::cpu.disassemble_opcode(text, SNES::cpu.regs.pc); SNES::cpu.disassemble_opcode(text, SNES::cpu.regs.pc);
@ -77,6 +79,7 @@ void Console::eventTraceCPU() {
void Console::eventTraceSMP() { void Console::eventTraceSMP() {
if(traceSMP.checked() == false) return; if(traceSMP.checked() == false) return;
if(traceToConsole.checked() == false && traceToFile.checked() == false) return;
char text[256]; char text[256];
SNES::smp.disassemble_opcode(text, SNES::smp.regs.pc); SNES::smp.disassemble_opcode(text, SNES::smp.regs.pc);

View File

@ -10,7 +10,7 @@ struct Console : TopLevelWindow {
file logfile; file logfile;
void create(); void create();
void write(const string &text); void write(const string &text, bool echo = false);
void tracerEnable(bool state); void tracerEnable(bool state);
void eventBreakpoint(); void eventBreakpoint();
void eventTraceCPU(); void eventTraceCPU();

View File

@ -29,7 +29,7 @@ void CPUDebugger::create() {
} }
void CPUDebugger::synchronize() { void CPUDebugger::synchronize() {
stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked()); stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked() && breakpointEditor.runToBreakpoint.checked() == false);
stepOver.setEnabled(stepInto.enabled() && SNES::cpu.opcode_edge); stepOver.setEnabled(stepInto.enabled() && SNES::cpu.opcode_edge);
} }

View File

@ -85,13 +85,10 @@ void Debugger::setVisible(bool visible) {
void Debugger::enable(bool state) { void Debugger::enable(bool state) {
enableDebugger.setChecked(state); enableDebugger.setChecked(state);
SNES::debugger.step_cpu = state; synchronize();
SNES::debugger.step_smp = state;
} }
void Debugger::run() { void Debugger::run() {
synchronize();
if(enableDebugger.checked() == false) { if(enableDebugger.checked() == false) {
SNES::system.run(); SNES::system.run();
return; return;
@ -109,30 +106,41 @@ void Debugger::run() {
debugMode = DebugMode::None; debugMode = DebugMode::None;
console.eventBreakpoint(); console.eventBreakpoint();
breakpointEditor.eventBreakpoint(); breakpointEditor.eventBreakpoint();
synchronize();
} }
} }
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::CPUStep) {
if(debugMode == DebugMode::StepIntoCPU) {
debugMode = DebugMode::None;
cpuDebugger.eventStepInto();
}
console.eventTraceCPU();
}
if(SNES::debugger.break_event == SNES::Debugger::BreakEvent::SMPStep) {
if(debugMode == DebugMode::StepIntoSMP) {
debugMode = DebugMode::None;
smpDebugger.eventStepInto();
}
console.eventTraceSMP();
}
SNES::debugger.break_event = SNES::Debugger::BreakEvent::None; SNES::debugger.break_event = SNES::Debugger::BreakEvent::None;
} }
bool Debugger::step_cpu() {
if(enableDebugger.checked() == false) return false;
console.eventTraceCPU();
if(debugMode == DebugMode::StepIntoCPU) {
debugMode = DebugMode::None;
cpuDebugger.eventStepInto();
synchronize();
return true;
}
return false;
}
bool Debugger::step_smp() {
if(enableDebugger.checked() == false) return false;
console.eventTraceSMP();
if(debugMode == DebugMode::StepIntoSMP) {
debugMode = DebugMode::None;
smpDebugger.eventStepInto();
synchronize();
return true;
}
return false;
}
Debugger::Debugger() { Debugger::Debugger() {
debugMode = DebugMode::None; debugMode = DebugMode::None;
SNES::cpu.step_event = { &Debugger::step_cpu, this };
SNES::smp.step_event = { &Debugger::step_smp, this };
} }
#endif #endif

View File

@ -24,6 +24,8 @@ struct Debugger : TopLevelWindow {
void setVisible(bool visible = true); void setVisible(bool visible = true);
void enable(bool state); void enable(bool state);
void run(); void run();
bool step_cpu();
bool step_smp();
Debugger(); Debugger();
}; };

View File

@ -29,7 +29,7 @@ void SMPDebugger::create() {
} }
void SMPDebugger::synchronize() { void SMPDebugger::synchronize() {
stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked()); stepInto.setEnabled(SNES::cartridge.loaded() && debugger.enableDebugger.checked() && breakpointEditor.runToBreakpoint.checked() == false);
stepOver.setEnabled(stepInto.enabled() && SNES::smp.opcode_edge); stepOver.setEnabled(stepInto.enabled() && SNES::smp.opcode_edge);
} }

View File

@ -28,6 +28,7 @@ void BreakpointEditor::create() {
} else { } else {
debugger.debugMode = Debugger::DebugMode::None; debugger.debugMode = Debugger::DebugMode::None;
} }
debugger.synchronize();
}; };
} }