Refactor various classes for 64-bit support
MODIFY
src/addressdialog.cpp
src/addressdialog.cpp
#include <QPushButton>
#include <QRegExpValidator>
+#include "processorhandler.h"
#include "radix.h"
namespace Ripes {
@@ -12,9 +13,19 @@ AddressDialog::AddressDialog(QWidget* parent) : QDialog(parent), m_ui(new Ui::Ad
m_ui->setupUi(this);
QRegExpValidator* validator = new QRegExpValidator(this);
+ const auto isaBytes = ProcessorHandler::currentISA()->bytes();
+ if (isaBytes == 2) {
+ validator->setRegExp(hexRegex16);
+ } else if (isaBytes == 4) {
validator->setRegExp(hexRegex32);
+ } else if (isaBytes == 8) {
+ validator->setRegExp(hexRegex64);
+ } else {
+ Q_UNREACHABLE();
+ }
+
m_ui->address->setValidator(validator);
- m_ui->address->setText("0x00000000");
+ m_ui->address->setText("0x" + QString("0").repeated(ProcessorHandler::currentISA()->bytes() * 2));
setWindowTitle("Ripes");
connect(m_ui->address, &QLineEdit::textChanged, this, &AddressDialog::validateTargetAddress);
@@ -26,7 +37,19 @@ AddressDialog::~AddressDialog() {
void AddressDialog::validateTargetAddress(const QString& address) {
bool ok;
- uint32_t value = address.toUInt(&ok, 16);
+
+ AInt value;
+ const auto isaBytes = ProcessorHandler::currentISA()->bytes();
+ if (isaBytes == 2) {
+ value = address.toUShort(&ok, 16);
+ } else if (isaBytes == 4) {
+ value = address.toUInt(&ok, 16);
+ } else if (isaBytes == 8) {
+ value = address.toULongLong(&ok, 16);
+ } else {
+ Q_UNREACHABLE();
+ }
+
if (ok) {
m_address = value;
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);

MODIFY
src/addressdialog.h
src/addressdialog.h
#include <QDialog>
+#include "ripes_types.h"
+
namespace Ripes {
namespace Ui {
@@ -16,11 +18,11 @@ public:
explicit AddressDialog(QWidget* parent = nullptr);
~AddressDialog() override;
- uint32_t getAddress() const { return m_address; }
+ AInt getAddress() const { return m_address; }
private:
Ui::AddressDialog* m_ui = nullptr;
- uint32_t m_address = 0;
+ AInt m_address = 0;
void validateTargetAddress(const QString& address);
};
} // namespace Ripes

MODIFY
src/gotocombobox.cpp
src/gotocombobox.cpp
@@ -16,8 +16,9 @@ GoToComboBox::GoToComboBox(QWidget* parent) : QComboBox(parent) {
}
void GoToComboBox::showPopup() {
- if (count())
+ if (count()) {
clear();
+ }
addItem("Select", QVariant::fromValue<GoToUserData>({GoToFunction::Select, 0}));
addTargets();
@@ -57,12 +58,12 @@ void GoToSectionComboBox::addTargets() {
}
}
-uint32_t GoToSectionComboBox::addrForIndex(int i) {
+AInt GoToSectionComboBox::addrForIndex(int i) {
const QString& sectionName = itemText(i);
if (auto prog_spt = ProcessorHandler::getProgram()) {
return prog_spt->getSection(sectionName)->address;
} else {
- return -1;
+ return 0;
}
}
@@ -74,7 +75,7 @@ void GoToRegisterComboBox::addTargets() {
}
}
-uint32_t GoToRegisterComboBox::addrForIndex(int i) {
+AInt GoToRegisterComboBox::addrForIndex(int i) {
const auto& regIdx = qvariant_cast<GoToUserData>(itemData(i));
return ProcessorHandler::getRegisterValue(RegisterFileType::GPR, regIdx.arg);
}

MODIFY
src/gotocombobox.h
src/gotocombobox.h
#include <QComboBox>
#include <QMetaType>
+#include "ripes_types.h"
+
namespace Ripes {
enum class GoToFunction { Select, Address, Custom };
@@ -19,14 +21,14 @@ public:
signals:
void indexChanged();
- void jumpToAddress(uint32_t address);
+ void jumpToAddress(AInt address);
public slots:
private:
void signalFilter(int index);
virtual void addTargets() = 0;
- virtual uint32_t addrForIndex(int i) = 0;
+ virtual AInt addrForIndex(int i) = 0;
};
class GoToSectionComboBox : public GoToComboBox {
@@ -35,7 +37,7 @@ public:
private:
void addTargets();
- uint32_t addrForIndex(int i);
+ AInt addrForIndex(int i);
};
class GoToRegisterComboBox : public GoToComboBox {
@@ -44,7 +46,7 @@ public:
private:
void addTargets();
- uint32_t addrForIndex(int i);
+ AInt addrForIndex(int i);
};
} // namespace Ripes

MODIFY
src/io/memorymapmodel.cpp
src/io/memorymapmodel.cpp
@@ -62,8 +62,11 @@ QVariant MemoryMapModel::data(const QModelIndex& index, int role) const {
case Column::AddressRange: {
switch (role) {
case Qt::DisplayRole:
- return encodeRadixValue(memoryMapEntry->first, Radix::Hex) + " - " +
- encodeRadixValue(memoryMapEntry->first + memoryMapEntry->second.size, Radix::Hex);
+ return encodeRadixValue(memoryMapEntry->first, Radix::Hex,
+ ProcessorHandler::currentISA()->bytes()) +
+ " - " +
+ encodeRadixValue(memoryMapEntry->first + memoryMapEntry->second.size, Radix::Hex,
+ ProcessorHandler::currentISA()->bytes());
case Qt::FontRole:
return QFont(Fonts::monospace, 11);
case Qt::TextAlignmentRole:

MODIFY
src/memorymodel.cpp
src/memorymodel.cpp
@@ -23,20 +23,35 @@ void MemoryModel::processorWasClocked() {
endResetModel();
}
-bool MemoryModel::validAddress(long long address) const {
- return !(address < 0 || (address > (std::pow(2, ProcessorHandler::currentISA()->bits()) - 1)));
+AInt maxAddress() {
+ return vsrtl::generateBitmask(ProcessorHandler::currentISA()->bits());
}
-void MemoryModel::setCentralAddress(uint32_t address) {
+void MemoryModel::setCentralAddress(AInt address) {
address = address - (address % ProcessorHandler::currentISA()->bytes());
m_centralAddress = address;
processorWasClocked();
}
+// Checks whether an overflow or underflow error occurred when calculating the new address, relative to the current
+// address
+bool validAddressChange(AInt currentAddress, AInt newAddress) {
+ bool validAddress = true;
+ const AIntS signed_center = static_cast<AIntS>(currentAddress);
+ const AIntS signed_aligned = static_cast<AIntS>(newAddress);
+
+ // Arithmetic underflow and overflow check (overflow, if ISA bytes == sizeof(AIntS))
+ validAddress &= (signed_center >= 0 && signed_aligned >= 0) || (signed_center < 0 && signed_aligned < 0);
+
+ // Overflow check 2: if ISA bytes < sizeof(AIntS)
+ validAddress &= newAddress < maxAddress();
+ return validAddress;
+}
+
void MemoryModel::offsetCentralAddress(int rowOffset) {
const int byteOffset = rowOffset * ProcessorHandler::currentISA()->bytes();
- const long long newCenterAddress = static_cast<long long>(m_centralAddress) + byteOffset;
- m_centralAddress = !validAddress(newCenterAddress) ? m_centralAddress : newCenterAddress;
+ const AInt newCenterAddress = m_centralAddress + byteOffset;
+ m_centralAddress = validAddressChange(m_centralAddress, newCenterAddress) ? newCenterAddress : m_centralAddress;
processorWasClocked();
}
@@ -54,7 +69,7 @@ QVariant MemoryModel::headerData(int section, Qt::Orientation orientation, int r
return QVariant();
}
-void MemoryModel::setRowsVisible(unsigned rows) {
+void MemoryModel::setRowsVisible(int rows) {
m_rowsVisible = rows;
processorWasClocked();
}
@@ -72,18 +87,38 @@ QVariant MemoryModel::data(const QModelIndex& index, int role) const {
}
const auto bytes = ProcessorHandler::currentISA()->bytes();
- const long long alignedAddress = static_cast<long long>(m_centralAddress) +
- ((((m_rowsVisible * bytes) / 2) / bytes) * bytes) - (index.row() * bytes);
+ // Calculate the word-aligned address corresponding to the row of the current index.
+ // If the central address is at one of its two extrema, based on the address space of the processor, the aligned
+ // address is invalid.
+ /*
+ AInt alignedAddress;
+ bool validAddress = true;
+ if (m_centralAddress == 0x0) {
+ validAddress &= index.row() < m_rowsVisible / 2;
+ }
+ if (m_centralAddress >= maxAddress()) {
+ validAddress &= index.row() > m_rowsVisible / 2;
+ }
+ if (validAddress) {
+ alignedAddress = static_cast<AInt>(m_centralAddress) + ((((m_rowsVisible * bytes) / 2) / bytes) * bytes) -
+ (index.row() * bytes);
+ }
+*/
+
+ const AInt alignedAddress =
+ static_cast<AInt>(m_centralAddress) + ((((m_rowsVisible * bytes) / 2) / bytes) * bytes) - (index.row() * bytes);
+ const bool validAddress = validAddressChange(m_centralAddress, alignedAddress);
+
const unsigned byteOffset = index.column() - FIXED_COLUMNS_CNT;
if (index.column() == Column::Address) {
if (role == Qt::DisplayRole) {
- return addrData(alignedAddress);
+ return addrData(alignedAddress, validAddress);
} else if (role == Qt::ForegroundRole) {
// Assign a brush if one of the byte-indexed address covered by the aligned address has been written to
QVariant unusedAddressBrush;
for (unsigned i = 0; i < ProcessorHandler::currentISA()->bytes(); i++) {
- QVariant addressBrush = fgColorData(alignedAddress, i);
+ QVariant addressBrush = fgColorData(alignedAddress, i, validAddress);
if (addressBrush.isNull()) {
return addressBrush;
} else {
@@ -95,12 +130,12 @@ QVariant MemoryModel::data(const QModelIndex& index, int role) const {
} else {
switch (role) {
case Qt::ForegroundRole:
- return fgColorData(alignedAddress, index.column() == Column::WordValue ? 0 : byteOffset);
+ return fgColorData(alignedAddress, index.column() == Column::WordValue ? 0 : byteOffset, validAddress);
case Qt::DisplayRole:
if (index.column() == Column::WordValue) {
- return wordData(alignedAddress);
+ return wordData(alignedAddress, validAddress);
} else {
- return byteData(alignedAddress, byteOffset);
+ return byteData(alignedAddress, byteOffset, validAddress);
}
default:
break;
@@ -115,46 +150,45 @@ void MemoryModel::setRadix(Radix r) {
processorWasClocked();
}
-QVariant MemoryModel::addrData(long long address) const {
- if (!validAddress(address)) {
+QVariant MemoryModel::addrData(AInt address, bool validAddress) const {
+ if (!validAddress) {
return "-";
}
- return encodeRadixValue(address, Radix::Hex);
+ return encodeRadixValue(address, Radix::Hex, ProcessorHandler::currentISA()->bytes());
}
-QVariant MemoryModel::fgColorData(long long address, unsigned byteOffset) const {
- if (!validAddress(address) ||
- !ProcessorHandler::getMemory().contains(static_cast<unsigned>(address + byteOffset))) {
+QVariant MemoryModel::fgColorData(AInt address, AInt byteOffset, bool validAddress) const {
+ if (!validAddress || !ProcessorHandler::getMemory().contains(address + byteOffset)) {
return QBrush(Qt::lightGray);
} else {
return QVariant(); // default
}
}
-QVariant MemoryModel::byteData(long long address, unsigned byteOffset) const {
- if (!validAddress(address)) {
+QVariant MemoryModel::byteData(AInt address, AInt byteOffset, bool validAddress) const {
+ if (!validAddress) {
return "-";
- } else if (!ProcessorHandler::getMemory().contains(static_cast<unsigned>(address + byteOffset))) {
+ } else if (!ProcessorHandler::getMemory().contains(address + byteOffset)) {
// Dont read the memory (this will create an entry in the memory if done so). Instead, create a "fake" entry in
// the memory model, containing X's.
return "X";
} else {
- uint32_t value = ProcessorHandler::getMemory().readMemConst(static_cast<unsigned>(address));
+ VInt value = ProcessorHandler::getMemory().readMemConst(address);
value = value >> (byteOffset * 8);
- return encodeRadixValue(value & 0xFF, m_radix, 8);
+ return encodeRadixValue(value & 0xFF, m_radix, 1);
}
}
-QVariant MemoryModel::wordData(long long address) const {
- if (!validAddress(address)) {
+QVariant MemoryModel::wordData(AInt address, bool validAddress) const {
+ if (!validAddress) {
return "-";
- } else if (!ProcessorHandler::getMemory().contains(static_cast<unsigned>(address))) {
+ } else if (!ProcessorHandler::getMemory().contains(address)) {
// Dont read the memory (this will create an entry in the memory if done so). Instead, create a "fake" entry in
// the memory model, containing X's.
return "X";
} else {
- uint32_t value = ProcessorHandler::getMemory().readMemConst(static_cast<unsigned>(address));
- return encodeRadixValue(value, m_radix, ProcessorHandler::currentISA()->bits());
+ VInt value = ProcessorHandler::getMemory().readMemConst(address);
+ return encodeRadixValue(value, m_radix, ProcessorHandler::currentISA()->bytes());
}
}

MODIFY
src/memorymodel.h
src/memorymodel.h
@@ -26,20 +26,19 @@ public:
public slots:
void processorWasClocked();
- void setRowsVisible(unsigned rows);
+ void setRowsVisible(int rows);
void offsetCentralAddress(int rowOffset);
- void setCentralAddress(uint32_t address);
+ void setCentralAddress(AInt address);
private:
- bool validAddress(long long address) const;
- QVariant addrData(long long address) const;
- QVariant byteData(long long address, unsigned byteOffset) const;
- QVariant wordData(long long address) const;
- QVariant fgColorData(long long address, unsigned byteOffset) const;
+ QVariant addrData(AInt address, bool validAddress) const;
+ QVariant byteData(AInt address, AInt byteOffset, bool validAddress) const;
+ QVariant wordData(AInt address, bool validAddress) const;
+ QVariant fgColorData(AInt address, AInt byteOffset, bool validAddress) const;
Radix m_radix = Radix::Hex;
- long long m_centralAddress = 4; // Address at the center of the model
- unsigned m_rowsVisible = 0; // Number of rows currently visible in the view associated with the model
+ AInt m_centralAddress = 0; // Memory address at the center of the model
+ int m_rowsVisible = 0; // Number of rows currently visible in the view associated with the model
};
} // namespace Ripes

MODIFY
src/memoryviewerwidget.cpp
src/memoryviewerwidget.cpp
@@ -16,7 +16,7 @@ MemoryViewerWidget::MemoryViewerWidget(QWidget* parent) : QWidget(parent), m_ui(
m_ui->setupUi(this);
setupNavigationWidgets();
-
+ connect(ProcessorHandler::get(), &ProcessorHandler::processorChanged, this, &MemoryViewerWidget::updateModel);
updateModel();
}
@@ -46,7 +46,7 @@ void MemoryViewerWidget::setupNavigationWidgets() {
flowLayout->addItem(layout);
}
-void MemoryViewerWidget::setCentralAddress(uint32_t address) {
+void MemoryViewerWidget::setCentralAddress(AInt address) {
m_memoryModel->setCentralAddress(address);
}
@@ -57,24 +57,28 @@ void MemoryViewerWidget::updateView() {
void MemoryViewerWidget::updateModel() {
auto* oldModel = m_memoryModel;
- m_memoryModel = new MemoryModel(this);
+ auto* newModel = new MemoryModel(this);
+ m_memoryModel = newModel;
m_ui->memoryView->setModel(m_memoryModel);
m_radixSelector->setRadix(m_memoryModel->getRadix());
connect(m_radixSelector, &RadixSelectorWidget::radixChanged, m_memoryModel, &MemoryModel::setRadix);
// Connect scroll events on the view to modify the center address of the model
- connect(m_ui->memoryView, &MemoryView::scrolled, [=](bool dir) {
+ connect(m_ui->memoryView, &MemoryView::scrolled, newModel, [=](bool dir) {
if (dir) {
- m_memoryModel->offsetCentralAddress(1);
+ newModel->offsetCentralAddress(1);
} else {
- m_memoryModel->offsetCentralAddress(-1);
+ newModel->offsetCentralAddress(-1);
}
});
m_memoryModel->setRowsVisible(1);
- connect(m_ui->memoryView, &MemoryView::resized, [=] {
- const auto rows = m_ui->memoryView->height() / m_ui->memoryView->rowHeight(0);
- m_memoryModel->setRowsVisible(rows);
+ connect(m_ui->memoryView, &MemoryView::resized, newModel, [=] {
+ int rowHeight = m_ui->memoryView->rowHeight(0);
+ if (rowHeight != 0) {
+ const auto rows = m_ui->memoryView->height() / rowHeight;
+ newModel->setRowsVisible(rows);
+ }
});
connect(m_goToSection, &GoToComboBox::jumpToAddress, m_memoryModel, &MemoryModel::setCentralAddress);
connect(m_goToRegister, &GoToComboBox::jumpToAddress, m_memoryModel, &MemoryModel::setCentralAddress);

MODIFY
src/memoryviewerwidget.h
src/memoryviewerwidget.h
@@ -26,7 +26,7 @@ public:
public slots:
void updateView();
- void setCentralAddress(uint32_t address);
+ void setCentralAddress(AInt address);
private:
void setupNavigationWidgets();

MODIFY
src/radix.h
src/radix.h
#include <QMetaType>
#include <QRegExp>
#include <QString>
+#include <climits>
#include <map>
#include "ripes_types.h"
@@ -15,20 +16,22 @@ const static std::map<Radix, QString> s_radixName = {{Radix::Hex, "Hex"},
{Radix::ASCII, "ASCII"}, {Radix::Float, "Float"}};
static const auto hexRegex = QRegExp("0[xX][0-9a-fA-F]+");
+static const auto hexRegex16 = QRegExp("0[xX][0-9a-fA-F]{0,4}");
static const auto hexRegex32 = QRegExp("0[xX][0-9a-fA-F]{0,8}");
+static const auto hexRegex64 = QRegExp("0[xX][0-9a-fA-F]{0,16}");
static const auto binRegex = QRegExp("0[bB][0-1]+");
static const auto unsignedRegex = QRegExp("[0-9]+");
static const auto signedRegex = QRegExp("[-]*[0-9]+");
-static inline QString encodeRadixValue(VInt value, const Radix type, unsigned width = 32) {
+static inline QString encodeRadixValue(VInt value, const Radix type, unsigned byteWidth) {
switch (type) {
case Radix::Hex: {
- return "0x" + QString::number(value, 16).rightJustified(width / 4, '0');
+ return "0x" + QString::number(value, 16).rightJustified(byteWidth * 2, '0');
}
case Radix::Float: {
float _fvalue; // Copy raw data instead of reinterpret_cast to avoid type-punned pointer error
double _dvalue;
- if (width <= 32) {
+ if (byteWidth <= 4) {
memcpy(&_fvalue, &value, sizeof(_fvalue));
return QString::number(_fvalue);
} else {
@@ -37,13 +40,13 @@ static inline QString encodeRadixValue(VInt value, const Radix type, unsigned wi
}
}
case Radix::Binary: {
- return "0b" + QString::number(value, 2).rightJustified(width, '0');
+ return "0b" + QString::number(value, 2).rightJustified(byteWidth * CHAR_BIT, '0');
}
case Radix::Unsigned: {
return QString::number(value, 10);
}
case Radix::Signed: {
- if (width == 32) {
+ if (byteWidth == 4) {
return QString::number(static_cast<int32_t>(value), 10);
} else {
return QString::number(static_cast<int64_t>(value), 10);
@@ -51,7 +54,7 @@ static inline QString encodeRadixValue(VInt value, const Radix type, unsigned wi
}
case Radix::ASCII: {
QString str;
- for (unsigned i = 0; i < width / 8; i++) {
+ for (unsigned i = 0; i < byteWidth; i++) {
str.prepend(QChar::fromLatin1(value & 0xFF));
value >>= 8;
}

MODIFY
src/registermodel.cpp
src/registermodel.cpp
@@ -10,7 +10,7 @@ namespace Ripes {
using namespace vsrtl;
RegisterModel::RegisterModel(RegisterFileType rft, QObject* parent) : QAbstractTableModel(parent), m_rft(rft) {
- m_regWidth = ProcessorHandler::getProcessor()->implementsISA()->bits();
+ m_regBytes = ProcessorHandler::getProcessor()->implementsISA()->bytes();
}
std::vector<VInt> RegisterModel::gatherRegisterValues() {
@@ -137,7 +137,7 @@ QVariant RegisterModel::tooltipData(unsigned idx) const {
}
QVariant RegisterModel::valueData(unsigned idx) const {
- return encodeRadixValue(ProcessorHandler::getRegisterValue(m_rft, idx), m_radix, m_regWidth);
+ return encodeRadixValue(ProcessorHandler::getRegisterValue(m_rft, idx), m_radix, m_regBytes);
}
Qt::ItemFlags RegisterModel::flags(const QModelIndex& index) const {

MODIFY
src/registermodel.h
src/registermodel.h
@@ -47,7 +47,7 @@ private:
QVariant tooltipData(unsigned idx) const;
Radix m_radix = Radix::Hex;
- unsigned m_regWidth;
+ unsigned m_regBytes;
RegisterFileType m_rft;
int m_mostRecentlyModifiedReg = -1;

MODIFY
src/ripes_types.h
src/ripes_types.h
@@ -9,6 +9,7 @@ namespace Ripes {
// all ISAs supported by Ripes.
using AInt = uint64_t;
using VInt = uint64_t;
+using AIntS = typename std::make_signed<AInt>::type;
using VIntS = typename std::make_signed<VInt>::type;
} // namespace Ripes

MODIFY
src/symbolnavigator.cpp
src/symbolnavigator.cpp
@@ -40,12 +40,12 @@ long SymbolNavigator::getSelectedSymbolAddress() const {
return 0;
}
-void SymbolNavigator::addSymbol(const long address, const QString& label) {
+void SymbolNavigator::addSymbol(const AInt address, const QString& label) {
m_ui->symbolTable->setRowCount(m_ui->symbolTable->rowCount() + 1);
QTableWidgetItem* addrItem = new QTableWidgetItem();
QTableWidgetItem* labelItem = new QTableWidgetItem();
- addrItem->setData(Qt::DisplayRole, encodeRadixValue(address, Radix::Hex));
+ addrItem->setData(Qt::DisplayRole, encodeRadixValue(address, Radix::Hex, ProcessorHandler::currentISA()->bytes()));
labelItem->setData(Qt::DisplayRole, label);
addrItem->setFlags(addrItem->flags() ^ Qt::ItemIsEditable);

MODIFY
src/symbolnavigator.h
src/symbolnavigator.h
@@ -20,7 +20,7 @@ public:
long getSelectedSymbolAddress() const;
private:
- void addSymbol(const long address, const QString& label);
+ void addSymbol(const AInt address, const QString& label);
Ui::SymbolNavigator* m_ui;
};

Refactor various classes for 64-bit support