QT Debugger: Finished up the breakpoints window. [Andrew Gardner]

It now shows breakpoints for all CPUs and lets you sort by
each field.
This commit is contained in:
Andrew Gardner 2013-06-12 06:22:35 +00:00
parent 0ee305fd61
commit e74983f6f8
5 changed files with 337 additions and 58 deletions

View File

@ -2303,7 +2303,7 @@ void device_debug::halt_on_next_instruction(const char *fmt, ...)
int device_debug::breakpoint_set(offs_t address, const char *condition, const char *action)
{
// allocate a new one
breakpoint *bp = auto_alloc(m_device.machine(), breakpoint(m_symtable, m_device.machine().debugcpu_data->bpindex++, address, condition, action));
breakpoint *bp = auto_alloc(m_device.machine(), breakpoint(this, m_symtable, m_device.machine().debugcpu_data->bpindex++, address, condition, action));
// hook it into our list
bp->m_next = m_bplist;
@ -3278,13 +3278,19 @@ void device_debug::set_state(symbol_table &table, void *ref, UINT64 value)
// breakpoint - constructor
//-------------------------------------------------
device_debug::breakpoint::breakpoint(symbol_table &symbols, int index, offs_t address, const char *condition, const char *action)
: m_next(NULL),
m_index(index),
m_enabled(true),
m_address(address),
m_condition(&symbols, (condition != NULL) ? condition : "1"),
m_action((action != NULL) ? action : "")
device_debug::breakpoint::breakpoint(device_debug* debugInterface,
symbol_table &symbols,
int index,
offs_t address,
const char *condition,
const char *action)
: m_debugInterface(debugInterface),
m_next(NULL),
m_index(index),
m_enabled(true),
m_address(address),
m_condition(&symbols, (condition != NULL) ? condition : "1"),
m_action((action != NULL) ? action : "")
{
}

View File

@ -79,9 +79,15 @@ public:
public:
// construction/destruction
breakpoint(symbol_table &symbols, int index, offs_t address, const char *condition = NULL, const char *action = NULL);
breakpoint(device_debug* debugInterface,
symbol_table &symbols,
int index,
offs_t address,
const char *condition = NULL,
const char *action = NULL);
// getters
const device_debug *debugInterface() const { return m_debugInterface; }
breakpoint *next() const { return m_next; }
int index() const { return m_index; }
bool enabled() const { return m_enabled; }
@ -89,16 +95,20 @@ public:
const char *condition() const { return m_condition.original_string(); }
const char *action() const { return m_action; }
// setters
void setEnabled(bool value) { m_enabled = value; }
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
const device_debug * m_debugInterface; // the interface we were created from
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
@ -108,7 +118,14 @@ public:
public:
// construction/destruction
watchpoint(symbol_table &symbols, int index, address_space &space, int type, offs_t address, offs_t length, const char *condition = NULL, const char *action = NULL);
watchpoint(symbol_table &symbols,
int index,
address_space &space,
int type,
offs_t address,
offs_t length,
const char *condition = NULL,
const char *action = NULL);
// getters
watchpoint *next() const { return m_next; }
@ -176,6 +193,8 @@ public:
int logaddrchars(address_spacenum spacenum = AS_0) const { return (m_memory != NULL && m_memory->has_space(spacenum)) ? 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; }
device_t& device() const { return m_device; }
// hooks used by the rest of the system
void start_hook(attotime endtime);

View File

@ -2,7 +2,7 @@
dvpoints.c
Breakpoint debugger view.
Breakpoint debugger view.
****************************************************************************
@ -38,9 +38,7 @@
***************************************************************************/
#include "emu.h"
#include "debugvw.h"
#include "dvbpoints.h"
#include "debugcpu.h"
@ -53,7 +51,8 @@
//-------------------------------------------------
debug_view_breakpoints::debug_view_breakpoints(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate)
: debug_view(machine, DVT_BREAK_POINTS, osdupdate, osdprivate)
: debug_view(machine, DVT_BREAK_POINTS, osdupdate, osdprivate),
m_sortType(SORT_INDEX_ASCENDING)
{
// fail if no available sources
enumerate_sources();
@ -61,8 +60,8 @@ debug_view_breakpoints::debug_view_breakpoints(running_machine &machine, debug_v
throw std::bad_alloc();
// configure the view
m_total.y = 50; // TODO
m_supports_cursor = true;
m_total.y = 10;
m_supports_cursor = false;
}
@ -126,6 +125,55 @@ void debug_view_breakpoints::view_char(int chval)
void debug_view_breakpoints::view_click(const int button, const debug_view_xy& pos)
{
bool clickedTopRow = (m_topleft.y == pos.y);
if (clickedTopRow)
{
if (pos.x < 5 && m_sortType == SORT_INDEX_ASCENDING)
m_sortType = SORT_INDEX_DESCENDING;
else if (pos.x < 5)
m_sortType = SORT_INDEX_ASCENDING;
else if (pos.x < 9 && m_sortType == SORT_ENABLED_ASCENDING)
m_sortType = SORT_ENABLED_DESCENDING;
else if (pos.x < 9)
m_sortType = SORT_ENABLED_ASCENDING;
else if (pos.x < 31 && m_sortType == SORT_CPU_ASCENDING)
m_sortType = SORT_CPU_DESCENDING;
else if (pos.x < 31)
m_sortType = SORT_CPU_ASCENDING;
else if (pos.x < 45 && m_sortType == SORT_ADDRESS_ASCENDING)
m_sortType = SORT_ADDRESS_DESCENDING;
else if (pos.x < 45)
m_sortType = SORT_ADDRESS_ASCENDING;
else if (pos.x < 63 && m_sortType == SORT_CONDITION_ASCENDING)
m_sortType = SORT_CONDITION_DESCENDING;
else if (pos.x < 63)
m_sortType = SORT_CONDITION_ASCENDING;
else if (pos.x < 80 && m_sortType == SORT_ACTION_ASCENDING)
m_sortType = SORT_ACTION_DESCENDING;
else if (pos.x < 80)
m_sortType = SORT_ACTION_ASCENDING;
}
else
{
// Gather a sorted list of all the breakpoints for all the CPUs
device_debug::breakpoint** bpList = NULL;
const int numBPs = breakpoints(SORT_NONE, bpList);
const int bpIndex = pos.y-1;
if (bpIndex > numBPs || bpIndex < 0)
return;
// Enable / disable
if (bpList[bpIndex]->enabled())
bpList[bpIndex]->setEnabled(false);
else
bpList[bpIndex]->setEnabled(true);
delete[] bpList;
}
view_update();
}
@ -142,6 +190,174 @@ void debug_view_breakpoints::pad_astring_to_length(astring& str, int len)
}
}
// Sorting functors for the qsort function
int cIndexAscending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
return left->index() > right->index();
}
int cIndexDescending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
return left->index() < right->index();
}
int cEnabledAscending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
return left->enabled() < right->enabled();
}
int cEnabledDescending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
return left->enabled() > right->enabled();
}
int cCpuAscending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
const int result = strcmp(left->debugInterface()->device().tag(), right->debugInterface()->device().tag());
return result >= 0;
}
int cCpuDescending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
const int result = strcmp(left->debugInterface()->device().tag(), right->debugInterface()->device().tag());
return result < 0;
}
int cAddressAscending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
return left->address() > right->address();
}
int cAddressDescending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
return left->address() < right->address();
}
int cConditionAscending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
const int result = strcmp(left->condition(), right->condition());
return result >= 0;
}
int cConditionDescending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
const int result = strcmp(left->condition(), right->condition());
return result < 0;
}
int cActionAscending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
const int result = strcmp(left->action(), right->action());
return result >= 0;
}
int cActionDescending(const void* a, const void* b)
{
const device_debug::breakpoint* left = *(device_debug::breakpoint**)a;
const device_debug::breakpoint* right = *(device_debug::breakpoint**)b;
const int result = strcmp(left->action(), right->action());
return result < 0;
}
int debug_view_breakpoints::breakpoints(SortMode sort, device_debug::breakpoint**& bpList)
{
int numBPs = 0;
bpList = NULL;
for (const debug_view_source *source = m_source_list.head(); source != NULL; source = source->next())
{
// Alloc
const device_debug& debugInterface = *source->device()->debug();
for (device_debug::breakpoint *bp = debugInterface.breakpoint_first(); bp != NULL; bp = bp->next())
numBPs++;
bpList = new device_debug::breakpoint*[numBPs];
}
int bpAddIndex = 1;
for (const debug_view_source *source = m_source_list.head(); source != NULL; source = source->next())
{
device_debug& debugInterface = *source->device()->debug();
if (debugInterface.breakpoint_first() != NULL)
{
// Collect
for (device_debug::breakpoint *bp = debugInterface.breakpoint_first(); bp != NULL; bp = bp->next())
{
bpList[numBPs-bpAddIndex] = bp;
bpAddIndex++;
}
}
}
// And now for the sort
switch (m_sortType)
{
case SORT_NONE:
break;
case SORT_INDEX_ASCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cIndexAscending);
break;
case SORT_INDEX_DESCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cIndexDescending);
break;
case SORT_ENABLED_ASCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cEnabledAscending);
break;
case SORT_ENABLED_DESCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cEnabledDescending);
break;
case SORT_CPU_ASCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cCpuAscending);
break;
case SORT_CPU_DESCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cCpuDescending);
break;
case SORT_ADDRESS_ASCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cAddressAscending);
break;
case SORT_ADDRESS_DESCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cAddressDescending);
break;
case SORT_CONDITION_ASCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cConditionAscending);
break;
case SORT_CONDITION_DESCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cConditionDescending);
break;
case SORT_ACTION_ASCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cActionAscending);
break;
case SORT_ACTION_DESCENDING:
qsort(bpList, numBPs, sizeof(device_debug::breakpoint*), cActionDescending);
break;
}
return numBPs;
}
//-------------------------------------------------
// view_update - update the contents of the
// disassembly view
@ -149,38 +365,48 @@ void debug_view_breakpoints::pad_astring_to_length(astring& str, int len)
void debug_view_breakpoints::view_update()
{
const debug_view_source& source = *m_source;
const device_debug& debugInterface = *source.device()->debug();
debug_view_char *dest = m_viewdata;
// Gather a list of all the breakpoints in reverse order
int numBPs = 0;
// Gather a list of all the breakpoints for all the CPUs
device_debug::breakpoint** bpList = NULL;
if (debugInterface.breakpoint_first() != NULL)
{
// Alloc
for (device_debug::breakpoint *bp = debugInterface.breakpoint_first(); bp != NULL; bp = bp->next())
numBPs++;
bpList = new device_debug::breakpoint*[numBPs];
// Collect
int i = 1;
for (device_debug::breakpoint *bp = debugInterface.breakpoint_first(); bp != NULL; bp = bp->next())
{
bpList[numBPs-i] = bp;
i++;
}
}
const int numBPs = breakpoints(SORT_NONE, bpList);
// Set the view region so the scroll bars update
m_total.y = numBPs+1;
// Draw
debug_view_char *dest = m_viewdata;
for (int row = 0; row < m_visible.y; row++)
{
UINT32 effrow = m_topleft.y + row;
// Header
if (effrow == 0)
if (row == 0)
{
astring header = "ID En Address Condition Action";
astring header;
header.printf("ID");
if (m_sortType == SORT_INDEX_ASCENDING) header.catprintf("\\");
else if (m_sortType == SORT_INDEX_DESCENDING) header.catprintf("/");
pad_astring_to_length(header, 5);
header.catprintf("En");
if (m_sortType == SORT_ENABLED_ASCENDING) header.catprintf("\\");
else if (m_sortType == SORT_ENABLED_DESCENDING) header.catprintf("/");
pad_astring_to_length(header, 9);
header.catprintf("CPU");
if (m_sortType == SORT_CPU_ASCENDING) header.catprintf("\\");
else if (m_sortType == SORT_CPU_DESCENDING) header.catprintf("/");
pad_astring_to_length(header, 31);
header.catprintf("Address");
if (m_sortType == SORT_ADDRESS_ASCENDING) header.catprintf("\\");
else if (m_sortType == SORT_ADDRESS_DESCENDING) header.catprintf("/");
pad_astring_to_length(header, 45);
header.catprintf("Condition");
if (m_sortType == SORT_CONDITION_ASCENDING) header.catprintf("\\");
else if (m_sortType == SORT_CONDITION_DESCENDING) header.catprintf("/");
pad_astring_to_length(header, 63);
header.catprintf("Action");
if (m_sortType == SORT_ACTION_ASCENDING) header.catprintf("\\");
else if (m_sortType == SORT_ACTION_DESCENDING) header.catprintf("/");
pad_astring_to_length(header, 80);
for (int i = 0; i < m_visible.x; i++)
{
dest->byte = (i < header.len()) ? header[i] : ' ';
@ -195,34 +421,41 @@ void debug_view_breakpoints::view_update()
if (bpi < numBPs && bpi >= 0)
{
device_debug::breakpoint* bp = bpList[bpi];
astring buffer;
astring buffer;
buffer.printf("%x", bp->index());
pad_astring_to_length(buffer, 5);
buffer.catprintf("%c", bp->enabled() ? 'X' : 'O');
pad_astring_to_length(buffer, 9);
buffer.catprintf("%s", core_i64_hex_format(bp->address(), debugInterface.logaddrchars()));
pad_astring_to_length(buffer, 26);
buffer.catprintf("%s", bp->debugInterface()->device().tag());
pad_astring_to_length(buffer, 31);
buffer.catprintf("%s", core_i64_hex_format(bp->address(), bp->debugInterface()->logaddrchars()));
pad_astring_to_length(buffer, 45);
if (astring(bp->condition()) != astring("1"))
{
buffer.catprintf("%s", bp->condition());
pad_astring_to_length(buffer, 44);
pad_astring_to_length(buffer, 63);
}
if (astring(bp->action()) != astring(""))
{
buffer.catprintf("%s", bp->action());
pad_astring_to_length(buffer, 60);
pad_astring_to_length(buffer, 80);
}
for (int i = 0; i < m_visible.x; i++)
{
dest->byte = (i < buffer.len()) ? buffer[i] : ' ';
dest->attrib = DCA_NORMAL;
// Color disabled breakpoints red
if (i == 5 && dest->byte == 'O')
dest->attrib = DCA_CHANGED;
dest++;
}
continue;
}
// Fill the remaining vertical space
for (int i = 0; i < m_visible.x; i++)
{
@ -231,6 +464,6 @@ void debug_view_breakpoints::view_update()
dest++;
}
}
delete bpList;
delete[] bpList;
}

View File

@ -2,7 +2,7 @@
dvpoints.h
Breakpoint debugger view.
Breakpoint debugger view.
****************************************************************************
@ -41,6 +41,7 @@
#define __DVBPOINTS_H__
#include "debugvw.h"
#include "debugcpu.h"
//**************************************************************************
@ -63,6 +64,23 @@ class debug_view_breakpoints : public debug_view
virtual ~debug_view_breakpoints();
public:
enum SortMode
{
SORT_NONE,
SORT_INDEX_ASCENDING,
SORT_INDEX_DESCENDING,
SORT_ENABLED_ASCENDING,
SORT_ENABLED_DESCENDING,
SORT_CPU_ASCENDING,
SORT_CPU_DESCENDING,
SORT_ADDRESS_ASCENDING,
SORT_ADDRESS_DESCENDING,
SORT_CONDITION_ASCENDING,
SORT_CONDITION_DESCENDING,
SORT_ACTION_ASCENDING,
SORT_ACTION_DESCENDING
};
// getters
// setters
@ -78,8 +96,11 @@ private:
void enumerate_sources();
bool recompute(offs_t pc, int startline, int lines);
void pad_astring_to_length(astring& str, int len);
int breakpoints(SortMode sort, device_debug::breakpoint**& bpList);
// internal state
SortMode m_sortType;
};

View File

@ -10,7 +10,7 @@
BreakpointsWindow::BreakpointsWindow(running_machine* machine, QWidget* parent) :
WindowQt(machine, NULL)
{
setWindowTitle("Debug: Machine Breakpoints");
setWindowTitle("Debug: All Breakpoints");
if (parent != NULL)
{