Skip to content

Commit

Permalink
Work on Breakpoint / Watchpoint API
Browse files Browse the repository at this point in the history
  • Loading branch information
dirkwhoffmann committed May 31, 2024
1 parent 47b32dd commit 236b9d2
Show file tree
Hide file tree
Showing 16 changed files with 524 additions and 266 deletions.
53 changes: 51 additions & 2 deletions Emulator/Base/CmdQueueTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,37 @@ enum_long(CMD_TYPE)
CMD_ALARM_ABS, ///< Schedule an alarm (absolute cycle)
CMD_ALARM_REL, ///< Schedule an alarm (relative cycle)
CMD_INSPECTION_TARGET, ///< Sets the auto-inspection component

// CPU
CMD_CPU_BRK, ///< Let the CPU execute a BRK instruction
CMD_CPU_NMI, ///< Emulate an external expansion port NMI

// CPU (Breakpoints)
CMD_BP_SET_AT, ///< Set a breakpoint
CMD_BP_MOVE_TO, ///< Change the address of breakpoint
CMD_BP_REMOVE_NR, ///< Remove the n-th breakpoint
CMD_BP_REMOVE_AT, ///< Remove the breakpoint at an address
CMD_BP_REMOVE_ALL, ///< Remove all brekpoints
CMD_BP_ENABLE_NR, ///< Enable the n-th breakpoint
CMD_BP_ENABLE_AT, ///< Enable the breakpoint at an address
CMD_BP_ENABLE_ALL, ///< Enable all brekpoints
CMD_BP_DISABLE_NR, ///< Disable the n-th breakpoint
CMD_BP_DISABLE_AT, ///< Disable the breakpoint at an address
CMD_BP_DISABLE_ALL, ///< Disable all brekpoints

// CPU (Watchpoints)
CMD_WP_SET_AT, ///< Set a watchpoint
CMD_WP_MOVE_TO, ///< Change the address of watchpoint
CMD_WP_REMOVE_NR, ///< Remove the n-th watchpoint
CMD_WP_REMOVE_AT, ///< Remove the watchpoint at an address
CMD_WP_REMOVE_ALL, ///< Remove all watchpoints
CMD_WP_ENABLE_NR, ///< Enable the n-th watchpoint
CMD_WP_ENABLE_AT, ///< Enable the watchpoint at an address
CMD_WP_ENABLE_ALL, ///< Enable all watchpoints
CMD_WP_DISABLE_NR, ///< Disable the n-th watchpoint
CMD_WP_DISABLE_AT, ///< Disable the watchpoint at an address
CMD_WP_DISABLE_ALL, ///< Disable all watchpoints

