mirror of
https://github.com/holub/mame
synced 2025-05-07 23:02:33 +03:00
Cleanup debugger interface some more.
This commit is contained in:
parent
16f14bc5f9
commit
f7ce43f8fb
@ -1280,7 +1280,7 @@ static void execute_bplist(running_machine *machine, int ref, int params, const
|
||||
debug_console_printf(machine, "Device '%s' breakpoints:\n", device->tag());
|
||||
|
||||
/* loop over the breakpoints */
|
||||
for (debug_cpu_breakpoint *bp = device->debug()->breakpoint_first(); bp != NULL; bp = bp->next())
|
||||
for (device_debug::breakpoint *bp = device->debug()->breakpoint_first(); bp != NULL; bp = bp->next())
|
||||
{
|
||||
buffer.printf("%c%4X @ %s", bp->enabled() ? ' ' : 'D', bp->index(), core_i64_hex_format(bp->address(), device->debug()->logaddrchars()));
|
||||
if (bp->condition() != NULL)
|
||||
@ -1441,7 +1441,7 @@ static void execute_wplist(running_machine *machine, int ref, int params, const
|
||||
debug_console_printf(machine, "Device '%s' %s space watchpoints:\n", device->tag(), device->debug()->watchpoint_first(spacenum)->space().name);
|
||||
|
||||
/* loop over the watchpoints */
|
||||
for (debug_cpu_watchpoint *wp = device->debug()->watchpoint_first(spacenum); wp != NULL; wp = wp->next())
|
||||
for (device_debug::watchpoint *wp = device->debug()->watchpoint_first(spacenum); wp != NULL; wp = wp->next())
|
||||
{
|
||||
buffer.printf("%c%4X @ %s-%s %s", wp->enabled() ? ' ' : 'D', wp->index(),
|
||||
core_i64_hex_format(memory_byte_to_address(&wp->space(), wp->address()), wp->space().addrchars),
|
||||
@ -2377,13 +2377,13 @@ static void execute_history(running_machine *machine, int ref, int params, const
|
||||
if (!debug_command_parameter_cpu_space(machine, (params > 0) ? param[0] : NULL, ADDRESS_SPACE_PROGRAM, &space))
|
||||
return;
|
||||
|
||||
UINT64 count = DEBUG_HISTORY_SIZE;
|
||||
UINT64 count = device_debug::HISTORY_SIZE;
|
||||
if (!debug_command_parameter_number(machine, param[1], &count))
|
||||
return;
|
||||
|
||||
/* further validation */
|
||||
if (count > DEBUG_HISTORY_SIZE)
|
||||
count = DEBUG_HISTORY_SIZE;
|
||||
if (count > device_debug::HISTORY_SIZE)
|
||||
count = device_debug::HISTORY_SIZE;
|
||||
|
||||
device_debug *debug = space->cpu->debug();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,10 +4,38 @@
|
||||
|
||||
Debugger CPU/memory interface engine.
|
||||
|
||||
Copyright Nicola Salmoria and the MAME Team.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
****************************************************************************
|
||||
|
||||
*********************************************************************/
|
||||
Copyright Aaron Giles
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name 'MAME' nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -17,104 +45,112 @@
|
||||
#include "express.h"
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
#define TRACE_LOOPS 64
|
||||
#define DEBUG_HISTORY_SIZE 256
|
||||
|
||||
#define WATCHPOINT_READ 1
|
||||
#define WATCHPOINT_WRITE 2
|
||||
#define WATCHPOINT_READWRITE (WATCHPOINT_READ | WATCHPOINT_WRITE)
|
||||
|
||||
#define DEBUG_FLAG_OBSERVING 0x00000001 /* observing this CPU */
|
||||
#define DEBUG_FLAG_HISTORY 0x00000002 /* tracking this CPU's history */
|
||||
#define DEBUG_FLAG_TRACING 0x00000004 /* tracing this CPU */
|
||||
#define DEBUG_FLAG_TRACING_OVER 0x00000008 /* tracing this CPU with step over behavior */
|
||||
#define DEBUG_FLAG_HOOKED 0x00000010 /* per-instruction callback hook */
|
||||
#define DEBUG_FLAG_STEPPING 0x00000020 /* CPU is single stepping */
|
||||
#define DEBUG_FLAG_STEPPING_OVER 0x00000040 /* CPU is stepping over a function */
|
||||
#define DEBUG_FLAG_STEPPING_OUT 0x00000080 /* CPU is stepping out of a function */
|
||||
#define DEBUG_FLAG_STOP_PC 0x00000100 /* there is a pending stop at cpu->breakpc */
|
||||
#define DEBUG_FLAG_STOP_CONTEXT 0x00000200 /* there is a pending stop on next context switch */
|
||||
#define DEBUG_FLAG_STOP_INTERRUPT 0x00000400 /* there is a pending stop on the next interrupt */
|
||||
#define DEBUG_FLAG_STOP_EXCEPTION 0x00000800 /* there is a pending stop on the next exception */
|
||||
#define DEBUG_FLAG_STOP_VBLANK 0x00001000 /* there is a pending stop on the next VBLANK */
|
||||
#define DEBUG_FLAG_STOP_TIME 0x00002000 /* there is a pending stop at cpu->stoptime */
|
||||
#define DEBUG_FLAG_LIVE_BP 0x00010000 /* there are live breakpoints for this CPU */
|
||||
|
||||
#define DEBUG_FLAG_STEPPING_ANY (DEBUG_FLAG_STEPPING | \
|
||||
DEBUG_FLAG_STEPPING_OVER | \
|
||||
DEBUG_FLAG_STEPPING_OUT)
|
||||
|
||||
#define DEBUG_FLAG_TRACING_ANY (DEBUG_FLAG_TRACING | \
|
||||
DEBUG_FLAG_TRACING_OVER)
|
||||
|
||||
#define DEBUG_FLAG_TRANSIENT (DEBUG_FLAG_STEPPING_ANY | \
|
||||
DEBUG_FLAG_STOP_PC | \
|
||||
DEBUG_FLAG_STOP_CONTEXT | \
|
||||
DEBUG_FLAG_STOP_INTERRUPT | \
|
||||
DEBUG_FLAG_STOP_EXCEPTION | \
|
||||
DEBUG_FLAG_STOP_VBLANK | \
|
||||
DEBUG_FLAG_STOP_TIME)
|
||||
const UINT8 WATCHPOINT_READ = 1;
|
||||
const UINT8 WATCHPOINT_WRITE = 2;
|
||||
const UINT8 WATCHPOINT_READWRITE = WATCHPOINT_READ | WATCHPOINT_WRITE;
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
typedef int (*debug_instruction_hook_func)(device_t &device, offs_t curpc);
|
||||
|
||||
|
||||
class debug_cpu_breakpoint;
|
||||
class debug_cpu_watchpoint;
|
||||
class debug_cpu_comment_group;
|
||||
|
||||
|
||||
class debug_trace_info
|
||||
{
|
||||
public:
|
||||
debug_trace_info();
|
||||
|
||||
FILE * file; /* tracing file for this CPU */
|
||||
astring action; /* action to perform during a trace */
|
||||
offs_t history[TRACE_LOOPS]; /* history of recent PCs */
|
||||
int loops; /* number of instructions in a loop */
|
||||
int nextdex; /* next index */
|
||||
offs_t trace_over_target; /* target for tracing over
|
||||
(0 = not tracing over,
|
||||
~0 = not currently tracing over) */
|
||||
};
|
||||
|
||||
|
||||
struct debug_hotspot_entry
|
||||
{
|
||||
offs_t access; /* access address */
|
||||
offs_t pc; /* PC of the access */
|
||||
const address_space *space; /* space where the access occurred */
|
||||
UINT32 count; /* number of hits */
|
||||
};
|
||||
|
||||
|
||||
class device_debug
|
||||
{
|
||||
typedef offs_t (*dasm_override_func)(device_t &device, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, int options);
|
||||
|
||||
public:
|
||||
// breakpoint class
|
||||
class breakpoint
|
||||
{
|
||||
friend class device_debug;
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
breakpoint(int index, offs_t address, parsed_expression *condition = NULL, const char *action = NULL);
|
||||
~breakpoint();
|
||||
|
||||
// getters
|
||||
breakpoint *next() const { return m_next; }
|
||||
int index() const { return m_index; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
offs_t address() const { return m_address; }
|
||||
const char *condition() const { return (m_condition != NULL) ? expression_original_string(m_condition) : NULL; }
|
||||
const char *action() const { return m_action; }
|
||||
|
||||
private:
|
||||
// internals
|
||||
bool hit(offs_t pc);
|
||||
|
||||
breakpoint * m_next; // next in the list
|
||||
int m_index; // user reported index
|
||||
UINT8 m_enabled; // enabled?
|
||||
offs_t m_address; // execution address
|
||||
parsed_expression * m_condition; // condition
|
||||
astring m_action; // action
|
||||
};
|
||||
|
||||
// watchpoint class
|
||||
class watchpoint
|
||||
{
|
||||
friend class device_debug;
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
watchpoint(int index, const address_space &space, int type, offs_t address, offs_t length, parsed_expression *condition = NULL, const char *action = NULL);
|
||||
~watchpoint();
|
||||
|
||||
// getters
|
||||
watchpoint *next() const { return m_next; }
|
||||
const address_space &space() const { return m_space; }
|
||||
int index() const { return m_index; }
|
||||
int type() const { return m_type; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
offs_t address() const { return m_address; }
|
||||
offs_t length() const { return m_length; }
|
||||
const char *condition() const { return (m_condition != NULL) ? expression_original_string(m_condition) : NULL; }
|
||||
const char *action() const { return m_action; }
|
||||
|
||||
private:
|
||||
// internals
|
||||
bool hit(int type, offs_t address, int size);
|
||||
|
||||
watchpoint * m_next; // next in the list
|
||||
const address_space &m_space; // address space
|
||||
int m_index; // user reported index
|
||||
bool m_enabled; // enabled?
|
||||
UINT8 m_type; // type (read/write)
|
||||
offs_t m_address; // start address
|
||||
offs_t m_length; // length of watch area
|
||||
parsed_expression * m_condition; // condition
|
||||
astring m_action; // action
|
||||
};
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
device_debug(device_t &device, symbol_table *globalsyms);
|
||||
~device_debug();
|
||||
|
||||
// getters
|
||||
symbol_table *symtable() const { return m_symtable; }
|
||||
|
||||
int logaddrchars(int spacenum = AS_PROGRAM) { return (m_memory != NULL && m_memory->space(spacenum) != NULL) ? m_memory->space(spacenum)->logaddrchars : 8; }
|
||||
|
||||
offs_t disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
|
||||
void set_dasm_override(dasm_override_func dasm_override) { m_dasm_override = dasm_override; }
|
||||
|
||||
// commonly-used pass-throughs
|
||||
offs_t pc() const { return (m_state != NULL) ? m_state->pc() : 0; }
|
||||
int logaddrchars(int spacenum = AS_PROGRAM) const { return (m_memory != NULL && m_memory->space(spacenum) != NULL) ? m_memory->space(spacenum)->logaddrchars : 8; }
|
||||
int min_opcode_bytes() const { return (m_disasm != NULL) ? m_disasm->max_opcode_bytes() : 1; }
|
||||
int max_opcode_bytes() const { return (m_disasm != NULL) ? m_disasm->max_opcode_bytes() : 1; }
|
||||
|
||||
|
||||
// hooks used by the rest of the system
|
||||
void start_hook(attotime endtime);
|
||||
void stop_hook();
|
||||
void interrupt_hook(int irqline);
|
||||
@ -123,167 +159,197 @@ public:
|
||||
void memory_read_hook(const address_space &space, offs_t address, UINT64 mem_mask);
|
||||
void memory_write_hook(const address_space &space, offs_t address, UINT64 data, UINT64 mem_mask);
|
||||
|
||||
void halt_on_next_instruction(const char *fmt, ...);
|
||||
// hooks into our operations
|
||||
void set_instruction_hook(debug_instruction_hook_func hook);
|
||||
void set_dasm_override(dasm_override_func dasm_override) { m_dasm_override = dasm_override; }
|
||||
|
||||
// disassembly
|
||||
offs_t disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
|
||||
|
||||
// debugger focus
|
||||
void ignore(bool ignore = true);
|
||||
bool observing() const { return ((m_flags & DEBUG_FLAG_OBSERVING) != 0); }
|
||||
|
||||
// single stepping
|
||||
void single_step(int numsteps = 1);
|
||||
void single_step_over(int numsteps = 1);
|
||||
void single_step_out();
|
||||
|
||||
// execution
|
||||
void go(offs_t targetpc = ~0);
|
||||
void go_vblank();
|
||||
void go_interrupt(int irqline = -1);
|
||||
void go_exception(int exception);
|
||||
void go_milliseconds(UINT64 milliseconds);
|
||||
void go_next_device();
|
||||
void halt_on_next_instruction(const char *fmt, ...);
|
||||
|
||||
debug_cpu_breakpoint *breakpoint_first() const { return m_bplist; }
|
||||
// breakpoints
|
||||
breakpoint *breakpoint_first() const { return m_bplist; }
|
||||
int breakpoint_set(offs_t address, parsed_expression *condition = NULL, const char *action = NULL);
|
||||
bool breakpoint_clear(int index);
|
||||
void breakpoint_clear_all();
|
||||
bool breakpoint_enable(int index, bool enable = true);
|
||||
void breakpoint_enable_all(bool enable = true);
|
||||
|
||||
debug_cpu_watchpoint *watchpoint_first(int spacenum) const { return m_wplist[spacenum]; }
|
||||
// watchpoints
|
||||
watchpoint *watchpoint_first(int spacenum) const { return m_wplist[spacenum]; }
|
||||
int watchpoint_set(const address_space &space, int type, offs_t address, offs_t length, parsed_expression *condition, const char *action);
|
||||
bool watchpoint_clear(int wpnum);
|
||||
void watchpoint_clear_all();
|
||||
bool watchpoint_enable(int index, bool enable = true);
|
||||
void watchpoint_enable_all(bool enable = true);
|
||||
|
||||
// hotspots
|
||||
bool hotspot_tracking_enabled() const { return (m_hotspots != NULL); }
|
||||
void hotspot_track(int numspots, int threshhold);
|
||||
|
||||
|
||||
// history
|
||||
offs_t history_pc(int index) const;
|
||||
|
||||
// tracing
|
||||
void trace(FILE *file, bool trace_over, const char *action);
|
||||
void trace_printf(const char *fmt, ...);
|
||||
void trace_flush() { if (m_trace.file != NULL) fflush(m_trace.file); }
|
||||
|
||||
void set_instruction_hook(debug_instruction_hook_func hook);
|
||||
void trace_flush() { if (m_trace != NULL) m_trace->flush(); }
|
||||
|
||||
void reset_transient_flag() { m_flags &= ~DEBUG_FLAG_TRANSIENT; }
|
||||
|
||||
static const int HISTORY_SIZE = 256;
|
||||
|
||||
private:
|
||||
// internal helpers
|
||||
void compute_debug_flags();
|
||||
void prepare_for_step_overout(offs_t pc);
|
||||
UINT32 dasm_wrapped(astring &buffer, offs_t pc);
|
||||
|
||||
void perform_trace();
|
||||
void prepare_for_step_overout();
|
||||
|
||||
// breakpoint and watchpoint helpers
|
||||
void breakpoint_update_flags();
|
||||
void breakpoint_check(offs_t pc);
|
||||
|
||||
void watchpoint_update_flags(const address_space &space);
|
||||
void watchpoint_check(const address_space &space, int type, offs_t address, UINT64 value_to_write, UINT64 mem_mask);
|
||||
|
||||
void hotspot_check(const address_space &space, offs_t address);
|
||||
UINT32 dasm_wrapped(astring &buffer, offs_t pc);
|
||||
|
||||
device_t & m_device;
|
||||
device_execute_interface *m_exec;
|
||||
device_memory_interface *m_memory;
|
||||
device_state_interface *m_state;
|
||||
device_disasm_interface *m_disasm;
|
||||
|
||||
symbol_table * m_symtable; /* symbol table for expression evaluation */
|
||||
UINT32 m_flags; /* debugging flags for this CPU */
|
||||
UINT8 m_opwidth; /* width of an opcode */
|
||||
offs_t m_stepaddr; /* step target address for DEBUG_FLAG_STEPPING_OVER */
|
||||
int m_stepsleft; /* number of steps left until done */
|
||||
offs_t m_stopaddr; /* stop address for DEBUG_FLAG_STOP_PC */
|
||||
attotime m_stoptime; /* stop time for DEBUG_FLAG_STOP_TIME */
|
||||
int m_stopirq; /* stop IRQ number for DEBUG_FLAG_STOP_INTERRUPT */
|
||||
int m_stopexception; /* stop exception number for DEBUG_FLAG_STOP_EXCEPTION */
|
||||
attotime m_endexectime; /* ending time of the current execution */
|
||||
debug_trace_info m_trace; /* trace info */
|
||||
debug_cpu_breakpoint * m_bplist; /* list of breakpoints */
|
||||
debug_hotspot_entry * m_hotspots; /* hotspot list */
|
||||
offs_t m_pc_history[DEBUG_HISTORY_SIZE]; /* history of recent PCs */
|
||||
UINT32 m_pc_history_index; /* current history index */
|
||||
int m_hotspot_count; /* number of hotspots */
|
||||
int m_hotspot_threshhold; /* threshhold for the number of hits to print */
|
||||
dasm_override_func m_dasm_override; /* pointer to provided override function */
|
||||
debug_instruction_hook_func m_instrhook; /* per-instruction callback hook */
|
||||
debug_cpu_watchpoint * m_wplist[ADDRESS_SPACES]; /* watchpoint lists for each address space */
|
||||
// symbol get/set callbacks
|
||||
static UINT64 get_current_pc(void *globalref, void *ref);
|
||||
static UINT64 get_cycles(void *globalref, void *ref);
|
||||
static UINT64 get_logunmap(void *globalref, void *ref);
|
||||
static void set_logunmap(void *globalref, void *ref, UINT64 value);
|
||||
static UINT64 get_cpu_reg(void *globalref, void *ref);
|
||||
static void set_state(void *globalref, void *ref, UINT64 value);
|
||||
|
||||
// basic device information
|
||||
device_t & m_device; // device we are attached to
|
||||
device_execute_interface *m_exec; // execute interface, if present
|
||||
device_memory_interface *m_memory; // memory interface, if present
|
||||
device_state_interface *m_state; // state interface, if present
|
||||
device_disasm_interface *m_disasm; // disasm interface, if present
|
||||
|
||||
// global state
|
||||
UINT32 m_flags; // debugging flags for this CPU
|
||||
symbol_table * m_symtable; // symbol table for expression evaluation
|
||||
debug_instruction_hook_func m_instrhook; // per-instruction callback hook
|
||||
|
||||
// disassembly
|
||||
dasm_override_func m_dasm_override; // pointer to provided override function
|
||||
UINT8 m_opwidth; // width of an opcode
|
||||
|
||||
// stepping information
|
||||
offs_t m_stepaddr; // step target address for DEBUG_FLAG_STEPPING_OVER
|
||||
int m_stepsleft; // number of steps left until done
|
||||
|
||||
// execution information
|
||||
offs_t m_stopaddr; // stop address for DEBUG_FLAG_STOP_PC
|
||||
attotime m_stoptime; // stop time for DEBUG_FLAG_STOP_TIME
|
||||
int m_stopirq; // stop IRQ number for DEBUG_FLAG_STOP_INTERRUPT
|
||||
int m_stopexception; // stop exception number for DEBUG_FLAG_STOP_EXCEPTION
|
||||
attotime m_endexectime; // ending time of the current execution
|
||||
|
||||
// history
|
||||
offs_t m_pc_history[HISTORY_SIZE]; // history of recent PCs
|
||||
UINT32 m_pc_history_index; // current history index
|
||||
|
||||
// breakpoints and watchpoints
|
||||
breakpoint * m_bplist; // list of breakpoints
|
||||
watchpoint * m_wplist[ADDRESS_SPACES]; // watchpoint lists for each address space
|
||||
|
||||
// tracing
|
||||
class tracer
|
||||
{
|
||||
public:
|
||||
tracer(device_debug &debug, FILE &file, bool trace_over, const char *action);
|
||||
~tracer();
|
||||
|
||||
void update(offs_t pc);
|
||||
void vprintf(const char *format, va_list va);
|
||||
void flush();
|
||||
|
||||
private:
|
||||
static const int TRACE_LOOPS = 64;
|
||||
|
||||
device_debug & m_debug; // reference to our owner
|
||||
FILE & m_file; // tracing file for this CPU
|
||||
astring m_action; // action to perform during a trace
|
||||
offs_t m_history[TRACE_LOOPS]; // history of recent PCs
|
||||
int m_loops; // number of instructions in a loop
|
||||
int m_nextdex; // next index
|
||||
bool m_trace_over; // true if we're tracing over
|
||||
offs_t m_trace_over_target; // target for tracing over
|
||||
// (0 = not tracing over,
|
||||
// ~0 = not currently tracing over)
|
||||
};
|
||||
tracer * m_trace; // tracer state
|
||||
|
||||
// hotspots
|
||||
struct hotspot_entry
|
||||
{
|
||||
offs_t m_access; // access address
|
||||
offs_t m_pc; // PC of the access
|
||||
const address_space *m_space; // space where the access occurred
|
||||
UINT32 m_count; // number of hits
|
||||
};
|
||||
hotspot_entry * m_hotspots; // hotspot list
|
||||
int m_hotspot_count; // number of hotspots
|
||||
int m_hotspot_threshhold; // threshhold for the number of hits to print
|
||||
|
||||
// internal flag values
|
||||
static const UINT32 DEBUG_FLAG_OBSERVING = 0x00000001; // observing this CPU
|
||||
static const UINT32 DEBUG_FLAG_HISTORY = 0x00000002; // tracking this CPU's history
|
||||
static const UINT32 DEBUG_FLAG_TRACING = 0x00000004; // tracing this CPU
|
||||
static const UINT32 DEBUG_FLAG_TRACING_OVER = 0x00000008; // tracing this CPU with step over behavior
|
||||
static const UINT32 DEBUG_FLAG_HOOKED = 0x00000010; // per-instruction callback hook
|
||||
static const UINT32 DEBUG_FLAG_STEPPING = 0x00000020; // CPU is single stepping
|
||||
static const UINT32 DEBUG_FLAG_STEPPING_OVER = 0x00000040; // CPU is stepping over a function
|
||||
static const UINT32 DEBUG_FLAG_STEPPING_OUT = 0x00000080; // CPU is stepping out of a function
|
||||
static const UINT32 DEBUG_FLAG_STOP_PC = 0x00000100; // there is a pending stop at cpu->breakpc
|
||||
static const UINT32 DEBUG_FLAG_STOP_CONTEXT = 0x00000200; // there is a pending stop on next context switch
|
||||
static const UINT32 DEBUG_FLAG_STOP_INTERRUPT = 0x00000400; // there is a pending stop on the next interrupt
|
||||
static const UINT32 DEBUG_FLAG_STOP_EXCEPTION = 0x00000800; // there is a pending stop on the next exception
|
||||
static const UINT32 DEBUG_FLAG_STOP_VBLANK = 0x00001000; // there is a pending stop on the next VBLANK
|
||||
static const UINT32 DEBUG_FLAG_STOP_TIME = 0x00002000; // there is a pending stop at cpu->stoptime
|
||||
static const UINT32 DEBUG_FLAG_LIVE_BP = 0x00010000; // there are live breakpoints for this CPU
|
||||
|
||||
static const UINT32 DEBUG_FLAG_STEPPING_ANY = DEBUG_FLAG_STEPPING | DEBUG_FLAG_STEPPING_OVER | DEBUG_FLAG_STEPPING_OUT;
|
||||
static const UINT32 DEBUG_FLAG_TRACING_ANY = DEBUG_FLAG_TRACING | DEBUG_FLAG_TRACING_OVER;
|
||||
static const UINT32 DEBUG_FLAG_TRANSIENT = DEBUG_FLAG_STEPPING_ANY | DEBUG_FLAG_STOP_PC | DEBUG_FLAG_STOP_CONTEXT |
|
||||
DEBUG_FLAG_STOP_INTERRUPT | DEBUG_FLAG_STOP_EXCEPTION | DEBUG_FLAG_STOP_VBLANK | DEBUG_FLAG_STOP_TIME;
|
||||
|
||||
public: // until comments get folded in
|
||||
debug_cpu_comment_group *m_comments; /* disassembly comments */
|
||||
};
|
||||
|
||||
|
||||
class debug_cpu_breakpoint
|
||||
{
|
||||
friend class device_debug;
|
||||
|
||||
public:
|
||||
debug_cpu_breakpoint(int index, offs_t address, parsed_expression *condition = NULL, const char *action = NULL);
|
||||
~debug_cpu_breakpoint();
|
||||
|
||||
debug_cpu_breakpoint *next() const { return m_next; }
|
||||
int index() const { return m_index; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
offs_t address() const { return m_address; }
|
||||
const char *condition() const { return (m_condition != NULL) ? expression_original_string(m_condition) : NULL; }
|
||||
const char *action() const { return m_action; }
|
||||
|
||||
private:
|
||||
bool hit(offs_t pc);
|
||||
|
||||
debug_cpu_breakpoint *m_next; /* next in the list */
|
||||
int m_index; /* user reported index */
|
||||
UINT8 m_enabled; /* enabled? */
|
||||
offs_t m_address; /* execution address */
|
||||
parsed_expression *m_condition; /* condition */
|
||||
astring m_action; /* action */
|
||||
};
|
||||
|
||||
|
||||
class debug_cpu_watchpoint
|
||||
{
|
||||
friend class device_debug;
|
||||
|
||||
public:
|
||||
debug_cpu_watchpoint(int index, const address_space &space, int type, offs_t address, offs_t length, parsed_expression *condition = NULL, const char *action = NULL);
|
||||
~debug_cpu_watchpoint();
|
||||
|
||||
debug_cpu_watchpoint *next() const { return m_next; }
|
||||
const address_space &space() const { return m_space; }
|
||||
int index() const { return m_index; }
|
||||
int type() const { return m_type; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
offs_t address() const { return m_address; }
|
||||
offs_t length() const { return m_length; }
|
||||
const char *condition() const { return (m_condition != NULL) ? expression_original_string(m_condition) : NULL; }
|
||||
const char *action() const { return m_action; }
|
||||
|
||||
private:
|
||||
bool hit(int type, offs_t address, int size);
|
||||
|
||||
debug_cpu_watchpoint *m_next; /* next in the list */
|
||||
const address_space &m_space; // address space
|
||||
int m_index; /* user reported index */
|
||||
bool m_enabled; /* enabled? */
|
||||
UINT8 m_type; /* type (read/write) */
|
||||
offs_t m_address; /* start address */
|
||||
offs_t m_length; /* length of watch area */
|
||||
parsed_expression *m_condition; /* condition */
|
||||
astring m_action; /* action */
|
||||
debug_cpu_comment_group *m_comments; // disassembly comments
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
GLOBAL VARIABLES
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
//**************************************************************************
|
||||
|
||||
extern const express_callbacks debug_expression_callbacks;
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
//**************************************************************************
|
||||
// FUNCTION PROTOTYPES
|
||||
//**************************************************************************
|
||||
|
||||
/* ----- initialization and cleanup ----- */
|
||||
|
||||
@ -318,13 +384,6 @@ symbol_table *debug_cpu_get_visible_symtable(running_machine *machine);
|
||||
|
||||
|
||||
|
||||
/* ----- memory and disassembly helpers ----- */
|
||||
|
||||
/* return the physical address corresponding to the given logical address */
|
||||
int debug_cpu_translate(const address_space *space, int intention, offs_t *address);
|
||||
|
||||
|
||||
|
||||
/* ----- misc debugger functions ----- */
|
||||
|
||||
/* specifies a debug command script to execute */
|
||||
@ -334,6 +393,9 @@ void debug_cpu_source_script(running_machine *machine, const char *file);
|
||||
|
||||
/* ----- debugger memory accessors ----- */
|
||||
|
||||
/* return the physical address corresponding to the given logical address */
|
||||
int debug_cpu_translate(const address_space *space, int intention, offs_t *address);
|
||||
|
||||
/* return a byte from the the specified memory space */
|
||||
UINT8 debug_read_byte(const address_space *space, offs_t address, int apply_translation);
|
||||
|
||||
@ -367,4 +429,5 @@ void debug_write_memory(const address_space *space, offs_t address, UINT64 data,
|
||||
/* read 1,2,4 or 8 bytes at the given offset from opcode space */
|
||||
UINT64 debug_read_opcode(const address_space *space, offs_t offset, int size, int arg);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -578,7 +578,7 @@ recompute:
|
||||
// if we're on a line with a breakpoint, tag it changed
|
||||
else
|
||||
{
|
||||
for (debug_cpu_breakpoint *bp = source.m_device.debug()->breakpoint_first(); bp != NULL; bp = bp->next())
|
||||
for (device_debug::breakpoint *bp = source.m_device.debug()->breakpoint_first(); bp != NULL; bp = bp->next())
|
||||
if (m_byteaddress[effrow] == (memory_address_to_byte(source.m_space, bp->address()) & source.m_space->logbytemask))
|
||||
attrib = DCA_CHANGED;
|
||||
}
|
||||
|
14
src/emu/ui.c
14
src/emu/ui.c
@ -1005,24 +1005,20 @@ astring &game_info_astring(running_machine *machine, astring &string)
|
||||
|
||||
/* loop over all CPUs */
|
||||
device_execute_interface *exec;
|
||||
int count = 1;
|
||||
for (bool gotone = machine->m_devicelist.first(exec); gotone; gotone = exec->next(exec))
|
||||
{
|
||||
// skip over any we already claimed
|
||||
if (--count != 0)
|
||||
continue;
|
||||
|
||||
/* get cpu specific clock that takes internal multiplier/dividers into account */
|
||||
int clock = exec->device().clock();
|
||||
|
||||
/* count how many identical CPUs we have */
|
||||
count = 1;
|
||||
int count = 1;
|
||||
device_execute_interface *scan;
|
||||
for (bool gotone = exec->next(scan); gotone; gotone = scan->next(scan))
|
||||
{
|
||||
if (exec->device().type() != scan->device().type() || exec->device().clock() != scan->device().clock())
|
||||
break;
|
||||
count++;
|
||||
exec = scan;
|
||||
}
|
||||
|
||||
/* if more than one, prepend a #x in front of the CPU name */
|
||||
@ -1047,9 +1043,9 @@ astring &game_info_astring(running_machine *machine, astring &string)
|
||||
found_sound = TRUE;
|
||||
|
||||
/* count how many identical sound chips we have */
|
||||
count = 1;
|
||||
device_sound_interface *scan = sound;
|
||||
for (bool gotanother = scan->next(scan); gotanother; gotanother = scan->next(scan))
|
||||
int count = 1;
|
||||
device_sound_interface *scan;
|
||||
for (bool gotanother = sound->next(scan); gotanother; gotanother = scan->next(scan))
|
||||
{
|
||||
if (sound->device().type() != scan->device().type() || sound->device().clock() != scan->device().clock())
|
||||
break;
|
||||
|
@ -872,9 +872,9 @@ void console_create_window(running_machine *machine)
|
||||
|
||||
@implementation MAMEDisassemblyView
|
||||
|
||||
- (debug_cpu_breakpoint *)findBreakpointAtAddress:(offs_t)address inAddressSpace:(const address_space *)space {
|
||||
- (device_debug::breakpoint *)findBreakpointAtAddress:(offs_t)address inAddressSpace:(const address_space *)space {
|
||||
cpu_debug_data *cpuinfo = cpu_get_debug_data(space->cpu);
|
||||
debug_cpu_breakpoint *bp;
|
||||
device_debug::breakpoint *bp;
|
||||
for (bp = cpuinfo->bplist; (bp != NULL) && (address != bp->address); bp = bp->next) {}
|
||||
return bp;
|
||||
}
|
||||
@ -946,7 +946,7 @@ void console_create_window(running_machine *machine)
|
||||
SEL action = [item action];
|
||||
BOOL inContextMenu = ([item menu] == [self menu]);
|
||||
BOOL haveCursor = NO, isCurrent = NO;
|
||||
debug_cpu_breakpoint *breakpoint = NULL;
|
||||
device_debug::breakpoint *breakpoint = NULL;
|
||||
|
||||
if (view->cursor_visible()) {
|
||||
if (debug_cpu_get_visible_cpu(machine) == view->source()->device()) {
|
||||
@ -1078,7 +1078,7 @@ void console_create_window(running_machine *machine)
|
||||
const address_space *space = downcast<const debug_view_disasm_source *>(view->source())->space();
|
||||
if (!useConsole || (debug_cpu_get_visible_cpu(machine) == space->cpu)) {
|
||||
offs_t address = downcast<debug_view_disasm *>(view)->selected_address();
|
||||
debug_cpu_breakpoint *bp = [self findBreakpointAtAddress:address inAddressSpace:space];
|
||||
device_debug::breakpoint *bp = [self findBreakpointAtAddress:address inAddressSpace:space];
|
||||
|
||||
// if it doesn't exist, add a new one
|
||||
if (useConsole) {
|
||||
@ -1104,7 +1104,7 @@ void console_create_window(running_machine *machine)
|
||||
const address_space *space = downcast<const debug_view_disasm_source *>(view->source())->space();
|
||||
if (!useConsole || (debug_cpu_get_visible_cpu(machine) == space->cpu)) {
|
||||
offs_t address = downcast<debug_view_disasm *>(view)->selected_address();
|
||||
debug_cpu_breakpoint *bp = [self findBreakpointAtAddress:address inAddressSpace:space];
|
||||
device_debug::breakpoint *bp = [self findBreakpointAtAddress:address inAddressSpace:space];
|
||||
|
||||
if (bp != NULL) {
|
||||
NSString *command;
|
||||
|
@ -1011,7 +1011,7 @@ on_set_breakpoint_at_cursor_activate(GtkWidget *win)
|
||||
{
|
||||
offs_t address = downcast<debug_view_disasm *>(disasm->view)->selected_address();
|
||||
device_debug *cpuinfo = disasm->view->source()->device()->debug();
|
||||
debug_cpu_breakpoint *bp;
|
||||
device_debug::breakpoint *bp;
|
||||
INT32 bpindex = -1;
|
||||
|
||||
/* first find an existing breakpoint at this address */
|
||||
|
@ -2255,7 +2255,7 @@ static int disasm_handle_command(debugwin_info *info, WPARAM wparam, LPARAM lpar
|
||||
INT32 bpindex = -1;
|
||||
|
||||
/* first find an existing breakpoint at this address */
|
||||
for (debug_cpu_breakpoint *bp = debug->breakpoint_first(); bp != NULL; bp = bp->next())
|
||||
for (device_debug::breakpoint *bp = debug->breakpoint_first(); bp != NULL; bp = bp->next())
|
||||
if (address == bp->address())
|
||||
{
|
||||
bpindex = bp->index();
|
||||
|
Loading…
Reference in New Issue
Block a user