23 using std::shared_ptr;
24 using std::make_shared;
41 virtual bool needRecord(
const vector<TclObject>& tokens)
const;
42 virtual void execute(
const vector<TclObject>& tokens,
44 virtual string help(
const vector<string>& tokens)
const;
49 void desc(
const vector<TclObject>& tokens,
51 void size(
const vector<TclObject>& tokens,
53 void read(
const vector<TclObject>& tokens,
55 void readBlock(
const vector<TclObject>& tokens,
57 void write(
const vector<TclObject>& tokens,
59 void writeBlock(
const vector<TclObject>& tokens,
61 void setBreakPoint(
const vector<TclObject>& tokens,
63 void removeBreakPoint(
const vector<TclObject>& tokens,
65 void listBreakPoints(
const vector<TclObject>& tokens,
67 vector<string> getBreakPointIds()
const;
68 vector<string> getWatchPointIds()
const;
69 vector<string> getConditionIds()
const;
70 void setWatchPoint(
const vector<TclObject>& tokens,
72 void removeWatchPoint(
const vector<TclObject>& tokens,
74 void listWatchPoints(
const vector<TclObject>& tokens,
76 void setCondition(
const vector<TclObject>& tokens,
78 void removeCondition(
const vector<TclObject>& tokens,
80 void listConditions(
const vector<TclObject>& tokens,
82 void probe(
const vector<TclObject>& tokens,
84 void probeList(
const vector<TclObject>& tokens,
86 void probeDesc(
const vector<TclObject>& tokens,
88 void probeRead(
const vector<TclObject>& tokens,
90 void probeSetBreakPoint(
const vector<TclObject>& tokens,
92 void probeRemoveBreakPoint(
const vector<TclObject>& tokens,
94 void probeListBreakPoints(
const vector<TclObject>& tokens,
103 : motherBoard(motherBoard_)
105 motherBoard.getCommandController(),
106 motherBoard.getStateChangeDistributor(),
107 motherBoard.getScheduler(),
108 motherBoard.getReactor().getGlobalCliComm(), *this))
116 assert(debuggables.
empty());
126 assert(debuggables.
find(name) == debuggables.
end());
127 debuggables[name] = &debuggable;
133 auto it = debuggables.
find(name);
134 assert(it != debuggables.
end() && (it->second == &debuggable));
135 debuggables.
erase(it);
140 auto it = debuggables.
find(name);
141 return (it != debuggables.
end()) ? it->
second :
nullptr;
155 assert(probes.
find(name) == probes.
end());
156 probes[name] = &probe;
162 auto it = probes.
find(name);
163 assert(it != probes.
end() && (it->second == &probe));
169 auto it = probes.
find(name);
170 return (it != probes.
end()) ? it->
second :
nullptr;
182 unsigned Debugger::insertProbeBreakPoint(
183 TclObject command, TclObject condition,
184 ProbeBase& probe,
unsigned newId )
186 auto bp = make_unique<ProbeBreakPoint>(
188 command, condition, *
this, probe, newId);
189 unsigned result = bp->getId();
190 probeBreakPoints.push_back(std::move(bp));
199 for (
auto it = probeBreakPoints.begin();
200 it != probeBreakPoints.end(); ++it) {
201 if ((*it)->getId() == id) {
202 probeBreakPoints.erase(it);
206 throw CommandException(
"No such breakpoint: " + name);
209 for (
auto it = probeBreakPoints.begin();
210 it != probeBreakPoints.end(); ++it) {
211 if ((*it)->getProbe().getName() == name) {
212 probeBreakPoints.erase(it);
216 throw CommandException(
217 "No (unconditional) breakpoint for probe: " + name);
223 auto it = std::find_if(probeBreakPoints.begin(), probeBreakPoints.end(),
224 [&](ProbeBreakPoints::value_type& v) {
return v.get() == &bp; });
225 assert(it != probeBreakPoints.end());
226 probeBreakPoints.erase(it);
231 unsigned beginAddr,
unsigned endAddr,
234 shared_ptr<WatchPoint> wp;
248 motherBoard, type, beginAddr, endAddr,
249 command, condition, newId));
254 wp.reset(
new WatchPoint(
256 command, condition, type, beginAddr, endAddr, newId));
267 setWatchPoint(wp->getCommandObj(), wp->getConditionObj(),
268 wp->getType(), wp->getBeginAddress(),
269 wp->getEndAddress(), wp->getId());
273 assert(probeBreakPoints.empty());
274 for (
auto& bp : other.probeBreakPoints) {
276 insertProbeBreakPoint(bp->getCommandObj(),
277 bp->getConditionObj(),
278 *probe, bp->getId());
289 static word getAddress(
const vector<TclObject>& tokens)
291 if (tokens.size() < 3) {
294 unsigned addr = tokens[2].getInt();
295 if (addr >= 0x10000) {
296 throw CommandException(
"Invalid address");
308 , debugger(debugger_)
318 if (tokens.size() < 2)
return false;
320 return (subCmd ==
"write") || (subCmd ==
"write_block");
326 if (tokens.size() < 2) {
330 if (subCmd ==
"read") {
331 read(tokens, result);
332 }
else if (subCmd ==
"read_block") {
333 readBlock(tokens, result);
334 }
else if (subCmd ==
"write") {
335 write(tokens, result);
336 }
else if (subCmd ==
"write_block") {
337 writeBlock(tokens, result);
338 }
else if (subCmd ==
"size") {
339 size(tokens, result);
340 }
else if (subCmd ==
"desc") {
341 desc(tokens, result);
342 }
else if (subCmd ==
"list") {
344 }
else if (subCmd ==
"step") {
346 }
else if (subCmd ==
"cont") {
348 }
else if (subCmd ==
"disasm") {
350 }
else if (subCmd ==
"break") {
352 }
else if (subCmd ==
"breaked") {
354 }
else if (subCmd ==
"set_bp") {
355 setBreakPoint(tokens, result);
356 }
else if (subCmd ==
"remove_bp") {
357 removeBreakPoint(tokens, result);
358 }
else if (subCmd ==
"list_bp") {
359 listBreakPoints(tokens, result);
360 }
else if (subCmd ==
"set_watchpoint") {
361 setWatchPoint(tokens, result);
362 }
else if (subCmd ==
"remove_watchpoint") {
363 removeWatchPoint(tokens, result);
364 }
else if (subCmd ==
"list_watchpoints") {
365 listWatchPoints(tokens, result);
366 }
else if (subCmd ==
"set_condition") {
367 setCondition(tokens, result);
368 }
else if (subCmd ==
"remove_condition") {
369 removeCondition(tokens, result);
370 }
else if (subCmd ==
"list_conditions") {
371 listConditions(tokens, result);
372 }
else if (subCmd ==
"probe") {
373 probe(tokens, result);
384 void DebugCmd::desc(
const vector<TclObject>& tokens, TclObject& result)
386 if (tokens.size() != 3) {
389 Debuggable& device = debugger.getDebuggable(tokens[2].getString());
390 result.setString(device.getDescription());
393 void DebugCmd::size(
const vector<TclObject>& tokens, TclObject& result)
395 if (tokens.size() != 3) {
398 Debuggable& device = debugger.getDebuggable(tokens[2].getString());
399 result.setInt(device.getSize());
402 void DebugCmd::read(
const vector<TclObject>& tokens, TclObject& result)
404 if (tokens.size() != 4) {
407 Debuggable& device = debugger.getDebuggable(tokens[2].getString());
408 unsigned addr = tokens[3].getInt();
409 if (addr >= device.getSize()) {
410 throw CommandException(
"Invalid address");
412 result.setInt(device.read(addr));
415 void DebugCmd::readBlock(
const vector<TclObject>& tokens, TclObject& result)
417 if (tokens.size() != 5) {
420 Debuggable& device = debugger.getDebuggable(tokens[2].getString());
421 unsigned size = device.getSize();
422 unsigned addr = tokens[3].getInt();
424 throw CommandException(
"Invalid address");
426 unsigned num = tokens[4].getInt();
427 if (num > (size - addr)) {
428 throw CommandException(
"Invalid size");
431 MemBuffer<byte> buf(num);
432 for (
unsigned i = 0; i < num; ++i) {
433 buf[i] = device.read(addr + i);
435 result.setBinary(buf.data(), num);
438 void DebugCmd::write(
const vector<TclObject>& tokens,
441 if (tokens.size() != 5) {
444 Debuggable& device = debugger.getDebuggable(tokens[2].getString());
445 unsigned addr = tokens[3].getInt();
446 if (addr >= device.getSize()) {
447 throw CommandException(
"Invalid address");
449 unsigned value = tokens[4].getInt();
451 throw CommandException(
"Invalid value");
454 device.write(addr, value);
457 void DebugCmd::writeBlock(
const vector<TclObject>& tokens,
460 if (tokens.size() != 5) {
463 Debuggable& device = debugger.getDebuggable(tokens[2].getString());
464 unsigned size = device.
getSize();
465 unsigned addr = tokens[3].getInt();
467 throw CommandException(
"Invalid address");
470 const byte* buf = tokens[4].getBinary(num);
471 if ((num + addr) > size) {
472 throw CommandException(
"Invalid size");
475 for (
unsigned i = 0; i < num; ++i) {
476 device.write(addr + i, static_cast<byte>(buf[i]));
480 void DebugCmd::setBreakPoint(
const vector<TclObject>& tokens,
483 shared_ptr<BreakPoint> bp;
484 TclObject command (result.getInterpreter(),
"debug break");
485 TclObject condition(result.getInterpreter());
488 switch (tokens.size()) {
494 condition = tokens[3];
500 addr = getAddress(tokens);
501 bp = make_shared<BreakPoint>(cliComm, addr, command, condition);
504 if (tokens.size() < 3) {
505 throw CommandException(
"Too few arguments.");
507 throw CommandException(
"Too many arguments.");
514 void DebugCmd::removeBreakPoint(
const vector<TclObject>& tokens,
517 if (tokens.size() != 3) {
520 auto&
interface = debugger.motherBoard.getCPUInterface();
521 auto& breakPoints = interface.getBreakPoints();
527 for (
auto& p : breakPoints) {
528 const BreakPoint& bp = *p.second;
529 if (bp.getId() == id) {
530 interface.removeBreakPoint(bp);
534 throw CommandException(
"No such breakpoint: " + tmp);
537 word addr = getAddress(tokens);
538 auto range = breakPoints.equal_range(addr);
539 for (
auto it = range.first; it != range.second; ++it) {
540 const BreakPoint& bp = *it->second;
541 if (bp.getCondition().empty()) {
542 interface.removeBreakPoint(bp);
546 throw CommandException(
547 "No (unconditional) breakpoint at address: " + tmp);
551 void DebugCmd::listBreakPoints(
const vector<TclObject>& ,
555 auto&
interface = debugger.motherBoard.getCPUInterface();
556 for (
auto& p : interface.getBreakPoints()) {
557 const BreakPoint& bp = *p.second;
558 TclObject line(result.getInterpreter());
561 line.addListElement(bp.getCondition());
562 line.addListElement(bp.getCommand());
563 res += line.getString() +
'\n';
565 result.setString(res);
569 void DebugCmd::setWatchPoint(
const vector<TclObject>& tokens,
572 TclObject command (result.getInterpreter(),
"debug break");
573 TclObject condition(result.getInterpreter());
574 unsigned beginAddr, endAddr;
577 switch (tokens.size()) {
580 command.checkCommand();
583 condition = tokens[4];
591 if (typeStr ==
"read_io") {
594 }
else if (typeStr ==
"write_io") {
597 }
else if (typeStr ==
"read_mem") {
600 }
else if (typeStr ==
"write_mem") {
604 throw CommandException(
"Invalid type: " + typeStr);
606 if (tokens[3].getListLength() == 2) {
607 beginAddr = tokens[3].getListIndex(0).getInt();
608 endAddr = tokens[3].getListIndex(1).getInt();
609 if (endAddr < beginAddr) {
610 throw CommandException(
611 "Not a valid range: end address may "
612 "not be smaller than begin address.");
615 beginAddr = endAddr = tokens[3].getInt();
617 if (endAddr >= max) {
618 throw CommandException(
"Invalid address: out of range");
623 if (tokens.size() < 4) {
624 throw CommandException(
"Too few arguments.");
626 throw CommandException(
"Too many arguments.");
629 unsigned id = debugger.setWatchPoint(
630 command, condition, type, beginAddr, endAddr);
634 void DebugCmd::removeWatchPoint(
const vector<TclObject>& tokens,
637 if (tokens.size() != 3) {
644 auto&
interface = debugger.motherBoard.getCPUInterface();
645 for (
auto& wp : interface.getWatchPoints()) {
646 if (wp->getId() == id) {
647 interface.removeWatchPoint(wp);
652 throw CommandException(
"No such watchpoint: " + tmp);
655 void DebugCmd::listWatchPoints(
const vector<TclObject>& ,
659 auto&
interface = debugger.motherBoard.getCPUInterface();
660 for (
auto& wp : interface.getWatchPoints()) {
661 TclObject line(result.getInterpreter());
664 switch (wp->getType()) {
680 line.addListElement(type);
681 unsigned beginAddr = wp->getBeginAddress();
682 unsigned endAddr = wp->getEndAddress();
683 if (beginAddr == endAddr) {
686 TclObject range(result.getInterpreter());
689 line.addListElement(range);
691 line.addListElement(wp->getCondition());
692 line.addListElement(wp->getCommand());
693 res += line.getString() +
'\n';
695 result.setString(res);
699 void DebugCmd::setCondition(
const vector<TclObject>& tokens,
702 shared_ptr<DebugCondition> dc;
703 TclObject command (result.getInterpreter(),
"debug break");
704 TclObject condition(result.getInterpreter());
706 switch (tokens.size()) {
709 command.checkCommand();
712 condition = tokens[2];
716 dc = make_shared<DebugCondition>(cliComm, command, condition);
719 if (tokens.size() < 3) {
720 throw CommandException(
"Too few arguments.");
722 throw CommandException(
"Too many arguments.");
729 void DebugCmd::removeCondition(
const vector<TclObject>& tokens,
732 if (tokens.size() != 3) {
740 auto&
interface = debugger.motherBoard.getCPUInterface();
741 for (
auto& c : interface.getConditions()) {
742 if (c->getId() == id) {
743 interface.removeCondition(*c);
748 throw CommandException(
"No such condition: " + tmp);
751 void DebugCmd::listConditions(
const vector<TclObject>& ,
755 auto&
interface = debugger.motherBoard.getCPUInterface();
756 for (
auto& c : interface.getConditions()) {
757 TclObject line(result.getInterpreter());
759 line.addListElement(c->getCondition());
760 line.addListElement(c->getCommand());
761 res += line.getString() +
'\n';
763 result.setString(res);
767 void DebugCmd::probe(
const vector<TclObject>& tokens,
770 if (tokens.size() < 3) {
771 throw CommandException(
"Missing argument");
774 if (subCmd ==
"list") {
775 probeList(tokens, result);
776 }
else if (subCmd ==
"desc") {
777 probeDesc(tokens, result);
778 }
else if (subCmd ==
"read") {
779 probeRead(tokens, result);
780 }
else if (subCmd ==
"set_bp") {
781 probeSetBreakPoint(tokens, result);
782 }
else if (subCmd ==
"remove_bp") {
783 probeRemoveBreakPoint(tokens, result);
784 }
else if (subCmd ==
"list_bp") {
785 probeListBreakPoints(tokens, result);
790 void DebugCmd::probeList(
const vector<TclObject>& ,
793 result.addListElements(
keys(debugger.probes));
795 void DebugCmd::probeDesc(
const vector<TclObject>& tokens,
798 if (tokens.size() != 4) {
801 ProbeBase& probe = debugger.getProbe(tokens[3].getString());
802 result.setString(probe.getDescription());
804 void DebugCmd::probeRead(
const vector<TclObject>& tokens,
807 if (tokens.size() != 4) {
810 ProbeBase& probe = debugger.getProbe(tokens[3].getString());
811 result.setString(probe.getValue());
813 void DebugCmd::probeSetBreakPoint(
const vector<TclObject>& tokens,
816 TclObject command (result.getInterpreter(),
"debug break");
817 TclObject condition(result.getInterpreter());
820 switch (tokens.size()) {
823 command.checkCommand();
826 condition = tokens[4];
832 probe = &debugger.getProbe(tokens[3].getString());
836 if (tokens.size() < 4) {
837 throw CommandException(
"Too few arguments.");
839 throw CommandException(
"Too many arguments.");
843 unsigned id = debugger.insertProbeBreakPoint(command, condition, *probe);
846 void DebugCmd::probeRemoveBreakPoint(
const vector<TclObject>& tokens,
849 if (tokens.size() != 4) {
854 void DebugCmd::probeListBreakPoints(
const vector<TclObject>& ,
858 for (
auto& p : debugger.probeBreakPoints) {
859 TclObject line(result.getInterpreter());
861 line.addListElement(p->getProbe().getName());
862 line.addListElement(p->getCondition());
863 line.addListElement(p->getCommand());
864 res += line.getString() +
'\n';
866 result.setString(res);
871 static const string generalHelp =
872 "debug <subcommand> [<arguments>]\n"
873 " Possible subcommands are:\n"
874 " list returns a list of all debuggables\n"
875 " desc returns a description of this debuggable\n"
876 " size returns the size of this debuggable\n"
877 " read read a byte from a debuggable\n"
878 " write write a byte to a debuggable\n"
879 " read_block read a whole block at once\n"
880 " write_block write a whole block at once\n"
881 " set_bp insert a new breakpoint\n"
882 " remove_bp remove a certain breakpoint\n"
883 " list_bp list the active breakpoints\n"
884 " set_watchpoint insert a new watchpoint\n"
885 " remove_watchpoint remove a certain watchpoint\n"
886 " list_watchpoints list the active watchpoints\n"
887 " set_condition insert a new condition\n"
888 " remove_condition remove a certain condition\n"
889 " list_conditions list the active conditions\n"
890 " probe probe related subcommands\n"
891 " cont continue execution after break\n"
892 " step execute one instruction\n"
893 " break break CPU at current position\n"
894 " breaked query CPU breaked status\n"
895 " disasm disassemble instructions\n"
896 " The arguments are specific for each subcommand.\n"
897 " Type 'help debug <subcommand>' for help about a specific subcommand.\n";
899 static const string listHelp =
901 " Returns a list with the names of all 'debuggables'.\n"
902 " These names are used in other debug subcommands.\n";
903 static const string descHelp =
904 "debug desc <name>\n"
905 " Returns a description for the debuggable with given name.\n";
906 static const string sizeHelp =
907 "debug size <name>\n"
908 " Returns the size (in bytes) of the debuggable with given name.\n";
909 static const string readHelp =
910 "debug read <name> <addr>\n"
911 " Read a byte at offset <addr> from the given debuggable.\n"
912 " The offset must be smaller than the value returned from the "
913 "'size' subcommand\n"
914 " Note that openMSX comes with a bunch of Tcl scripts that make "
915 "some of the debug reads much more convenient (e.g. reading from "
916 "Z80 or VDP registers). See the Console Command Reference for more "
917 "details about these.\n";
918 static const string writeHelp =
919 "debug write <name> <addr> <val>\n"
920 " Write a byte to the given debuggable at a certain offset.\n"
921 " The offset must be smaller than the value returned from the "
922 "'size' subcommand\n";
923 static const string readBlockHelp =
924 "debug read_block <name> <addr> <size>\n"
925 " Read a whole block at once. This is equivalent with repeated "
926 "invocations of the 'read' subcommand, but using this subcommand "
927 "may be faster. The result is a Tcl binary string (see Tcl manual).\n"
928 " The block is specified as size/offset in the debuggable. The "
929 "complete block must fit in the debuggable (see the 'size' "
931 static const string writeBlockHelp =
932 "debug write_block <name> <addr> <values>\n"
933 " Write a whole block at once. This is equivalent with repeated "
934 "invocations of the 'write' subcommand, but using this subcommand "
935 "may be faster. The <values> argument must be a Tcl binary string "
936 "(see Tcl manual).\n"
937 " The block has a size and an offset in the debuggable. The "
938 "complete block must fit in the debuggable (see the 'size' "
940 static const string setBpHelp =
941 "debug set_bp <addr> [<cond>] [<cmd>]\n"
942 " Insert a new breakpoint at given address. When the CPU is about "
943 "to execute the instruction at this address, execution will be "
944 "breaked. At least this is the default behaviour, see next "
946 " Optionally you can specify a condition. When the CPU reaches "
947 "the breakpoint this condition is evaluated, only when the condition "
948 "evaluated to true execution will be breaked.\n"
949 " A condition must be specified as a Tcl expression. For example\n"
950 " debug set_bp 0xf37d {[reg C] == 0x2F}\n"
951 " This breaks on address 0xf37d but only when Z80 register C has the "
953 " Also optionally you can specify a command that should be "
954 "executed when the breakpoint is reached (and condition is true). "
955 "By default this command is 'debug break'.\n"
956 " The result of this command is a breakpoint ID. This ID can "
957 "later be used to remove this breakpoint again.\n";
958 static const string removeBpHelp =
959 "debug remove_bp <id>\n"
960 " Remove the breakpoint with given ID again. You can use the "
961 "'list_bp' subcommand to see all valid IDs.\n";
962 static const string listBpHelp =
964 " Lists all active breakpoints. The result is printed in 4 "
965 "columns. The first column contains the breakpoint ID. The "
966 "second one has the address. The third has the condition "
967 "(default condition is empty). And the last column contains "
968 "the command that will be executed (default is 'debug break').\n";
969 static const string setWatchPointHelp =
970 "debug set_watchpoint <type> <region> [<cond>] [<cmd>]\n"
971 " Insert a new watchpoint of given type on the given region, "
972 "there can be an optional condition and alternative command. See "
973 "the 'set_bp' subcommand for details about these last two.\n"
974 " Type must be one of the following:\n"
975 " read_io break when CPU reads from given IO port(s)\n"
976 " write_io break when CPU writes to given IO port(s)\n"
977 " read_mem break when CPU reads from given memory location(s)\n"
978 " write_mem break when CPU writes to given memory location(s)\n"
979 " Region is either a single value, this corresponds to a single "
980 "memory location or IO port. Otherwise region must be a list of "
981 "two values (enclosed in braces) that specify a begin and end "
982 "point of a whole memory region or a range of IO ports.\n"
983 "During the execution of <cmd>, the following global Tcl "
984 "variables are set:\n"
985 " ::wp_last_address this is the actual address of the mem/io "
986 "read/write that triggered the watchpoint\n"
987 " ::wp_last_value this is the actual value that was written "
988 "by the mem/io write that triggered the watchpoint\n"
990 " debug set_watchpoint write_io 0x99 {[reg A] == 0x81}\n"
991 " debug set_watchpoint read_mem {0xfbe5 0xfbef}\n";
992 static const string removeWatchPointHelp =
993 "debug remove_watchpoint <id>\n"
994 " Remove the watchpoint with given ID again. You can use the "
995 "'list_watchpoints' subcommand to see all valid IDs.\n";
996 static const string listWatchPointsHelp =
997 "debug list_watchpoints\n"
998 " Lists all active watchpoints. The result is similar to the "
999 "'list_bp' subcommand, but there is an extra column (2nd column) "
1000 "that contains the type of the watchpoint.\n";
1001 static const string setCondHelp =
1002 "debug set_condition <cond> [<cmd>]\n"
1003 " Insert a new condition. These are much like breakpoints, "
1004 "except that they are checked before every instruction "
1005 "(breakpoints are tied to a specific address).\n"
1006 " Conditions will slow down simulation MUCH more than "
1007 "breakpoints. So only use them when you don't care about "
1008 "simulation speed (when you're debugging this is usually not "
1010 " See 'help debug set_bp' for more details.\n";
1011 static const string removeCondHelp =
1012 "debug remove_condition <id>\n"
1013 " Remove the condition with given ID again. You can use the "
1014 "'list_conditions' subcommand to see all valid IDs.\n";
1015 static const string listCondHelp =
1016 "debug list_conditions\n"
1017 " Lists all active conditions. The result is similar to the "
1018 "'list_bp' subcommand, but without the 2nd column that would "
1019 "show the address.\n";
1020 static const string probeHelp =
1021 "debug probe <subcommand> [<arguments>]\n"
1022 " Possible subcommands are:\n"
1023 " list returns a list of all probes\n"
1024 " desc <probe> returns a description of this probe\n"
1025 " read <probe> returns the current value of this probe\n"
1026 " set_bp <probe> [<cond>] [<cmd>] set a breakpoint on the given probe\n"
1027 " remove_bp <id> remove the given breakpoint\n"
1028 " list_bp returns a list of breakpoints that are set on probes\n";
1029 static const string contHelp =
1031 " Continue execution after CPU was breaked.\n";
1032 static const string stepHelp =
1034 " Execute one instruction. This command is only meaningful in "
1036 static const string breakHelp =
1038 " Immediately break CPU execution. When CPU was already breaked "
1039 "this command has no effect.\n";
1040 static const string breakedHelp =
1042 " Query the CPU breaked status. Returns '1' when CPU was "
1043 "breaked, '0' otherwise.\n";
1044 static const string disasmHelp =
1045 "debug disasm <addr>\n"
1046 " Disassemble the instruction at the given address. The result "
1047 "is a Tcl list. The first element in the list contains a textual "
1048 "representation of the instruction, the next elements contain the "
1049 "bytes that make up this instruction (thus the length of the "
1050 "resulting list can be used to derive the number of bytes in the "
1052 " Note that openMSX comes with a 'disasm' Tcl script that is much "
1053 "more convenient to use than this subcommand.";
1054 static const string unknownHelp =
1055 "Unknown subcommand, use 'help debug' to see a list of valid "
1058 if (tokens.size() == 1) {
1060 }
else if (tokens[1] ==
"list") {
1062 }
else if (tokens[1] ==
"desc") {
1064 }
else if (tokens[1] ==
"size") {
1066 }
else if (tokens[1] ==
"read") {
1068 }
else if (tokens[1] ==
"write") {
1070 }
else if (tokens[1] ==
"read_block") {
1071 return readBlockHelp;
1072 }
else if (tokens[1] ==
"write_block") {
1073 return writeBlockHelp;
1074 }
else if (tokens[1] ==
"set_bp") {
1076 }
else if (tokens[1] ==
"remove_bp") {
1077 return removeBpHelp;
1078 }
else if (tokens[1] ==
"list_bp") {
1080 }
else if (tokens[1] ==
"set_watchpoint") {
1081 return setWatchPointHelp;
1082 }
else if (tokens[1] ==
"remove_watchpoint") {
1083 return removeWatchPointHelp;
1084 }
else if (tokens[1] ==
"list_watchpoints") {
1085 return listWatchPointsHelp;
1086 }
else if (tokens[1] ==
"set_condition") {
1088 }
else if (tokens[1] ==
"remove_condition") {
1089 return removeCondHelp;
1090 }
else if (tokens[1] ==
"list_conditions") {
1091 return listCondHelp;
1092 }
else if (tokens[1] ==
"probe") {
1094 }
else if (tokens[1] ==
"cont") {
1096 }
else if (tokens[1] ==
"step") {
1098 }
else if (tokens[1] ==
"break") {
1100 }
else if (tokens[1] ==
"breaked") {
1102 }
else if (tokens[1] ==
"disasm") {
1109 vector<string> DebugCmd::getBreakPointIds()
const
1111 vector<string> bpids;
1112 auto&
interface = debugger.motherBoard.getCPUInterface();
1113 for (
auto& p : interface.getBreakPoints()) {
1118 vector<string> DebugCmd::getWatchPointIds()
const
1120 vector<string> wpids;
1121 auto&
interface = debugger.motherBoard.getCPUInterface();
1122 for (
auto& w : interface.getWatchPoints()) {
1127 vector<string> DebugCmd::getConditionIds()
const
1129 vector<string> condids;
1130 auto&
interface = debugger.motherBoard.getCPUInterface();
1131 for (
auto& c : interface.getConditions()) {
1139 static const char*
const singleArgCmds[] = {
1140 "list",
"step",
"cont",
"break",
"breaked",
1141 "list_bp",
"list_watchpoints",
"list_conditions",
1143 static const char*
const debuggableArgCmds[] = {
1144 "desc",
"size",
"read",
"read_block",
1145 "write",
"write_block",
1147 static const char*
const otherCmds[] = {
1148 "disasm",
"set_bp",
"remove_bp",
"set_watchpoint",
1149 "remove_watchpoint",
"set_condition",
"remove_condition",
1152 switch (tokens.size()) {
1154 vector<const char*> cmds;
1155 cmds.insert(end(cmds), begin(singleArgCmds), end(singleArgCmds));
1156 cmds.insert(end(cmds), begin(debuggableArgCmds), end(debuggableArgCmds));
1157 cmds.insert(end(cmds), begin(otherCmds), end(otherCmds));
1162 if (find(begin(singleArgCmds), end(singleArgCmds), tokens[1]) ==
1163 end(singleArgCmds)) {
1165 if (find(begin(debuggableArgCmds), end(debuggableArgCmds),
1167 end(debuggableArgCmds)) {
1170 }
else if (tokens[1] ==
"remove_bp") {
1173 }
else if (tokens[1] ==
"remove_watchpoint") {
1176 }
else if (tokens[1] ==
"remove_condition") {
1179 }
else if (tokens[1] ==
"set_watchpoint") {
1180 static const char*
const types[] = {
1181 "write_io",
"write_mem",
1182 "read_io",
"read_mem",
1185 }
else if (tokens[1] ==
"probe") {
1186 static const char*
const subCmds[] = {
1187 "list",
"desc",
"read",
"set_bp",
1188 "remove_bp",
"list_bp",
1195 if ((tokens[1] ==
"probe") &&
1196 ((tokens[2] ==
"desc") || (tokens[2] ==
"read") ||
1197 (tokens[2] ==
"set_bp"))) {