// Keyboard
CMD_KEY_PRESS, ///< Press a key on the C64 keyboard
CMD_KEY_RELEASE, ///< Release a key on the C64 keyboard
Expand Down Expand Up @@ -101,6 +128,28 @@ struct CmdTypeEnum : util::Reflection<CmdType, CmdType> {
case CMD_CPU_BRK: return "CPU_BRK";
case CMD_CPU_NMI: return "CPU_NMI";

case CMD_BP_SET_AT: return "BP_SET_AT";
case CMD_BP_REMOVE_NR: return "BP_REMOVE_NR";
case CMD_BP_REMOVE_AT: return "BP_REMOVE_AT";
case CMD_BP_REMOVE_ALL: return "BP_REMOVE_ALL";
case CMD_BP_ENABLE_NR: return "BP_ENABLE_NR";
case CMD_BP_ENABLE_AT: return "BP_ENABLE_AT";
case CMD_BP_ENABLE_ALL: return "BP_ENABLE_ALL";
case CMD_BP_DISABLE_NR: return "BP_DISABLE_NR";
case CMD_BP_DISABLE_AT: return "BP_DISABLE_AT";
case CMD_BP_DISABLE_ALL: return "BP_DISABLE_ALL";

case CMD_WP_SET_AT: return "WP_SET_AT";
case CMD_WP_REMOVE_NR: return "WP_REMOVE_NR";
case CMD_WP_REMOVE_AT: return "WP_REMOVE_AT";
case CMD_WP_REMOVE_ALL: return "WP_REMOVE_ALL";
case CMD_WP_ENABLE_NR: return "WP_ENABLE_NR";
case CMD_WP_ENABLE_AT: return "WP_ENABLE_AT";
case CMD_WP_ENABLE_ALL: return "WP_ENABLE_ALL";
case CMD_WP_DISABLE_NR: return "WP_DISABLE_NR";
case CMD_WP_DISABLE_AT: return "WP_DISABLE_AT";
case CMD_WP_DISABLE_ALL: return "WP_DISABLE_ALL";

case CMD_KEY_PRESS: return "KEY_PRESS";
case CMD_KEY_RELEASE: return "KEY_RELEASE";
case CMD_KEY_RELEASE_ALL: return "KEY_RELEASE_ALL";
Expand Down Expand Up @@ -196,7 +245,7 @@ struct Cmd
// Payload
union {

i64 value;
struct { i64 value; i64 value2; };
ConfigCmd config;
KeyCmd key;
CoordCmd coord;
Expand All @@ -207,7 +256,7 @@ struct Cmd
};

Cmd() { }
Cmd(CmdType type, i64 value = 0) : type(type), value(value) { }
Cmd(CmdType type, i64 v1 = 0, i64 v2 = 0) : type(type), value(v1), value2(v2) { }
Cmd(CmdType type, const KeyCmd &cmd) : type(type), key(cmd) { }
Cmd(CmdType type, const CoordCmd &cmd) : type(type), coord(cmd) { }
Cmd(CmdType type, const GamePadCmd &cmd) : type(type), action(cmd) { }
Expand Down
24 changes: 24 additions & 0 deletions Emulator/Components/C64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,30 @@ C64::process(const Cmd &cmd)
}
break;

case CMD_BP_SET_AT: cpu.setBreakpoint(u32(cmd.value)); break;
case CMD_BP_MOVE_TO: cpu.moveBreakpoint(cmd.value, u32(cmd.value2)); break;
case CMD_BP_REMOVE_NR: cpu.deleteBreakpoint(cmd.value); break;
case CMD_BP_REMOVE_AT: cpu.deleteBreakpointAt(u32(cmd.value)); break;
case CMD_BP_REMOVE_ALL: cpu.deleteAllBreakpoints(); break;
case CMD_BP_ENABLE_NR: cpu.enableBreakpoint(cmd.value); break;
case CMD_BP_ENABLE_AT: cpu.enableBreakpoint(u32(cmd.value)); break;
case CMD_BP_ENABLE_ALL: cpu.enableAllBreakpoints(); break;
case CMD_BP_DISABLE_NR: cpu.disableBreakpoint(cmd.value); break;
case CMD_BP_DISABLE_AT: cpu.disableBreakpoint(u32(cmd.value)); break;
case CMD_BP_DISABLE_ALL: cpu.disableAllBreakpoints(); break;

case CMD_WP_SET_AT: cpu.setWatchpoint(u32(cmd.value)); break;
case CMD_WP_MOVE_TO: cpu.moveWatchpoint(cmd.value, u32(cmd.value2)); break;
case CMD_WP_REMOVE_NR: cpu.deleteWatchpoint(cmd.value); break;
case CMD_WP_REMOVE_AT: cpu.deleteWatchpointAt(u32(cmd.value)); break;
case CMD_WP_REMOVE_ALL: cpu.deleteAllWatchpoints(); break;
case CMD_WP_ENABLE_NR: cpu.enableWatchpoint(cmd.value); break;
case CMD_WP_ENABLE_AT: cpu.enableWatchpoint(u32(cmd.value)); break;
case CMD_WP_ENABLE_ALL: cpu.enableAllWatchpoints(); break;
case CMD_WP_DISABLE_NR: cpu.disableWatchpoint(cmd.value); break;
case CMD_WP_DISABLE_AT: cpu.disableWatchpoint(u32(cmd.value)); break;
case CMD_WP_DISABLE_ALL: cpu.disableAllWatchpoints(); break;

case CMD_ALARM_ABS:

setAlarmAbs(cmd.alarm.cycle, cmd.alarm.value);
Expand Down
141 changes: 127 additions & 14 deletions Emulator/Components/CPU/CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,55 @@ CPU::jump(u16 addr)
}
}

