summaryrefslogtreecommitdiff
path: root/src/plugins/debugger/registerhandler.cpp
diff options
context:
space:
mode:
authorhjk <qtc-committer@nokia.com>2011-08-31 16:45:44 +0200
committerhjk <qthjk@ovi.com>2011-08-31 16:51:54 +0200
commit188156977ca956e7366923682021322afac4a055 (patch)
tree2d6220871481b1a815361a35989b985868bbc975 /src/plugins/debugger/registerhandler.cpp
parent5d82ba7d87d0d2576108f4c8852fb0a553108145 (diff)
downloadqt-creator-188156977ca956e7366923682021322afac4a055.tar.gz
debugger: prepare support for partial register display
Change-Id: I74e971cfb41afbdd07f4193c14c3bb7ecd634859 Reviewed-on: http://codereview.qt.nokia.com/3990 Reviewed-by: hjk <qthjk@ovi.com>
Diffstat (limited to 'src/plugins/debugger/registerhandler.cpp')
-rw-r--r--src/plugins/debugger/registerhandler.cpp309
1 files changed, 276 insertions, 33 deletions
diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp
index bc9d8248a5..ebd739b95a 100644
--- a/src/plugins/debugger/registerhandler.cpp
+++ b/src/plugins/debugger/registerhandler.cpp
@@ -33,29 +33,231 @@
#include "registerhandler.h"
#include "watchdelegatewidgets.h"
+#if USE_REGISTER_MODEL_TEST
+#include "modeltest.h"
+#endif
+
+#include <utils/qtcassert.h>
+
+namespace Debugger {
+namespace Internal {
+
//////////////////////////////////////////////////////////////////
//
-// RegisterHandler
+// Register
//
//////////////////////////////////////////////////////////////////
-namespace Debugger {
-namespace Internal {
+enum RegisterType
+{
+ RegisterUnknown,
+ //RegisterDummy, // like AH if EAX is present.
+ RegisterI8,
+ RegisterI16,
+ RegisterI32,
+ RegisterI64,
+ RegisterF32,
+ RegisterF64,
+ RegisterF80,
+ RegisterXMM,
+ RegisterMMX,
+ RegisterNeon,
+ RegisterFlags32
+};
+
+static struct RegisterNameAndType
+{
+ const char *name;
+ RegisterType type;
+} theNameAndType[] = {
+ { "eax", RegisterI32 },
+ { "ecx", RegisterI32 },
+ { "edx", RegisterI32 },
+ { "ebx", RegisterI32 },
+ { "esp", RegisterI32 },
+ { "ebp", RegisterI32 },
+ { "esi", RegisterI32 },
+ { "edi", RegisterI32 },
+ { "eip", RegisterI32 },
+ { "eflags", RegisterFlags32 },
+ { "cs", RegisterI32 },
+ { "ss", RegisterI32 },
+ { "ds", RegisterI32 },
+ { "es", RegisterI32 },
+ { "fs", RegisterI32 },
+ { "gs", RegisterI32 },
+ { "st0", RegisterF80 },
+ { "st1", RegisterF80 },
+ { "st2", RegisterF80 },
+ { "st3", RegisterF80 },
+ { "st4", RegisterF80 },
+ { "st5", RegisterF80 },
+ { "st6", RegisterF80 },
+ { "st7", RegisterF80 },
+ { "fctrl", RegisterFlags32 },
+ { "fstat", RegisterFlags32 },
+ { "ftag", RegisterFlags32 },
+ { "fiseg", RegisterFlags32 },
+ { "fioff", RegisterFlags32 },
+ { "foseg", RegisterFlags32 },
+ { "fooff", RegisterFlags32 },
+ { "fop", RegisterFlags32 },
+ { "xmm0", RegisterXMM },
+ { "xmm1", RegisterXMM },
+ { "xmm2", RegisterXMM },
+ { "xmm3", RegisterXMM },
+ { "xmm4", RegisterXMM },
+ { "xmm5", RegisterXMM },
+ { "xmm6", RegisterXMM },
+ { "xmm7", RegisterXMM },
+ { "mxcsr", RegisterFlags32 },
+ { "orig_eax", RegisterI32 },
+ { "al", RegisterI8 },
+ { "cl", RegisterI8 },
+ { "dl", RegisterI8 },
+ { "bl", RegisterI8 },
+ { "ah", RegisterI8 },
+ { "ch", RegisterI8 },
+ { "dh", RegisterI8 },
+ { "bh", RegisterI8 },
+ { "ax", RegisterI16 },
+ { "cx", RegisterI16 },
+ { "dx", RegisterI16 },
+ { "bx", RegisterI16 },
+ { "bp", RegisterI16 },
+ { "si", RegisterI16 },
+ { "di", RegisterI16 },
+ { "mm0", RegisterMMX },
+ { "mm1", RegisterMMX },
+ { "mm2", RegisterMMX },
+ { "mm3", RegisterMMX },
+ { "mm4", RegisterMMX },
+ { "mm5", RegisterMMX },
+ { "mm6", RegisterMMX },
+ { "mm7", RegisterMMX }
+ };
+
+static RegisterType guessType(const QByteArray &name)
+{
+ static QHash<QByteArray, RegisterType> theTypes;
+ if (theTypes.isEmpty()) {
+ for (int i = 0; i != sizeof(theNameAndType) / sizeof(theNameAndType[0]); ++i)
+ theTypes[theNameAndType[i].name] = theNameAndType[i].type;
+ }
+ return theTypes.value(name, RegisterUnknown);
+}
+
+static int childCountFromType(int type)
+{
+ switch (type) {
+ case RegisterUnknown: return 0;
+ case RegisterI8: return 0;
+ case RegisterI16: return 1;
+ case RegisterI32: return 2;
+ case RegisterI64: return 3;
+ case RegisterF32: return 0;
+ case RegisterF64: return 0;
+ case RegisterF80: return 0;
+ case RegisterXMM: return 3;
+ case RegisterMMX: return 3;
+ case RegisterNeon: return 3;
+ case RegisterFlags32: return 0;
+ }
+ QTC_ASSERT(false, /**/);
+ return 0;
+}
+
+static int bitWidthFromType(int type, int subType)
+{
+ const uint integer[] = { 8, 16, 32, 64 };
+ const uint xmm[] = { 8, 16, 32, 64 };
+ const uint mmx[] = { 8, 16, 32, 64 };
+ const uint neon[] = { 8, 16, 32, 64 };
+
+ switch (type) {
+ case RegisterUnknown: return 0;
+ case RegisterI8: return 8;
+ case RegisterI16: return integer[subType];
+ case RegisterI32: return integer[subType];
+ case RegisterI64: return integer[subType];
+ case RegisterF32: return 0;
+ case RegisterF64: return 0;
+ case RegisterF80: return 0;
+ case RegisterXMM: return xmm[subType];
+ case RegisterMMX: return mmx[subType];
+ case RegisterNeon: return neon[subType];
+ case RegisterFlags32: return 0;
+ }
+ QTC_ASSERT(false, /**/);
+ return 0;
+}
+
+Register::Register(const QByteArray &name_)
+ : name(name_), changed(true)
+{
+ type = guessType(name);
+}
+
+
+//////////////////////////////////////////////////////////////////
+//
+// RegisterHandler
+//
+//////////////////////////////////////////////////////////////////
RegisterHandler::RegisterHandler()
- : m_base(-1)
{
- setNumberBase(16);
+ m_base = 16;
+ calculateWidth();
+#if USE_REGISTER_MODEL_TEST
+ new ModelTest(this, 0);
+#endif
+}
+
+int RegisterHandler::rowCount(const QModelIndex &idx) const
+{
+ if (idx.column() > 0)
+ return 0;
+ if (!idx.isValid())
+ return m_registers.size(); // Top level.
+ if (idx.internalId() >= 0)
+ return 0; // Sub-Items don't have children.
+ if (idx.row() >= m_registers.size())
+ return 0;
+ return childCountFromType(m_registers[idx.row()].type);
+}
+
+int RegisterHandler::columnCount(const QModelIndex &idx) const
+{
+ if (idx.column() > 0)
+ return 0;
+ if (!idx.isValid())
+ return 2;
+ if (idx.internalId() >= 0)
+ return 0; // Sub-Items don't have children.
+ return 2;
}
-int RegisterHandler::rowCount(const QModelIndex &parent) const
+QModelIndex RegisterHandler::index(int row, int col, const QModelIndex &parent) const
{
- return parent.isValid() ? 0 : m_registers.size();
+ if (row < 0 || col < 0 || col >= 2)
+ return QModelIndex();
+ if (!parent.isValid()) // Top level.
+ return createIndex(row, col, -1);
+ if (parent.internalId() >= 0) // Sub-Item has no children.
+ return QModelIndex();
+ if (parent.column() > 0)
+ return QModelIndex();
+ return createIndex(row, col, parent.row());
}
-int RegisterHandler::columnCount(const QModelIndex &parent) const
+QModelIndex RegisterHandler::parent(const QModelIndex &idx) const
{
- return parent.isValid() ? 0 : 2;
+ if (!idx.isValid())
+ return QModelIndex();
+ if (idx.internalId() >= 0)
+ return createIndex(idx.internalId(), 0, -1);
+ return QModelIndex();
}
// Editor value: Preferably number, else string.
@@ -83,27 +285,67 @@ QString Register::displayValue(int base, int strlen) const
QVariant RegisterHandler::data(const QModelIndex &index, int role) const
{
- if (!index.isValid() || index.row() >= m_registers.size())
+ if (!index.isValid())
+ return QVariant();
+
+ QModelIndex topLevel = index.parent();
+ const int mainRow = topLevel.isValid() ? topLevel.row() : index.row();
+
+ if (mainRow >= m_registers.size())
return QVariant();
- const Register &reg = m_registers.at(index.row());
- switch (role) {
- case Qt::DisplayRole:
- switch (index.column()) {
- case 0: {
- const QString padding = QLatin1String(" ");
- return QVariant(padding + reg.name + padding);
+ const Register &reg = m_registers.at(mainRow);
+
+ if (topLevel.isValid()) {
+ //
+ // Nested
+ //
+ int subType = index.row();
+ int bitWidth = bitWidthFromType(reg.type, subType);
+
+ switch (role) {
+ case Qt::DisplayRole:
+ switch (index.column()) {
+ case 0: {
+ switch (bitWidth) {
+ case 8: return "[Bytes]";
+ case 16: return "[Words]";
+ case 32: return "[DWords]";
+ case 64: return "[QWords]";
+ case -32: return "[Single]";
+ case -64: return "[Double]";
+ return QVariant(bitWidth);
+ }
+ }
+ }
+ default:
+ break;
+ }
+
+ } else {
+ //
+ // Toplevel
+ //
+
+ switch (role) {
+ case Qt::DisplayRole:
+ switch (index.column()) {
+ case 0: {
+ const QString padding = QLatin1String(" ");
+ return QVariant(padding + reg.name + padding);
+ //return QVariant(reg.name);
+ }
+ case 1: // Display: Pad value for alignment
+ return reg.displayValue(m_base, m_strlen);
+ } // switch column
+ case Qt::EditRole: // Edit: Unpadded for editing
+ return reg.editValue();
+ case Qt::TextAlignmentRole:
+ return index.column() == 1 ? QVariant(Qt::AlignRight) : QVariant();
+ default:
+ break;
}
- case 1: // Display: Pad value for alignment
- return reg.displayValue(m_base, m_strlen);
- } // switch column
- case Qt::EditRole: // Edit: Unpadded for editing
- return reg.editValue();
- case Qt::TextAlignmentRole:
- return index.column() == 1 ? QVariant(Qt::AlignRight) : QVariant();
- default:
- break;
}
return QVariant();
}
@@ -113,8 +355,8 @@ QVariant RegisterHandler::headerData(int section, Qt::Orientation orientation,
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
- case 0: return tr("Name");
- case 1: return tr("Value (base %1)").arg(m_base);
+ case 0: return tr("Name");
+ case 1: return tr("Value (Base %1)").arg(m_base);
};
}
return QVariant();
@@ -128,7 +370,7 @@ Qt::ItemFlags RegisterHandler::flags(const QModelIndex &idx) const
const Qt::ItemFlags notEditable = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
// Can edit registers if they are hex numbers and not arrays.
if (idx.column() == 1
- && IntegerWatchLineEdit::isUnsignedHexNumber(m_registers.at(idx.row()).value))
+ && IntegerWatchLineEdit::isUnsignedHexNumber(m_registers.at(idx.row()).value))
return notEditable | Qt::ItemIsEditable;
return notEditable;
}
@@ -173,15 +415,16 @@ void RegisterHandler::setAndMarkRegisters(const Registers &registers)
return;
}
const int size = m_registers.size();
- for (int r = 0; r < size; r++) {
- const QModelIndex regIndex = index(r, 1);
+ for (int r = 0; r != size; ++r) {
+ const QModelIndex regIndex = index(r, 1, QModelIndex());
if (m_registers.at(r).value != registers.at(r).value) {
// Indicate red if values change, keep changed.
- m_registers[r].changed = m_registers[r].changed || !m_registers.at(r).value.isEmpty();
+ m_registers[r].changed = m_registers.at(r).changed
+ || !m_registers.at(r).value.isEmpty();
m_registers[r].value = registers.at(r).value;
emit dataChanged(regIndex, regIndex);
}
- emit registerSet(regIndex); // notify attached memory views.
+ emit registerSet(regIndex); // Notify attached memory views.
}
}