Make assembler segment base pointers adjustable through settings
MODIFY
src/CMakeLists.txt
src/CMakeLists.txt
@@ -10,7 +10,8 @@ file(GLOB LIB_SOURCES
syscall/*.cpp
version/version.cpp
assembler/*.cpp
- io/*.cpp)
+ io/*.cpp
+ utilities/*.cpp)
file(GLOB LIB_HEADERS
*.h
isa/*.h
@@ -19,7 +20,8 @@ file(GLOB LIB_HEADERS
syscall/*.h
graphics/*.h
assembler/*.h
- io/*.h)
+ io/*.h
+ utilities/*.h)
file(GLOB LIB_UIS
*.ui
cachesim/*.ui

MODIFY
src/assembler/assembler.h
src/assembler/assembler.h
@@ -59,12 +59,7 @@ public:
return {};
}
- void setSegmentBase(Section seg, uint32_t base) {
- if (m_sectionBasePointers.count(seg) != 0) {
- throw std::runtime_error("Base address already set for segment '" + seg.toStdString() + +"'");
- }
- m_sectionBasePointers[seg] = base;
- }
+ void setSegmentBase(Section seg, uint32_t base) { m_sectionBasePointers[seg] = base; }
virtual AssembleResult assemble(const QStringList& programLines) const = 0;
AssembleResult assembleRaw(const QString& program) const {

MODIFY
src/assembler/rv32i_assembler.cpp
src/assembler/rv32i_assembler.cpp
#include "rv32i_assembler.h"
#include "gnudirectives.h"
#include "rvrelocations.h"
+#include "ripessettings.h"
#include <QByteArray>
#include <algorithm>
@@ -16,9 +17,17 @@ RV32I_Assembler::RV32I_Assembler(const ISAInfo<ISA::RV32I>* isa) : Assembler(isa
initialize(instrs, pseudos, directives, relocations);
// Initialize segment pointers
- setSegmentBase(".text", 0x0);
- setSegmentBase(".data", 0x10000000);
- setSegmentBase(".bss", 0x11000000);
+ setSegmentBase(".text", RipesSettings::value(RIPES_SETTING_ASSEMBLER_TEXTSTART).toUInt());
+ setSegmentBase(".data", RipesSettings::value(RIPES_SETTING_ASSEMBLER_DATASTART).toUInt());
+ setSegmentBase(".bss", RipesSettings::value(RIPES_SETTING_ASSEMBLER_BSSSTART).toUInt());
+
+ // Monitor settings changes to segment pointers
+ connect(RipesSettings::getObserver(RIPES_SETTING_ASSEMBLER_TEXTSTART), &SettingObserver::modified,
+ [this](const QVariant& value) { setSegmentBase(".text", value.toUInt()); });
+ connect(RipesSettings::getObserver(RIPES_SETTING_ASSEMBLER_DATASTART), &SettingObserver::modified,
+ [this](const QVariant& value) { setSegmentBase(".data", value.toUInt()); });
+ connect(RipesSettings::getObserver(RIPES_SETTING_ASSEMBLER_BSSSTART), &SettingObserver::modified,
+ [this](const QVariant& value) { setSegmentBase(".bss", value.toUInt()); });
}
std::tuple<InstrVec, PseudoInstrVec> RV32I_Assembler::initInstructions(const ISAInfo<ISA::RV32I>* isa) const {

MODIFY
src/assembler/rv32i_assembler.h
src/assembler/rv32i_assembler.h
#include "assembler.h"
+#include <QObject>
#include <functional>
namespace Ripes {
namespace Assembler {
-class RV32I_Assembler : public Assembler {
+class RV32I_Assembler : public QObject, public Assembler {
+ Q_OBJECT
public:
RV32I_Assembler(const ISAInfo<ISA::RV32I>* isa);

MODIFY
src/ripessettings.h
src/ripessettings.h
@@ -18,6 +18,10 @@ namespace Ripes {
#define RIPES_SETTING_CONSOLEFONT ("console_font")
#define RIPES_SETTING_INDENTAMT ("editor_indent")
+#define RIPES_SETTING_ASSEMBLER_TEXTSTART ("text_start")
+#define RIPES_SETTING_ASSEMBLER_DATASTART ("data_start")
+#define RIPES_SETTING_ASSEMBLER_BSSSTART ("bss_start")
+
// Program state preserving settings
#define RIPES_SETTING_SETTING_TAB ("settings_tab")
#define RIPES_SETTING_VIEW_ZOOM ("view_zoom")
@@ -40,6 +44,10 @@ const static std::map<QString, QVariant> s_defaultSettings = {
{RIPES_SETTING_CONSOLEFONT, QColor(Qt::black)},
{RIPES_SETTING_INDENTAMT, 4},
+ {RIPES_SETTING_ASSEMBLER_TEXTSTART, 0x0},
+ {RIPES_SETTING_ASSEMBLER_DATASTART, 0x10000000},
+ {RIPES_SETTING_ASSEMBLER_BSSSTART, 0x11000000},
+
// Program state preserving settings
{RIPES_SETTING_SETTING_TAB, 0},
{RIPES_SETTING_VIEW_ZOOM, 250},

MODIFY
src/settingsdialog.cpp
src/settingsdialog.cpp
#include <QSpacerItem>
#include <QSpinBox>
#include <QStackedWidget>
+#include "utilities/hexspinbox.h"
namespace Ripes {
@@ -46,6 +47,10 @@ std::pair<QLabel*, T_TriggerWidget*> createSettingsWidgets(const QString& settin
widget->setValue(settingObserver->value().toUInt());
widget->connect(widget, QOverload<int>::of(&QSpinBox::valueChanged), settingObserver,
&SettingObserver::setValue);
+ } else if constexpr (std::is_same<T_EditWidget, HexSpinBox>()) {
+ widget->setValue(settingObserver->value().toUInt());
+ widget->connect(widget, QOverload<int>::of(&QSpinBox::valueChanged), settingObserver,
+ &SettingObserver::setValue);
} else if constexpr (std::is_same<T_EditWidget, QLineEdit>()) {
widget->connect(widget, &QLineEdit::textChanged, settingObserver, &SettingObserver::setValue);
widget->setText(settingObserver->value().toString());
@@ -135,6 +140,10 @@ void SettingsDialog::accept() {
QWidget* SettingsDialog::createCompilerPage() {
auto [pageWidget, pageLayout] = constructPage();
+ /***********************************************************************
+ * Compiler settings
+ **********************************************************************/
+
// Setting: RIPES_SETTING_CCPATH
CCManager::get();
@@ -206,6 +215,23 @@ QWidget* SettingsDialog::createCompilerPage() {
// Trigger initial rehighlighting
CCManager::get().trySetCC(m_ccpath->text());
+ /***********************************************************************
+ * Assembler settings
+ **********************************************************************/
+
+ auto* ASMGroupBox = new QGroupBox("Assembler");
+ auto* ASMLayout = new QGridLayout();
+ ASMGroupBox->setLayout(ASMLayout);
+
+ appendToLayout(createSettingsWidgets<HexSpinBox>(RIPES_SETTING_ASSEMBLER_TEXTSTART, ".text section start address:"),
+ ASMLayout);
+ appendToLayout(createSettingsWidgets<HexSpinBox>(RIPES_SETTING_ASSEMBLER_DATASTART, ".data section start address:"),
+ ASMLayout);
+ appendToLayout(createSettingsWidgets<HexSpinBox>(RIPES_SETTING_ASSEMBLER_BSSSTART, ".bss section start address:"),
+ ASMLayout);
+
+ pageLayout->addWidget(ASMGroupBox);
+
return pageWidget;
}
@@ -292,6 +318,12 @@ QWidget* SettingsDialog::createEnvironmentPage() {
return pageWidget;
}
+void SettingsDialog::appendToLayout(std::pair<QLabel*, QWidget*> settingsWidgets, QGridLayout* pageLayout) {
+ const unsigned row = pageLayout->rowCount();
+ pageLayout->addWidget(settingsWidgets.first, row, 0);
+ pageLayout->addWidget(settingsWidgets.second, row, 1);
+}
+
void SettingsDialog::addPage(const QString& name, QWidget* page) {
const int index = m_ui->settingsPages->addWidget(page);
m_pageIndex[name] = index;

MODIFY
src/settingsdialog.h
src/settingsdialog.h
QT_FORWARD_DECLARE_CLASS(QLineEdit);
QT_FORWARD_DECLARE_CLASS(QLabel);
+QT_FORWARD_DECLARE_CLASS(QGridLayout);
namespace Ripes {
@@ -39,6 +40,7 @@ private:
Ui::SettingsDialog* m_ui;
void addPage(const QString& name, QWidget* page);
+ void appendToLayout(std::pair<QLabel*, QWidget*> settingsWidgets, QGridLayout* pageLayout);
std::map<QString, int> m_pageIndex;
};

ADD
src/utilities/hexspinbox.h
+#pragma once
+
+#include <QSpinBox>
+
+namespace Ripes {
+
+class HexSpinBox : public QSpinBox {
+public:
+ HexSpinBox(QWidget* parent = 0) : QSpinBox(parent) {
+ setPrefix("0x");
+ setDisplayIntegerBase(16);
+ setRange(INT_MIN, INT_MAX);
+ }
+
+protected:
+ QString textFromValue(int value) const override {
+ return QString::number(static_cast<unsigned>(value), 16).rightJustified(8, '0').toUpper();
+ }
+ int valueFromText(const QString& text) const override {
+ int v = sanitize(text).toUInt(nullptr, 16);
+ return v;
+ }
+ QValidator::State validate(QString& input, int& pos) const {
+ bool okay;
+ unsigned int val = sanitize(input).toUInt(&okay, 16);
+ if (!okay)
+ return QValidator::Invalid;
+ return QValidator::Acceptable;
+ }
+
+private:
+ QString sanitize(const QString& input) const {
+ QString copy(input);
+ if (copy.startsWith("0x"))
+ copy.remove(0, 2);
+ return copy;
+ }
+};
+
+} // namespace Ripes

Make assembler segment base pointers adjustable through settings