void
CPU::processCommand(const Cmd &cmd)
{
switch (cmd.type) {

case CMD_CPU_BRK:

cpu.next = BRK;
cpu.reg.pc0 = cpu.reg.pc - 1;
break;

case CMD_CPU_NMI:

if (cmd.value) {
cpu.pullDownNmiLine(INTSRC_EXP);
} else {
cpu.releaseNmiLine(INTSRC_EXP);
}
break;

case CMD_BP_SET_AT: cpu.setBreakpoint(u32(cmd.value)); break;
case CMD_BP_MOVE_TO: cpu.moveBreakpoint(cmd.value, u32(cmd.value2)); break;
case CMD_BP_REMOVE_NR: cpu.deleteBreakpoint(cmd.value); break;
case CMD_BP_REMOVE_AT: cpu.deleteBreakpointAt(u32(cmd.value)); break;
case CMD_BP_REMOVE_ALL: cpu.deleteAllBreakpoints(); break;
case CMD_BP_ENABLE_NR: cpu.enableBreakpoint(cmd.value); break;
case CMD_BP_ENABLE_AT: cpu.enableBreakpointAt(u32(cmd.value)); break;
case CMD_BP_ENABLE_ALL: cpu.enableAllBreakpoints(); break;
case CMD_BP_DISABLE_NR: cpu.disableBreakpoint(cmd.value); break;
case CMD_BP_DISABLE_AT: cpu.disableBreakpointAt(u32(cmd.value)); break;
case CMD_BP_DISABLE_ALL: cpu.disableAllBreakpoints(); break;

case CMD_WP_SET_AT: cpu.setWatchpoint(u32(cmd.value)); break;
case CMD_WP_MOVE_TO: cpu.moveWatchpoint(cmd.value, u32(cmd.value2)); break;
case CMD_WP_REMOVE_NR: cpu.deleteWatchpoint(cmd.value); break;
case CMD_WP_REMOVE_AT: cpu.deleteWatchpointAt(u32(cmd.value)); break;
case CMD_WP_REMOVE_ALL: cpu.deleteAllWatchpoints(); break;
case CMD_WP_ENABLE_NR: cpu.enableWatchpoint(cmd.value); break;
case CMD_WP_ENABLE_AT: cpu.enableWatchpointAt(u32(cmd.value)); break;
case CMD_WP_ENABLE_ALL: cpu.enableAllWatchpoints(); break;
case CMD_WP_DISABLE_NR: cpu.disableWatchpoint(cmd.value); break;
case CMD_WP_DISABLE_AT: cpu.disableWatchpointAt(u32(cmd.value)); break;
case CMD_WP_DISABLE_ALL: cpu.disableAllWatchpoints(); break;

default:
fatalError;
}
}

void
CPU::setBreakpoint(u32 addr, isize ignores)
{
Expand All @@ -209,6 +258,15 @@ CPU::setBreakpoint(u32 addr, isize ignores)
msgQueue.put(MSG_BREAKPOINT_UPDATED);
}

void
CPU::moveBreakpoint(isize nr, u32 newAddr)
{
if (!debugger.breakpoints.guardWithNr(nr)) throw VC64Error(ERROR_BP_NOT_FOUND, nr);

debugger.breakpoints.moveTo(nr, newAddr);
msgQueue.put(MSG_BREAKPOINT_UPDATED);
}

void
CPU::deleteBreakpoint(isize nr)
{
Expand All @@ -219,20 +277,18 @@ CPU::deleteBreakpoint(isize nr)
}

void
CPU::enableBreakpoint(isize nr)
CPU::deleteBreakpointAt(u32 addr)
{
if (!debugger.breakpoints.guardWithNr(nr)) throw VC64Error(ERROR_BP_NOT_FOUND, nr);
if (!debugger.breakpoints.guardAtAddr(addr)) throw VC64Error(ERROR_BP_NOT_FOUND, addr);

debugger.breakpoints.setEnable(nr, true);
debugger.breakpoints.removeAt(addr);
msgQueue.put(MSG_BREAKPOINT_UPDATED);
}

void
CPU::disableBreakpoint(isize nr)
CPU::deleteAllBreakpoints()
{
if (!debugger.breakpoints.guardWithNr(nr)) throw VC64Error(ERROR_BP_NOT_FOUND, nr);

debugger.breakpoints.setEnable(nr, false);
debugger.breakpoints.removeAll();
msgQueue.put(MSG_BREAKPOINT_UPDATED);
}

Expand All @@ -242,6 +298,31 @@ CPU::toggleBreakpoint(isize nr)
debugger.breakpoints.isEnabled(nr) ? disableBreakpoint(nr) : enableBreakpoint(nr);
}

void
CPU::setEnableBreakpoint(isize nr, bool value)
{
if (!debugger.breakpoints.guardWithNr(nr)) throw VC64Error(ERROR_BP_NOT_FOUND, nr);

debugger.breakpoints.setEnable(nr, value);
msgQueue.put(MSG_BREAKPOINT_UPDATED);
}

void
CPU::setEnableBreakpointAt(u32 addr, bool value)
{
if (!debugger.breakpoints.guardAtAddr(addr)) throw VC64Error(ERROR_BP_NOT_FOUND, addr);

debugger.breakpoints.setEnableAt(addr, value);
msgQueue.put(MSG_BREAKPOINT_UPDATED);
}

void
CPU::setEnableAllBreakpoints(bool value)
{
debugger.breakpoints.setEnableAll(value);
msgQueue.put(MSG_BREAKPOINT_UPDATED);
}

void
CPU::setWatchpoint(u32 addr, isize ignores)
{
Expand All @@ -252,29 +333,36 @@ CPU::setWatchpoint(u32 addr, isize ignores)
}

void
CPU::deleteWatchpoint(isize nr)
CPU::moveWatchpoint(isize nr, u32 newAddr)
{
if (!debugger.watchpoints.guardWithNr(nr)) throw VC64Error(ERROR_WP_NOT_FOUND, nr);

debugger.watchpoints.remove(nr);
debugger.watchpoints.moveTo(nr, newAddr);
msgQueue.put(MSG_WATCHPOINT_UPDATED);
}

void
CPU::enableWatchpoint(isize nr)
CPU::deleteWatchpoint(isize nr)
{
if (!debugger.watchpoints.guardWithNr(nr)) throw VC64Error(ERROR_WP_NOT_FOUND, nr);

debugger.watchpoints.setEnable(nr, true);
debugger.watchpoints.remove(nr);
msgQueue.put(MSG_WATCHPOINT_UPDATED);
}

void
CPU::disableWatchpoint(isize nr)
CPU::deleteWatchpointAt(u32 addr)
{
if (!debugger.watchpoints.guardWithNr(nr)) throw VC64Error(ERROR_WP_NOT_FOUND, nr);
if (!debugger.watchpoints.guardAtAddr(addr)) throw VC64Error(ERROR_WP_NOT_FOUND, addr);

debugger.watchpoints.setEnable(nr, false);
debugger.watchpoints.removeAt(addr);
msgQueue.put(MSG_WATCHPOINT_UPDATED);
}

void
CPU::deleteAllWatchpoints()
{
debugger.watchpoints.removeAll();
msgQueue.put(MSG_WATCHPOINT_UPDATED);
}

Expand All @@ -284,6 +372,31 @@ CPU::toggleWatchpoint(isize nr)
debugger.watchpoints.isEnabled(nr) ? disableWatchpoint(nr) : enableWatchpoint(nr);
}

void
CPU::setEnableWatchpoint(isize nr, bool value)
{
if (!debugger.watchpoints.guardWithNr(nr)) throw VC64Error(ERROR_WP_NOT_FOUND, nr);

debugger.watchpoints.setEnable(nr, value);
msgQueue.put(MSG_WATCHPOINT_UPDATED);
}

void
CPU::setEnableWatchpointAt(u32 addr, bool value)
{
if (!debugger.watchpoints.guardAtAddr(addr)) throw VC64Error(ERROR_WP_NOT_FOUND, addr);

debugger.watchpoints.setEnableAt(addr, value);
msgQueue.put(MSG_WATCHPOINT_UPDATED);
}

void
CPU::setEnableAllWatchpoints(bool value)
{
debugger.watchpoints.setEnableAll(value);
msgQueue.put(MSG_WATCHPOINT_UPDATED);
}


//
// Memory API
Expand Down
Loading

0 comments on commit 236b9d2

Please sign in to comment.