Commit 29322b61 authored by hjk's avatar hjk

Debugger: Polish register view

Right-align subregister values, drop the 0x prefix for hex values,
add a subitem with ASCII representation and tooltips for subitems.

Change-Id: I6a5764fa5ef8b2bfd916cdd828d949a82304503d
Reviewed-by: default avatarChristian Stenger <christian.stenger@theqtcompany.com>
parent 76a8606c
......@@ -252,14 +252,29 @@ void Register::guessMissingData()
fixup(this, IntegerRegister, 0);
}
static QString subTypeName(RegisterKind kind, int size)
static QString subTypeName(RegisterKind kind, int size, RegisterFormat format)
{
if (kind == IntegerRegister)
return QString::fromLatin1("[i%1]").arg(size * 8);
if (kind == FloatRegister)
return QString::fromLatin1("[f%1]").arg(size * 8);
QTC_ASSERT(false, /**/);
return QString();
QString name(QLatin1Char('['));
switch (kind) {
case IntegerRegister: name += QLatin1Char('i'); break;
case FloatRegister: name += QLatin1Char('f'); break;
default: break;
}
name += QString::number(size);
switch (format) {
case BinaryFormat: name += QLatin1Char('b'); break;
case OctalFormat: name += QLatin1Char('o'); break;
case DecimalFormat: name += QLatin1Char('d'); break;
case HexadecimalFormat: name += QLatin1Char('x'); break;
case CharacterFormat: name += QLatin1Char('c'); break;
}
name += QLatin1Char(']');
return name;
}
static uint decodeHexChar(unsigned char c)
......@@ -305,15 +320,29 @@ bool RegisterValue::operator==(const RegisterValue &other)
return v.u64[0] == other.v.u64[0] && v.u64[1] == other.v.u64[1];
}
static QByteArray format(quint64 v, int base, int size)
static QByteArray formatRegister(quint64 v, int size, RegisterFormat format)
{
QByteArray result = QByteArray::number(v, base);
if (base == 16)
QByteArray result;
if (format == HexadecimalFormat) {
result = QByteArray::number(v, 16);
result.prepend(QByteArray(2*size - result.size(), '0'));
} else if (format == DecimalFormat) {
result = QByteArray::number(v, 10);
result.prepend(QByteArray(2*size - result.size(), ' '));
} else if (format == CharacterFormat) {
if (v >= 32 && v < 127) {
result += '\'';
result += char(v);
result += '\'';
} else {
result += " ";
}
result.prepend(QByteArray(2*size - result.size(), ' '));
}
return result;
}
QByteArray RegisterValue::toByteArray(int base, RegisterKind kind, int size) const
QByteArray RegisterValue::toByteArray(RegisterKind kind, int size, RegisterFormat format) const
{
if (!known)
return "[inaccessible]";
......@@ -326,15 +355,12 @@ QByteArray RegisterValue::toByteArray(int base, RegisterKind kind, int size) con
QByteArray result;
if (size > 8) {
result += format(v.u64[1], base, size - 8);
result += formatRegister(v.u64[1], size - 8, format);
size = 8;
if (base != 16)
if (format != HexadecimalFormat)
result += ',';
}
result += format(v.u64[0], base, size);
if (base == 16)
result.prepend("0x");
return result;
return result + formatRegister(v.u64[0], size, format);
}
RegisterValue RegisterValue::subValue(int size, int index) const
......@@ -367,8 +393,8 @@ RegisterValue RegisterValue::subValue(int size, int index) const
class RegisterSubItem : public Utils::TreeItem
{
public:
RegisterSubItem(RegisterKind subKind, int subSize, int count)
: m_subKind(subKind), m_subSize(subSize), m_count(count), m_changed(false)
RegisterSubItem(RegisterKind subKind, int subSize, int count, RegisterFormat format)
: m_subKind(subKind), m_subFormat(format), m_subSize(subSize), m_count(count), m_changed(false)
{}
QVariant data(int column, int role) const;
......@@ -382,6 +408,7 @@ public:
}
RegisterKind m_subKind;
RegisterFormat m_subFormat;
int m_subSize;
int m_count;
bool m_changed;
......@@ -398,23 +425,27 @@ public:
quint64 addressValue() const;
Register m_reg;
int m_base;
RegisterFormat m_format;
bool m_changed;
};
RegisterItem::RegisterItem(const Register &reg) :
m_reg(reg), m_base(16), m_changed(true)
m_reg(reg), m_format(HexadecimalFormat), m_changed(true)
{
if (m_reg.kind == UnknownRegister)
m_reg.guessMissingData();
if (m_reg.kind == IntegerRegister || m_reg.kind == VectorRegister) {
for (int s = m_reg.size / 2; s; s = s / 2)
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s));
for (int s = m_reg.size / 2; s; s = s / 2) {
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, HexadecimalFormat));
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, DecimalFormat));
if (s == 1)
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, CharacterFormat));
}
}
if (m_reg.kind == IntegerRegister || m_reg.kind == VectorRegister) {
for (int s = m_reg.size; s >= 4; s = s / 2)
appendChild(new RegisterSubItem(FloatRegister, s, m_reg.size / s));
appendChild(new RegisterSubItem(FloatRegister, s, m_reg.size / s, DecimalFormat));
}
}
......@@ -444,12 +475,12 @@ QVariant RegisterItem::data(int column, int role) const
case RegisterChangedRole:
return m_changed;
case RegisterNumberBaseRole:
return m_base;
case RegisterAsAddressRole:
return addressValue();
case RegisterFormatRole:
return m_format;
case Qt::DisplayRole:
switch (column) {
case RegisterNameColumn: {
......@@ -459,17 +490,17 @@ QVariant RegisterItem::data(int column, int role) const
return res;
}
case RegisterValueColumn: {
return m_reg.value.toByteArray(m_base, m_reg.kind, m_reg.size);
return m_reg.value.toByteArray(m_reg.kind, m_reg.size, m_format);
}
}
case Qt::ToolTipRole:
return QString::fromLatin1("Current Value: %1\nPreviousValue: %2")
.arg(QString::fromLatin1(m_reg.value.toByteArray(m_base, m_reg.kind, m_reg.size)))
.arg(QString::fromLatin1(m_reg.previousValue.toByteArray(m_base, m_reg.kind, m_reg.size)));
.arg(QString::fromLatin1(m_reg.value.toByteArray(m_reg.kind, m_reg.size, m_format)))
.arg(QString::fromLatin1(m_reg.previousValue.toByteArray(m_reg.kind, m_reg.size, m_format)));
case Qt::EditRole: // Edit: Unpadded for editing
return m_reg.value.toByteArray(m_base, m_reg.kind, m_reg.size);
return m_reg.value.toByteArray(m_reg.kind, m_reg.size, m_format);
case Qt::TextAlignmentRole:
return column == RegisterValueColumn ? QVariant(Qt::AlignRight) : QVariant();
......@@ -486,8 +517,10 @@ QVariant RegisterSubItem::data(int column, int role) const
case RegisterChangedRole:
return m_changed;
case RegisterNumberBaseRole:
return 16;
case RegisterFormatRole: {
RegisterItem *registerItem = static_cast<RegisterItem *>(parent());
return int(registerItem->m_format);
}
case RegisterAsAddressRole:
return 0;
......@@ -495,20 +528,32 @@ QVariant RegisterSubItem::data(int column, int role) const
case Qt::DisplayRole:
switch (column) {
case RegisterNameColumn:
return subTypeName(m_subKind, m_subSize);
return subTypeName(m_subKind, m_subSize, m_subFormat);
case RegisterValueColumn: {
QTC_ASSERT(parent(), return QVariant());
RegisterItem *registerItem = static_cast<RegisterItem *>(parent());
RegisterValue value = registerItem->m_reg.value;
QByteArray ba;
for (int i = 0; i != m_count; ++i) {
ba += value.subValue(m_subSize, i).toByteArray(16, m_subKind, m_subSize);
int tab = 5 * (i + 1) * m_subSize;
ba += QByteArray(tab - ba.size(), ' ');
QByteArray b = value.subValue(m_subSize, i).toByteArray(m_subKind, m_subSize, m_subFormat);
ba += QByteArray(tab - ba.size() - b.size(), ' ');
ba += b;
}
return ba;
}
}
case Qt::ToolTipRole:
if (m_subKind == IntegerRegister) {
if (m_subFormat == CharacterFormat)
return RegisterHandler::tr("Content as ASCII Characters");
else
return RegisterHandler::tr("Content as %1-bit Integer Values").arg(8 * m_subSize);
}
if (m_subKind == FloatRegister)
return RegisterHandler::tr("Contents as %1-bit Floating Point Values").arg(8 * m_subSize);
default:
break;
}
......@@ -553,11 +598,11 @@ void RegisterHandler::updateRegister(const Register &r)
}
}
void RegisterHandler::setNumberBase(const QByteArray &name, int base)
void RegisterHandler::setNumberFormat(const QByteArray &name, RegisterFormat format)
{
RegisterItem *reg = m_registerByName.value(name, 0);
QTC_ASSERT(reg, return);
reg->m_base = base;
reg->m_format = format;
QModelIndex index = indexFromItem(reg);
emit dataChanged(index, index);
}
......
......@@ -52,7 +52,7 @@ enum RegisterDataRole
RegisterNameRole = Qt::UserRole,
RegisterIsBigRole,
RegisterChangedRole,
RegisterNumberBaseRole,
RegisterFormatRole,
RegisterAsAddressRole
};
......@@ -66,6 +66,15 @@ enum RegisterKind
OtherRegister
};
enum RegisterFormat
{
CharacterFormat,
HexadecimalFormat,
DecimalFormat,
OctalFormat,
BinaryFormat
};
class RegisterValue
{
public:
......@@ -73,7 +82,7 @@ public:
void operator=(const QByteArray &ba);
bool operator==(const RegisterValue &other);
bool operator!=(const RegisterValue &other) { return !operator==(other); }
QByteArray toByteArray(int base, RegisterKind kind, int size) const;
QByteArray toByteArray(RegisterKind kind, int size, RegisterFormat format) const;
RegisterValue subValue(int size, int index) const;
union {
......@@ -116,7 +125,7 @@ public:
void updateRegister(const Register &reg);
void setNumberBase(const QByteArray &name, int base);
void setNumberFormat(const QByteArray &name, RegisterFormat format);
void commitUpdates() { emit layoutChanged(); }
RegisterMap registerMap() const;
......
......@@ -66,11 +66,20 @@ public:
const QModelIndex &index) const
{
IntegerWatchLineEdit *lineEdit = new IntegerWatchLineEdit(parent);
const int base = index.data(RegisterNumberBaseRole).toInt();
const RegisterFormat format = RegisterFormat(index.data(RegisterFormatRole).toInt());
const bool big = index.data(RegisterIsBigRole).toBool();
// Big integers are assumed to be hexadecimal.
int base = 16;
if (!big) {
if (format == DecimalFormat)
base = 10;
else if (format == OctalFormat)
base = 8;
else if (format == BinaryFormat)
base = 2;
}
lineEdit->setBigInt(big);
lineEdit->setBase(big ? 16 : base);
lineEdit->setBase(base);
lineEdit->setSigned(false);
lineEdit->setAlignment(Qt::AlignRight);
lineEdit->setFrame(false);
......@@ -91,9 +100,9 @@ public:
return;
IntegerWatchLineEdit *lineEdit = qobject_cast<IntegerWatchLineEdit*>(editor);
QTC_ASSERT(lineEdit, return);
const int base = index.data(RegisterNumberBaseRole).toInt();
const RegisterFormat format = RegisterFormat(index.data(RegisterFormatRole).toInt());
QString value = lineEdit->text();
if (base == 16 && !value.startsWith(QLatin1String("0x")))
if (format == HexadecimalFormat && !value.startsWith(QLatin1String("0x")))
value.insert(0, QLatin1String("0x"));
currentEngine()->setRegisterValue(index.data(RegisterNameRole).toByteArray(), value);
}
......@@ -206,19 +215,19 @@ void RegisterTreeView::contextMenuEvent(QContextMenuEvent *ev)
}
menu.addSeparator();
const int base = idx.data(RegisterNumberBaseRole).toInt();
const RegisterFormat format = RegisterFormat(idx.data(RegisterFormatRole).toInt());
QAction *act16 = menu.addAction(tr("Hexadecimal"));
act16->setCheckable(true);
act16->setChecked(base == 16);
act16->setChecked(format == HexadecimalFormat);
QAction *act10 = menu.addAction(tr("Decimal"));
act10->setCheckable(true);
act10->setChecked(base == 10);
act10->setChecked(format == DecimalFormat);
QAction *act8 = menu.addAction(tr("Octal"));
act8->setCheckable(true);
act8->setChecked(base == 8);
act8->setChecked(format == OctalFormat);
QAction *act2 = menu.addAction(tr("Binary"));
act2->setCheckable(true);
act2->setChecked(base == 2);
act2->setChecked(format == BinaryFormat);
menu.addSeparator();
menu.addAction(action(SettingsDialog));
......@@ -252,13 +261,13 @@ void RegisterTreeView::contextMenuEvent(QContextMenuEvent *ev)
} else if (act == actShowDisassemblerAt) {
engine->openDisassemblerView(Location(address));
} else if (act == act16)
handler->setNumberBase(registerName, 16);
handler->setNumberFormat(registerName, HexadecimalFormat);
else if (act == act10)
handler->setNumberBase(registerName, 10);
handler->setNumberFormat(registerName, DecimalFormat);
else if (act == act8)
handler->setNumberBase(registerName, 8);
handler->setNumberFormat(registerName, OctalFormat);
else if (act == act2)
handler->setNumberBase(registerName, 2);
handler->setNumberFormat(registerName, BinaryFormat);
}
void RegisterTreeView::reloadRegisters()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment