2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2010-12-17 16:01:08 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 15:08:31 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "registerhandler.h"
|
2015-08-25 13:48:55 +02:00
|
|
|
|
|
|
|
|
#include "debuggerengine.h"
|
2010-09-22 17:30:22 +02:00
|
|
|
#include "watchdelegatewidgets.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-08-31 16:45:44 +02:00
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
|
|
|
|
|
namespace Debugger {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
2011-08-31 16:45:44 +02:00
|
|
|
// Register
|
2008-12-02 12:01:29 +01:00
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
void Register::guessMissingData()
|
2011-08-31 16:45:44 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
if (reportedType == "int")
|
2015-07-21 12:52:18 +02:00
|
|
|
kind = IntegerRegister;
|
2014-12-17 13:14:29 +01:00
|
|
|
else if (reportedType == "float")
|
2015-07-21 12:52:18 +02:00
|
|
|
kind = FloatRegister;
|
2014-12-17 13:14:29 +01:00
|
|
|
else if (reportedType == "_i387_ext")
|
2015-07-21 12:52:18 +02:00
|
|
|
kind = FloatRegister;
|
2014-12-17 13:14:29 +01:00
|
|
|
else if (reportedType == "*1" || reportedType == "long")
|
2015-07-21 12:52:18 +02:00
|
|
|
kind = IntegerRegister;
|
2014-12-17 13:14:29 +01:00
|
|
|
else if (reportedType.contains("vec"))
|
2015-07-21 12:52:18 +02:00
|
|
|
kind = VectorRegister;
|
2014-12-17 13:14:29 +01:00
|
|
|
else if (reportedType.startsWith("int"))
|
2015-07-21 12:52:18 +02:00
|
|
|
kind = IntegerRegister;
|
|
|
|
|
else if (name.startsWith("xmm") || name.startsWith("ymm"))
|
|
|
|
|
kind = VectorRegister;
|
2014-12-17 13:14:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-31 14:20:43 +02:00
|
|
|
static QString subTypeName(RegisterKind kind, int size, RegisterFormat format)
|
2014-12-17 13:14:29 +01:00
|
|
|
{
|
2015-03-31 14:20:43 +02:00
|
|
|
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;
|
2015-07-21 10:26:39 +02:00
|
|
|
case DecimalFormat: name += QLatin1Char('u'); break;
|
|
|
|
|
case SignedDecimalFormat: name += QLatin1Char('s'); break;
|
2015-03-31 14:20:43 +02:00
|
|
|
case HexadecimalFormat: name += QLatin1Char('x'); break;
|
|
|
|
|
case CharacterFormat: name += QLatin1Char('c'); break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name += QLatin1Char(']');
|
|
|
|
|
|
|
|
|
|
return name;
|
2011-08-31 16:45:44 +02:00
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
static uint decodeHexChar(unsigned char c)
|
2011-08-31 16:45:44 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
c -= '0';
|
|
|
|
|
if (c < 10)
|
|
|
|
|
return c;
|
|
|
|
|
c -= 'A' - '0';
|
|
|
|
|
if (c < 6)
|
|
|
|
|
return 10 + c;
|
|
|
|
|
c -= 'a' - 'A';
|
|
|
|
|
if (c < 6)
|
|
|
|
|
return 10 + c;
|
|
|
|
|
return uint(-1);
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-07 17:04:53 +02:00
|
|
|
void RegisterValue::fromString(const QString &str, RegisterFormat format)
|
2014-12-17 13:14:29 +01:00
|
|
|
{
|
2016-06-07 17:04:53 +02:00
|
|
|
known = !str.isEmpty();
|
2014-12-17 13:14:29 +01:00
|
|
|
v.u64[1] = v.u64[0] = 0;
|
2015-08-25 13:48:55 +02:00
|
|
|
|
2016-06-07 17:04:53 +02:00
|
|
|
const int n = str.size();
|
2015-08-25 13:48:55 +02:00
|
|
|
int pos = 0;
|
2016-06-07 17:04:53 +02:00
|
|
|
if (str.startsWith("0x"))
|
2015-08-25 13:48:55 +02:00
|
|
|
pos += 2;
|
|
|
|
|
|
2016-06-07 17:04:53 +02:00
|
|
|
bool negative = pos < n && str.at(pos) == '-';
|
2015-08-25 13:48:55 +02:00
|
|
|
if (negative)
|
|
|
|
|
++pos;
|
|
|
|
|
|
|
|
|
|
while (pos < n) {
|
2016-06-07 17:04:53 +02:00
|
|
|
uint c = str.at(pos).unicode();
|
2015-08-25 13:48:55 +02:00
|
|
|
if (format != CharacterFormat) {
|
|
|
|
|
c = decodeHexChar(c);
|
|
|
|
|
if (c == uint(-1))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
shiftOneDigit(c, format);
|
|
|
|
|
++pos;
|
2014-12-17 13:14:29 +01:00
|
|
|
}
|
2015-08-25 13:48:55 +02:00
|
|
|
|
|
|
|
|
if (negative) {
|
|
|
|
|
v.u64[1] = ~v.u64[1];
|
|
|
|
|
v.u64[0] = ~v.u64[0];
|
|
|
|
|
++v.u64[0];
|
|
|
|
|
if (v.u64[0] == 0)
|
|
|
|
|
++v.u64[1];
|
2011-08-31 16:45:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
bool RegisterValue::operator==(const RegisterValue &other)
|
2012-09-24 15:48:17 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
return v.u64[0] == other.v.u64[0] && v.u64[1] == other.v.u64[1];
|
2012-09-24 15:48:17 +02:00
|
|
|
}
|
|
|
|
|
|
2016-06-07 17:04:53 +02:00
|
|
|
static QString formatRegister(quint64 v, int size, RegisterFormat format, bool forEdit)
|
2011-08-31 16:45:44 +02:00
|
|
|
{
|
2016-06-07 17:04:53 +02:00
|
|
|
QString result;
|
2015-03-31 14:20:43 +02:00
|
|
|
if (format == HexadecimalFormat) {
|
2016-06-07 17:04:53 +02:00
|
|
|
result = QString::number(v, 16);
|
|
|
|
|
result.prepend(QString(2*size - result.size(), '0'));
|
2015-03-31 14:20:43 +02:00
|
|
|
} else if (format == DecimalFormat) {
|
2016-06-07 17:04:53 +02:00
|
|
|
result = QString::number(v, 10);
|
|
|
|
|
result.prepend(QString(2*size - result.size(), ' '));
|
2015-07-21 10:26:39 +02:00
|
|
|
} else if (format == SignedDecimalFormat) {
|
|
|
|
|
qint64 sv;
|
|
|
|
|
if (size >= 8)
|
|
|
|
|
sv = qint64(v);
|
|
|
|
|
else if (size >= 4)
|
|
|
|
|
sv = qint32(v);
|
|
|
|
|
else if (size >= 2)
|
|
|
|
|
sv = qint16(v);
|
|
|
|
|
else
|
|
|
|
|
sv = qint8(v);
|
2016-06-07 17:04:53 +02:00
|
|
|
result = QString::number(sv, 10);
|
|
|
|
|
result.prepend(QString(2*size - result.size(), ' '));
|
2015-03-31 14:20:43 +02:00
|
|
|
} else if (format == CharacterFormat) {
|
2015-08-28 13:35:50 +02:00
|
|
|
bool spacesOnly = true;
|
2015-03-31 14:20:43 +02:00
|
|
|
if (v >= 32 && v < 127) {
|
2015-08-28 13:35:50 +02:00
|
|
|
spacesOnly = false;
|
|
|
|
|
if (!forEdit)
|
|
|
|
|
result += '\'';
|
2015-03-31 14:20:43 +02:00
|
|
|
result += char(v);
|
2015-08-28 13:35:50 +02:00
|
|
|
if (!forEdit)
|
|
|
|
|
result += '\'';
|
2015-03-31 14:20:43 +02:00
|
|
|
} else {
|
|
|
|
|
result += " ";
|
|
|
|
|
}
|
2015-08-28 13:35:50 +02:00
|
|
|
if (spacesOnly && forEdit)
|
|
|
|
|
result.clear();
|
|
|
|
|
else
|
2016-06-07 17:04:53 +02:00
|
|
|
result.prepend(QString(2*size - result.size(), ' '));
|
2015-03-31 14:20:43 +02:00
|
|
|
}
|
2014-12-17 13:14:29 +01:00
|
|
|
return result;
|
2011-08-31 16:45:44 +02:00
|
|
|
}
|
|
|
|
|
|
2016-06-07 17:04:53 +02:00
|
|
|
QString RegisterValue::toString(RegisterKind kind, int size, RegisterFormat format, bool forEdit) const
|
2014-12-17 13:14:29 +01:00
|
|
|
{
|
2015-02-26 11:10:25 +01:00
|
|
|
if (!known)
|
2016-06-07 17:04:53 +02:00
|
|
|
return QLatin1String("[inaccessible]");
|
2014-12-17 13:14:29 +01:00
|
|
|
if (kind == FloatRegister) {
|
|
|
|
|
if (size == 4)
|
2016-06-07 17:04:53 +02:00
|
|
|
return QString::number(v.f[0]);
|
2014-12-17 13:14:29 +01:00
|
|
|
if (size == 8)
|
2016-06-07 17:04:53 +02:00
|
|
|
return QString::number(v.d[0]);
|
2014-12-17 13:14:29 +01:00
|
|
|
}
|
|
|
|
|
|
2016-06-07 17:04:53 +02:00
|
|
|
QString result;
|
2014-12-17 13:14:29 +01:00
|
|
|
if (size > 8) {
|
2015-08-28 13:35:50 +02:00
|
|
|
result += formatRegister(v.u64[1], size - 8, format, forEdit);
|
2014-12-17 13:14:29 +01:00
|
|
|
size = 8;
|
2015-03-31 14:20:43 +02:00
|
|
|
if (format != HexadecimalFormat)
|
2014-12-17 13:14:29 +01:00
|
|
|
result += ',';
|
|
|
|
|
}
|
2015-08-28 13:35:50 +02:00
|
|
|
return result + formatRegister(v.u64[0], size, format, forEdit);
|
2014-12-17 13:14:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RegisterValue RegisterValue::subValue(int size, int index) const
|
|
|
|
|
{
|
|
|
|
|
RegisterValue value;
|
2015-03-25 12:54:00 +01:00
|
|
|
value.known = known;
|
2014-12-17 13:14:29 +01:00
|
|
|
switch (size) {
|
|
|
|
|
case 1:
|
|
|
|
|
value.v.u8[0] = v.u8[index];
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
value.v.u16[0] = v.u16[index];
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
value.v.u32[0] = v.u32[index];
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
value.v.u64[0] = v.u64[index];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
}
|
2011-08-31 16:45:44 +02:00
|
|
|
|
2015-08-25 13:48:55 +02:00
|
|
|
void RegisterValue::setSubValue(int size, int index, RegisterValue subValue)
|
|
|
|
|
{
|
|
|
|
|
switch (size) {
|
|
|
|
|
case 1:
|
|
|
|
|
v.u8[index] = subValue.v.u8[0];
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
v.u16[index] = subValue.v.u16[0];
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
v.u32[index] = subValue.v.u32[0];
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
v.u64[index] = subValue.v.u64[0];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline void shiftBitsLeft(RegisterValue *val, int amount)
|
|
|
|
|
{
|
|
|
|
|
val->v.u64[1] <<= amount;
|
|
|
|
|
val->v.u64[1] |= val->v.u64[0] >> (64 - amount);
|
|
|
|
|
val->v.u64[0] <<= amount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RegisterValue::shiftOneDigit(uint digit, RegisterFormat format)
|
|
|
|
|
{
|
|
|
|
|
switch (format) {
|
|
|
|
|
case HexadecimalFormat:
|
|
|
|
|
shiftBitsLeft(this, 4);
|
|
|
|
|
v.u64[0] |= digit;
|
|
|
|
|
break;
|
|
|
|
|
case OctalFormat:
|
|
|
|
|
shiftBitsLeft(this, 3);
|
|
|
|
|
v.u64[0] |= digit;
|
|
|
|
|
break;
|
|
|
|
|
case BinaryFormat:
|
|
|
|
|
shiftBitsLeft(this, 1);
|
|
|
|
|
v.u64[0] |= digit;
|
|
|
|
|
break;
|
|
|
|
|
case DecimalFormat:
|
|
|
|
|
case SignedDecimalFormat: {
|
|
|
|
|
shiftBitsLeft(this, 1);
|
|
|
|
|
quint64 tmp0 = v.u64[0];
|
|
|
|
|
quint64 tmp1 = v.u64[1];
|
|
|
|
|
shiftBitsLeft(this, 2);
|
|
|
|
|
v.u64[1] += tmp1;
|
|
|
|
|
v.u64[0] += tmp0;
|
|
|
|
|
if (v.u64[0] < tmp0)
|
|
|
|
|
++v.u64[1];
|
|
|
|
|
v.u64[0] += digit;
|
|
|
|
|
if (v.u64[0] < digit)
|
|
|
|
|
++v.u64[1];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CharacterFormat:
|
|
|
|
|
shiftBitsLeft(this, 8);
|
|
|
|
|
v.u64[0] |= digit;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-31 16:45:44 +02:00
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
2014-12-17 13:14:29 +01:00
|
|
|
// RegisterSubItem and RegisterItem
|
2011-08-31 16:45:44 +02:00
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
2010-11-05 13:35:31 +01:00
|
|
|
|
2015-08-25 13:48:55 +02:00
|
|
|
class RegisterSubItem;
|
|
|
|
|
|
|
|
|
|
class RegisterEditItem : public Utils::TreeItem
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
RegisterEditItem(int pos, RegisterKind subKind, int subSize, RegisterFormat format)
|
|
|
|
|
: m_index(pos), m_subKind(subKind), m_subSize(subSize), m_subFormat(format)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
QVariant data(int column, int role) const override;
|
|
|
|
|
bool setData(int column, const QVariant &value, int role) override;
|
|
|
|
|
Qt::ItemFlags flags(int column) const override;
|
|
|
|
|
|
|
|
|
|
int m_index;
|
|
|
|
|
RegisterKind m_subKind;
|
|
|
|
|
int m_subSize;
|
|
|
|
|
RegisterFormat m_subFormat;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
class RegisterSubItem : public Utils::TreeItem
|
2009-08-13 16:16:19 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
public:
|
2015-03-31 14:20:43 +02:00
|
|
|
RegisterSubItem(RegisterKind subKind, int subSize, int count, RegisterFormat format)
|
|
|
|
|
: m_subKind(subKind), m_subFormat(format), m_subSize(subSize), m_count(count), m_changed(false)
|
2015-08-25 13:48:55 +02:00
|
|
|
{
|
|
|
|
|
for (int i = 0; i != count; ++i)
|
|
|
|
|
appendChild(new RegisterEditItem(i, subKind, subSize, format));
|
|
|
|
|
}
|
2014-12-17 13:14:29 +01:00
|
|
|
|
|
|
|
|
QVariant data(int column, int role) const;
|
|
|
|
|
|
|
|
|
|
Qt::ItemFlags flags(int column) const
|
|
|
|
|
{
|
|
|
|
|
//return column == 1 ? Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable
|
|
|
|
|
// : Qt::ItemIsSelectable|Qt::ItemIsEnabled;
|
|
|
|
|
Q_UNUSED(column);
|
|
|
|
|
return Qt::ItemIsSelectable|Qt::ItemIsEnabled;
|
|
|
|
|
}
|
2011-08-31 16:45:44 +02:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
RegisterKind m_subKind;
|
2015-03-31 14:20:43 +02:00
|
|
|
RegisterFormat m_subFormat;
|
2014-12-17 13:14:29 +01:00
|
|
|
int m_subSize;
|
|
|
|
|
int m_count;
|
|
|
|
|
bool m_changed;
|
|
|
|
|
};
|
2011-08-31 16:45:44 +02:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
class RegisterItem : public Utils::TreeItem
|
2011-08-31 16:45:44 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
public:
|
|
|
|
|
explicit RegisterItem(const Register ®);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-08-25 13:48:55 +02:00
|
|
|
QVariant data(int column, int role) const override;
|
|
|
|
|
bool setData(int column, const QVariant &value, int role) override;
|
|
|
|
|
Qt::ItemFlags flags(int column) const override;
|
2014-12-17 13:14:29 +01:00
|
|
|
|
|
|
|
|
quint64 addressValue() const;
|
2015-08-25 13:48:55 +02:00
|
|
|
void triggerChange();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
Register m_reg;
|
2015-03-31 14:20:43 +02:00
|
|
|
RegisterFormat m_format;
|
2014-12-17 13:14:29 +01:00
|
|
|
bool m_changed;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
RegisterItem::RegisterItem(const Register ®) :
|
2015-03-31 14:20:43 +02:00
|
|
|
m_reg(reg), m_format(HexadecimalFormat), m_changed(true)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
if (m_reg.kind == UnknownRegister)
|
|
|
|
|
m_reg.guessMissingData();
|
|
|
|
|
|
|
|
|
|
if (m_reg.kind == IntegerRegister || m_reg.kind == VectorRegister) {
|
2015-07-21 10:26:39 +02:00
|
|
|
if (m_reg.size <= 8) {
|
|
|
|
|
appendChild(new RegisterSubItem(IntegerRegister, m_reg.size, 1, SignedDecimalFormat));
|
|
|
|
|
appendChild(new RegisterSubItem(IntegerRegister, m_reg.size, 1, DecimalFormat));
|
|
|
|
|
}
|
2015-03-31 14:20:43 +02:00
|
|
|
for (int s = m_reg.size / 2; s; s = s / 2) {
|
|
|
|
|
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, HexadecimalFormat));
|
2015-07-21 10:26:39 +02:00
|
|
|
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, SignedDecimalFormat));
|
2015-03-31 14:20:43 +02:00
|
|
|
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, DecimalFormat));
|
|
|
|
|
if (s == 1)
|
|
|
|
|
appendChild(new RegisterSubItem(IntegerRegister, s, m_reg.size / s, CharacterFormat));
|
|
|
|
|
}
|
2014-12-17 13:14:29 +01:00
|
|
|
}
|
|
|
|
|
if (m_reg.kind == IntegerRegister || m_reg.kind == VectorRegister) {
|
|
|
|
|
for (int s = m_reg.size; s >= 4; s = s / 2)
|
2015-03-31 14:20:43 +02:00
|
|
|
appendChild(new RegisterSubItem(FloatRegister, s, m_reg.size / s, DecimalFormat));
|
2014-12-17 13:14:29 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
Qt::ItemFlags RegisterItem::flags(int column) const
|
2010-09-22 09:41:15 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
const Qt::ItemFlags notEditable = Qt::ItemIsSelectable|Qt::ItemIsEnabled;
|
|
|
|
|
// Can edit registers if they are hex numbers and not arrays.
|
|
|
|
|
if (column == 1) // && IntegerWatchLineEdit::isUnsignedHexNumber(QLatin1String(m_reg.display)))
|
|
|
|
|
return notEditable | Qt::ItemIsEditable;
|
|
|
|
|
return notEditable;
|
2010-09-22 17:30:22 +02:00
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
quint64 RegisterItem::addressValue() const
|
2010-09-22 17:30:22 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
return m_reg.value.v.u64[0];
|
2010-09-22 09:41:15 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-25 13:48:55 +02:00
|
|
|
void RegisterItem::triggerChange()
|
|
|
|
|
{
|
2016-06-07 17:04:53 +02:00
|
|
|
QString value = "0x" + m_reg.value.toString(m_reg.kind, m_reg.size, HexadecimalFormat);
|
2015-08-25 13:48:55 +02:00
|
|
|
DebuggerEngine *engine = static_cast<RegisterHandler *>(model())->engine();
|
2016-06-07 17:04:53 +02:00
|
|
|
engine->setRegisterValue(m_reg.name, value);
|
2015-08-25 13:48:55 +02:00
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
QVariant RegisterItem::data(int column, int role) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
switch (role) {
|
|
|
|
|
case RegisterNameRole:
|
|
|
|
|
return m_reg.name;
|
2011-08-31 16:45:44 +02:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
case RegisterIsBigRole:
|
|
|
|
|
return m_reg.value.v.u64[1] > 0;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
case RegisterChangedRole:
|
|
|
|
|
return m_changed;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
case RegisterAsAddressRole:
|
|
|
|
|
return addressValue();
|
2011-08-31 16:45:44 +02:00
|
|
|
|
2015-03-31 14:20:43 +02:00
|
|
|
case RegisterFormatRole:
|
|
|
|
|
return m_format;
|
|
|
|
|
|
2011-08-31 16:45:44 +02:00
|
|
|
case Qt::DisplayRole:
|
2014-12-17 13:14:29 +01:00
|
|
|
switch (column) {
|
2015-02-26 11:10:25 +01:00
|
|
|
case RegisterNameColumn: {
|
2016-06-07 17:04:53 +02:00
|
|
|
QString res = m_reg.name;
|
2014-12-17 13:14:29 +01:00
|
|
|
if (!m_reg.description.isEmpty())
|
|
|
|
|
res += " (" + m_reg.description + ')';
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2015-02-26 11:10:25 +01:00
|
|
|
case RegisterValueColumn: {
|
2016-06-07 17:04:53 +02:00
|
|
|
return m_reg.value.toString(m_reg.kind, m_reg.size, m_format);
|
2011-08-31 16:45:44 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
case Qt::ToolTipRole:
|
2016-06-07 17:04:53 +02:00
|
|
|
return QString("Current Value: %1\nPreviousValue: %2")
|
|
|
|
|
.arg(m_reg.value.toString(m_reg.kind, m_reg.size, m_format))
|
|
|
|
|
.arg(m_reg.previousValue.toString(m_reg.kind, m_reg.size, m_format));
|
2011-08-31 16:45:44 +02:00
|
|
|
|
|
|
|
|
case Qt::EditRole: // Edit: Unpadded for editing
|
2016-06-07 17:04:53 +02:00
|
|
|
return m_reg.value.toString(m_reg.kind, m_reg.size, m_format);
|
2014-12-17 13:14:29 +01:00
|
|
|
|
2011-08-31 16:45:44 +02:00
|
|
|
case Qt::TextAlignmentRole:
|
2015-02-26 11:10:25 +01:00
|
|
|
return column == RegisterValueColumn ? QVariant(Qt::AlignRight) : QVariant();
|
2014-12-17 13:14:29 +01:00
|
|
|
|
2011-08-31 16:45:44 +02:00
|
|
|
default:
|
|
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-25 13:48:55 +02:00
|
|
|
bool RegisterItem::setData(int column, const QVariant &value, int role)
|
|
|
|
|
{
|
|
|
|
|
if (column == RegisterValueColumn && role == Qt::EditRole) {
|
2016-06-07 17:04:53 +02:00
|
|
|
m_reg.value.fromString(value.toString(), m_format);
|
2015-08-25 13:48:55 +02:00
|
|
|
triggerChange();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
QVariant RegisterSubItem::data(int column, int role) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
switch (role) {
|
|
|
|
|
case RegisterChangedRole:
|
|
|
|
|
return m_changed;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-03-31 14:20:43 +02:00
|
|
|
case RegisterFormatRole: {
|
|
|
|
|
RegisterItem *registerItem = static_cast<RegisterItem *>(parent());
|
|
|
|
|
return int(registerItem->m_format);
|
|
|
|
|
}
|
2009-08-18 08:34:48 +02:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
case RegisterAsAddressRole:
|
|
|
|
|
return 0;
|
2009-08-18 08:34:48 +02:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
case Qt::DisplayRole:
|
|
|
|
|
switch (column) {
|
2015-02-26 11:10:25 +01:00
|
|
|
case RegisterNameColumn:
|
2015-03-31 14:20:43 +02:00
|
|
|
return subTypeName(m_subKind, m_subSize, m_subFormat);
|
2015-02-26 11:10:25 +01:00
|
|
|
case RegisterValueColumn: {
|
2014-12-17 13:14:29 +01:00
|
|
|
QTC_ASSERT(parent(), return QVariant());
|
|
|
|
|
RegisterItem *registerItem = static_cast<RegisterItem *>(parent());
|
|
|
|
|
RegisterValue value = registerItem->m_reg.value;
|
2016-06-07 17:04:53 +02:00
|
|
|
QString ba;
|
2014-12-17 13:14:29 +01:00
|
|
|
for (int i = 0; i != m_count; ++i) {
|
|
|
|
|
int tab = 5 * (i + 1) * m_subSize;
|
2016-06-07 17:04:53 +02:00
|
|
|
QString b = value.subValue(m_subSize, i).toString(m_subKind, m_subSize, m_subFormat);
|
|
|
|
|
ba += QString(tab - ba.size() - b.size(), ' ');
|
2015-03-31 14:20:43 +02:00
|
|
|
ba += b;
|
2014-12-17 13:14:29 +01:00
|
|
|
}
|
|
|
|
|
return ba;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-03-31 14:20:43 +02:00
|
|
|
|
|
|
|
|
case Qt::ToolTipRole:
|
|
|
|
|
if (m_subKind == IntegerRegister) {
|
|
|
|
|
if (m_subFormat == CharacterFormat)
|
|
|
|
|
return RegisterHandler::tr("Content as ASCII Characters");
|
2015-07-21 10:26:39 +02:00
|
|
|
if (m_subFormat == SignedDecimalFormat)
|
|
|
|
|
return RegisterHandler::tr("Content as %1-bit Signed Decimal Values").arg(8 * m_subSize);
|
|
|
|
|
if (m_subFormat == DecimalFormat)
|
|
|
|
|
return RegisterHandler::tr("Content as %1-bit Unsigned Decimal Values").arg(8 * m_subSize);
|
|
|
|
|
if (m_subFormat == HexadecimalFormat)
|
|
|
|
|
return RegisterHandler::tr("Content as %1-bit Hexadecimal Values").arg(8 * m_subSize);
|
|
|
|
|
if (m_subFormat == OctalFormat)
|
|
|
|
|
return RegisterHandler::tr("Content as %1-bit Octal Values").arg(8 * m_subSize);
|
|
|
|
|
if (m_subFormat == BinaryFormat)
|
|
|
|
|
return RegisterHandler::tr("Content as %1-bit Binary Values").arg(8 * m_subSize);
|
2015-03-31 14:20:43 +02:00
|
|
|
}
|
|
|
|
|
if (m_subKind == FloatRegister)
|
2016-01-20 15:50:07 +01:00
|
|
|
return RegisterHandler::tr("Content as %1-bit Floating Point Values").arg(8 * m_subSize);
|
2015-03-31 14:20:43 +02:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
return QVariant();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// RegisterHandler
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2015-08-25 13:48:55 +02:00
|
|
|
RegisterHandler::RegisterHandler(DebuggerEngine *engine)
|
|
|
|
|
: m_engine(engine)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
setObjectName(QLatin1String("RegisterModel"));
|
2015-08-25 13:48:55 +02:00
|
|
|
setHeader({tr("Name"), tr("Value")});
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
void RegisterHandler::updateRegister(const Register &r)
|
2010-09-01 13:56:51 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
RegisterItem *reg = m_registerByName.value(r.name, 0);
|
|
|
|
|
if (!reg) {
|
|
|
|
|
reg = new RegisterItem(r);
|
|
|
|
|
m_registerByName[r.name] = reg;
|
|
|
|
|
rootItem()->appendChild(reg);
|
2011-04-06 14:07:09 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2010-09-01 13:56:51 +02:00
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
if (r.size > 0)
|
|
|
|
|
reg->m_reg.size = r.size;
|
|
|
|
|
if (!r.description.isEmpty())
|
|
|
|
|
reg->m_reg.description = r.description;
|
|
|
|
|
if (reg->m_reg.value != r.value) {
|
|
|
|
|
// Indicate red if values change, keep changed.
|
|
|
|
|
reg->m_changed = true;
|
|
|
|
|
reg->m_reg.previousValue = reg->m_reg.value;
|
|
|
|
|
reg->m_reg.value = r.value;
|
|
|
|
|
emit registerChanged(reg->m_reg.name, reg->addressValue()); // Notify attached memory views.
|
|
|
|
|
} else {
|
|
|
|
|
reg->m_changed = false;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2009-08-13 16:16:19 +02:00
|
|
|
|
2016-06-07 17:04:53 +02:00
|
|
|
void RegisterHandler::setNumberFormat(const QString &name, RegisterFormat format)
|
2010-09-22 09:41:15 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
RegisterItem *reg = m_registerByName.value(name, 0);
|
|
|
|
|
QTC_ASSERT(reg, return);
|
2015-03-31 14:20:43 +02:00
|
|
|
reg->m_format = format;
|
2015-04-22 12:37:39 +02:00
|
|
|
QModelIndex index = indexForItem(reg);
|
2014-12-17 13:14:29 +01:00
|
|
|
emit dataChanged(index, index);
|
2010-09-22 09:41:15 +02:00
|
|
|
}
|
|
|
|
|
|
2014-12-17 13:14:29 +01:00
|
|
|
RegisterMap RegisterHandler::registerMap() const
|
2009-08-13 16:16:19 +02:00
|
|
|
{
|
2014-12-17 13:14:29 +01:00
|
|
|
RegisterMap result;
|
|
|
|
|
Utils::TreeItem *root = rootItem();
|
|
|
|
|
for (int i = 0, n = root->rowCount(); i != n; ++i) {
|
|
|
|
|
RegisterItem *reg = static_cast<RegisterItem *>(root->child(i));
|
|
|
|
|
quint64 value = reg->addressValue();
|
|
|
|
|
if (value)
|
|
|
|
|
result.insert(value, reg->m_reg.name);
|
2010-09-22 09:41:15 +02:00
|
|
|
}
|
2014-12-17 13:14:29 +01:00
|
|
|
return result;
|
2009-08-13 16:16:19 +02:00
|
|
|
}
|
2010-11-05 13:35:31 +01:00
|
|
|
|
2015-08-25 13:48:55 +02:00
|
|
|
QVariant RegisterEditItem::data(int column, int role) const
|
|
|
|
|
{
|
|
|
|
|
switch (role) {
|
|
|
|
|
case Qt::DisplayRole:
|
|
|
|
|
case Qt::EditRole:
|
|
|
|
|
switch (column) {
|
|
|
|
|
case RegisterNameColumn: {
|
2016-06-07 17:04:53 +02:00
|
|
|
return QString("[%1]").arg(m_index);
|
2015-08-25 13:48:55 +02:00
|
|
|
}
|
|
|
|
|
case RegisterValueColumn: {
|
|
|
|
|
RegisterItem *registerItem = static_cast<RegisterItem *>(parent()->parent());
|
|
|
|
|
RegisterValue value = registerItem->m_reg.value;
|
2015-08-28 13:35:50 +02:00
|
|
|
return value.subValue(m_subSize, m_index)
|
2016-06-07 17:04:53 +02:00
|
|
|
.toString(m_subKind, m_subSize, m_subFormat, role == Qt::EditRole);
|
2015-08-25 13:48:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
case Qt::ToolTipRole: {
|
|
|
|
|
RegisterItem *registerItem = static_cast<RegisterItem *>(parent()->parent());
|
|
|
|
|
return RegisterHandler::tr("Edit bits %1...%2 of register %3")
|
2016-06-07 17:04:53 +02:00
|
|
|
.arg(m_index * 8).arg(m_index * 8 + 7).arg(registerItem->m_reg.name);
|
2015-08-25 13:48:55 +02:00
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool RegisterEditItem::setData(int column, const QVariant &value, int role)
|
|
|
|
|
{
|
|
|
|
|
if (column == RegisterValueColumn && role == Qt::EditRole) {
|
|
|
|
|
QTC_ASSERT(parent(), return false);
|
|
|
|
|
QTC_ASSERT(parent()->parent(), return false);
|
|
|
|
|
RegisterItem *registerItem = static_cast<RegisterItem *>(parent()->parent());
|
|
|
|
|
Register ® = registerItem->m_reg;
|
|
|
|
|
RegisterValue vv;
|
2016-06-07 17:04:53 +02:00
|
|
|
vv.fromString(value.toString(), m_subFormat);
|
2015-08-25 13:48:55 +02:00
|
|
|
reg.value.setSubValue(m_subSize, m_index, vv);
|
|
|
|
|
registerItem->triggerChange();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Qt::ItemFlags RegisterEditItem::flags(int column) const
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(parent(), return Qt::ItemFlags());
|
|
|
|
|
RegisterSubItem *registerSubItem = static_cast<RegisterSubItem *>(parent());
|
|
|
|
|
Qt::ItemFlags f = registerSubItem->flags(column);
|
|
|
|
|
if (column == RegisterValueColumn)
|
|
|
|
|
f |= Qt::ItemIsEditable;
|
|
|
|
|
return f;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-05 13:35:31 +01:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Debugger
|