From c643372753b8e5823d2ff5b68475a6b60e0a672d Mon Sep 17 00:00:00 2001 From: "therealmogminer@gmail.com" Date: Thu, 14 Jul 2016 16:13:52 +0200 Subject: Make loop collation optional for debugger trace and traceover commands --- src/emu/debug/debugcmd.cpp | 31 ++++++++++++++++++++++++-- src/emu/debug/debugcmd.h | 3 +++ src/emu/debug/debugcpu.cpp | 54 +++++++++++++++++++++++++--------------------- src/emu/debug/debugcpu.h | 5 +++-- src/emu/debug/debughlp.cpp | 47 ++++++++++++++++++++++++---------------- 5 files changed, 93 insertions(+), 47 deletions(-) diff --git a/src/emu/debug/debugcmd.cpp b/src/emu/debug/debugcmd.cpp index bdfd4dbf826..ff734e9f65d 100644 --- a/src/emu/debug/debugcmd.cpp +++ b/src/emu/debug/debugcmd.cpp @@ -379,6 +379,30 @@ bool debugger_commands::validate_number_parameter(const char *param, UINT64 *res } +/*------------------------------------------------- + validate_boolean_parameter - validates a + boolean parameter +-------------------------------------------------*/ + +bool debugger_commands::validate_boolean_parameter(const char *param, bool *result) +{ + /* nullptr parameter does nothing and returns no error */ + if (param == nullptr) + return true; + + /* evaluate the expression; success if no error */ + bool is_true = (strcmp(param, "true") == 0 || strcmp(param, "TRUE") == 0 || strcmp(param, "1") == 0); + bool is_false = (strcmp(param, "false") == 0 || strcmp(param, "FALSE") == 0 || strcmp(param, "0") == 0); + + if (!is_true && !is_false) + return false; + + *result = is_true; + + return true; +} + + /*------------------------------------------------- validate_cpu_parameter - validates a parameter as a cpu @@ -2444,6 +2468,7 @@ void debugger_commands::execute_dasm(int ref, int params, const char *param[]) void debugger_commands::execute_trace_internal(int ref, int params, const char *param[], bool trace_over) { const char *action = nullptr; + bool detect_loops = true; device_t *cpu; FILE *f = nullptr; const char *mode; @@ -2455,7 +2480,9 @@ void debugger_commands::execute_trace_internal(int ref, int params, const char * /* validate parameters */ if (!validate_cpu_parameter((params > 1) ? param[1] : nullptr, &cpu)) return; - if (!debug_command_parameter_command(action = param[2])) + if (!validate_boolean_parameter((params > 2) ? param[2] : nullptr, &detect_loops)) + return; + if (!debug_command_parameter_command(action = param[3])) return; /* open the file */ @@ -2479,7 +2506,7 @@ void debugger_commands::execute_trace_internal(int ref, int params, const char * } /* do it */ - cpu->debug()->trace(f, trace_over, action); + cpu->debug()->trace(f, trace_over, detect_loops, action); if (f) m_console.printf("Tracing CPU '%s' to file %s\n", cpu->tag(), filename.c_str()); else diff --git a/src/emu/debug/debugcmd.h b/src/emu/debug/debugcmd.h index 7ecfc87958b..eae6fc611d3 100644 --- a/src/emu/debug/debugcmd.h +++ b/src/emu/debug/debugcmd.h @@ -25,6 +25,9 @@ class debugger_commands public: debugger_commands(running_machine& machine, debugger_cpu& cpu, debugger_console& console); + /* validates a parameter as a boolean value */ + bool validate_boolean_parameter(const char *param, bool *result); + /* validates a parameter as a numeric value */ bool validate_number_parameter(const char *param, UINT64 *result); diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index d28a15bd79b..b9062d3894d 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -2637,14 +2637,14 @@ UINT32 device_debug::compute_opcode_crc32(offs_t pc) const // trace - trace execution of a given device //------------------------------------------------- -void device_debug::trace(FILE *file, bool trace_over, const char *action) +void device_debug::trace(FILE *file, bool trace_over, bool detect_loops, const char *action) { // delete any existing tracers m_trace = nullptr; // if we have a new file, make a new tracer if (file != nullptr) - m_trace = std::make_unique(*this, *file, trace_over, action); + m_trace = std::make_unique(*this, *file, trace_over, detect_loops, action); } @@ -3305,14 +3305,15 @@ bool device_debug::registerpoint::hit() // tracer - constructor //------------------------------------------------- -device_debug::tracer::tracer(device_debug &debug, FILE &file, bool trace_over, const char *action) - : m_debug(debug), - m_file(file), - m_action((action != nullptr) ? action : ""), - m_loops(0), - m_nextdex(0), - m_trace_over(trace_over), - m_trace_over_target(~0) +device_debug::tracer::tracer(device_debug &debug, FILE &file, bool trace_over, bool detect_loops, const char *action) + : m_debug(debug) + , m_file(file) + , m_action((action != nullptr) ? action : "") + , m_detect_loops(detect_loops) + , m_loops(0) + , m_nextdex(0) + , m_trace_over(trace_over) + , m_trace_over_target(~0) { memset(m_history, 0, sizeof(m_history)); } @@ -3344,23 +3345,26 @@ void device_debug::tracer::update(offs_t pc) m_trace_over_target = ~0; } - // check for a loop condition - int count = 0; - for (auto & elem : m_history) - if (elem == pc) - count++; - - // if more than 1 hit, just up the loop count and get out - if (count > 1) + if (m_detect_loops) { - m_loops++; - return; - } + // check for a loop condition + int count = 0; + for (auto & elem : m_history) + if (elem == pc) + count++; + + // if more than 1 hit, just up the loop count and get out + if (count > 1) + { + m_loops++; + return; + } - // if we just finished looping, indicate as much - if (m_loops != 0) - fprintf(&m_file, "\n (loops for %d instructions)\n\n", m_loops); - m_loops = 0; + // if we just finished looping, indicate as much + if (m_loops != 0) + fprintf(&m_file, "\n (loops for %d instructions)\n\n", m_loops); + m_loops = 0; + } // execute any trace actions first if (!m_action.empty()) diff --git a/src/emu/debug/debugcpu.h b/src/emu/debug/debugcpu.h index bc4ee3675cf..aa2018201dd 100644 --- a/src/emu/debug/debugcpu.h +++ b/src/emu/debug/debugcpu.h @@ -263,7 +263,7 @@ public: void track_mem_data_clear() { m_track_mem_set.clear(); } // tracing - void trace(FILE *file, bool trace_over, const char *action); + void trace(FILE *file, bool trace_over, bool detect_loops, const char *action); void trace_printf(const char *fmt, ...) ATTR_PRINTF(2,3); void trace_flush() { if (m_trace != nullptr) m_trace->flush(); } @@ -336,7 +336,7 @@ private: class tracer { public: - tracer(device_debug &debug, FILE &file, bool trace_over, const char *action); + tracer(device_debug &debug, FILE &file, bool trace_over, bool detect_loops, const char *action); ~tracer(); void update(offs_t pc); @@ -350,6 +350,7 @@ private: FILE & m_file; // tracing file for this CPU std::string m_action; // action to perform during a trace offs_t m_history[TRACE_LOOPS]; // history of recent PCs + bool m_detect_loops; // whether or not we should detect loops int m_loops; // number of instructions in a loop int m_nextdex; // next index bool m_trace_over; // true if we're tracing over diff --git a/src/emu/debug/debughlp.cpp b/src/emu/debug/debughlp.cpp index 8d66f59d85a..6f14f4d3e64 100644 --- a/src/emu/debug/debughlp.cpp +++ b/src/emu/debug/debughlp.cpp @@ -140,8 +140,8 @@ static const help_item static_help_list[] = " focus -- focuses debugger only on \n" " ignore [[,[,...]]] -- stops debugging on \n" " observe [[,[,...]]] -- resumes debugging on \n" - " trace {|OFF}[,[,]] -- trace the given CPU to a file (defaults to active CPU)\n" - " traceover {|OFF}[,[,]] -- trace the given CPU to a file, but skip subroutines (defaults to active CPU)\n" + " trace {|OFF}[,[,[,]]] -- trace the given CPU to a file (defaults to active CPU)\n" + " traceover {|OFF}[,[,[,]]] -- trace the given CPU to a file, but skip subroutines (defaults to active CPU)\n" " traceflush -- flushes all open trace files\n" }, { @@ -818,11 +818,14 @@ static const help_item static_help_list[] = { "trace", "\n" - " trace {|OFF}[,[,]]\n" + " trace {|OFF}[,[,[,]]]\n" "\n" "Starts or stops tracing of the execution of the specified . If is omitted, " "the currently active CPU is specified. When enabling tracing, specify the filename in the " - " parameter. To disable tracing, substitute the keyword 'off' for . If you " + " parameter. To disable tracing, substitute the keyword 'off' for . " + " should be either true or false. If is true or omitted, the trace " + "will have loops detected and condensed to a single line. If it is false, the trace will contain " + "every opcode as it is executed. If you " "wish to log additional information on each trace, you can append an parameter which " "is a command that is executed before each trace is logged. Generally, this is used to include " "a 'tracelog' command. Note that you may need to embed the action within braces { } in order " @@ -831,11 +834,14 @@ static const help_item static_help_list[] = "\n" "Examples:\n" "\n" + "trace joust.tr\n" + " Begin tracing the currently active CPU, logging output to joust.tr.\n" + "\n" "trace dribling.tr,0\n" " Begin tracing the execution of CPU #0, logging output to dribling.tr.\n" "\n" - "trace joust.tr\n" - " Begin tracing the currently active CPU, logging output to joust.tr.\n" + "trace starswep.tr,0,false\n" + " Begin tracing the execution of CPU #0, logging output to starswep.tr, with loop detection disabled.\n" "\n" "trace >>pigskin.tr\n" " Begin tracing the currently active CPU, appending log output to pigskin.tr.\n" @@ -843,39 +849,44 @@ static const help_item static_help_list[] = "trace off,0\n" " Turn off tracing on CPU #0.\n" "\n" - "trace asteroid.tr,0,{tracelog \"A=%02X \",a}\n" + "trace asteroid.tr,0,true,{tracelog \"A=%02X \",a}\n" " Begin tracing the execution of CPU #0, logging output to asteroid.tr. Before each line, " "output A= to the tracelog.\n" }, { "traceover", "\n" - " traceover {|OFF}[,[,]]\n" + " traceover {|OFF}[,[,[,]]]\n" "\n" "Starts or stops tracing of the execution of the specified . When tracing reaches " "a subroutine or call, tracing will skip over the subroutine. The same algorithm is used as is " "used in the step over command. This means that traceover will not work properly when calls " "are recusive or the return address is not immediately following the call instruction. If " - " is omitted, the currently active CPU is specified. When enabling tracing, specify the " - "filename in the parameter. To disable tracing, substitute the keyword 'off' for " - ". If you wish to log additional information on each trace, you can append an " - "parameter which is a command that is executed before each trace is logged. Generally, this is " - "used to include a 'tracelog' command. Note that you may need to embed the action within braces " - "{ } in order to prevent commas and semicolons from being interpreted as applying to the trace " - "command itself.\n" + " should be either true or false. If is true or omitted, the trace " + "will have loops detected and condensed to a single line. If it is false, the trace will contain " + "every opcode as it is executed. If is omitted, the currently active CPU is specified. When " + "enabling tracing, specify the filename in the parameter. To disable tracing, substitute " + "the keyword 'off' for . If you wish to log additional information on each trace, you can " + "append an parameter which is a command that is executed before each trace is logged. " + "Generally, this is used to include a 'tracelog' command. Note that you may need to embed the " + "action within braces { } in order to prevent commas and semicolons from being interpreted as " + "applying to the trace command itself.\n" "\n" "Examples:\n" "\n" + "traceover joust.tr\n" + " Begin tracing the currently active CPU, logging output to joust.tr.\n" + "\n" "traceover dribling.tr,0\n" " Begin tracing the execution of CPU #0, logging output to dribling.tr.\n" "\n" - "traceover joust.tr\n" - " Begin tracing the currently active CPU, logging output to joust.tr.\n" + "traceover starswep.tr,0,false\n" + " Begin tracing the execution of CPU #0, logging output to starswep.tr, with loop detection disabled.\n" "\n" "traceover off,0\n" " Turn off tracing on CPU #0.\n" "\n" - "traceover asteroid.tr,0,{tracelog \"A=%02X \",a}\n" + "traceover asteroid.tr,0,true,{tracelog \"A=%02X \",a}\n" " Begin tracing the execution of CPU #0, logging output to asteroid.tr. Before each line, " "output A= to the tracelog.\n" }, -- cgit v1.2.3