Load assembler directives into Data segment of simulator
MODIFY
src/codeeditor.cpp
src/codeeditor.cpp
#include "codeeditor.h"
#include "defines.h"
+#include "pipeline.h"
#include <QAction>
#include <QApplication>
@@ -72,6 +73,9 @@ void CodeEditor::assembleCode() {
err.exec();
}
}
+ // Restart the simulator to trigger the data memory to be loaded into the main memory. Bad code that this is done
+ // from here, but it works
+ Pipeline::getPipeline()->restart();
}
int CodeEditor::lineNumberAreaWidth() {

MODIFY
src/gotocombobox.cpp
src/gotocombobox.cpp
#include "gotocombobox.h"
#include "addressdialog.h"
+#include "defines.h"
#include <QAbstractItemView>
#include <QEvent>
@@ -11,7 +12,8 @@ GoToComboBox::GoToComboBox(QWidget* parent) : QComboBox(parent) {
addItem("Select", 0);
addItem("Address...", 0);
addItem("Text", 0);
- addItem("Stack", 0x7ffffff0);
+ addItem("Data", DATASTART);
+ addItem("Stack", STACKSTART);
// connect to a "signal filter"
connect(this, QOverload<int>::of(&GoToComboBox::activated), this, &GoToComboBox::signalFilter);

MODIFY
src/parser.cpp
src/parser.cpp
@@ -110,6 +110,24 @@ const QString& Parser::loadFromByteArray(QByteArray arr, bool disassembled, uint
}
}
+void Parser::loadFromByteArrayIntoData(QByteArray arr) {
+ // Loads a byte array into the data segment of the simulator
+ // In this, we do no string convertion etc., which is usually done for generating the disassembled view of the
+ // program
+ auto memPtr = Pipeline::getPipeline()->getDataMemoryPtr();
+ auto length = arr.length();
+ QDataStream in(&arr, QIODevice::ReadOnly);
+ char buffer[4];
+ uint32_t byteIndex = DATASTART;
+ for (int i = 0; i < length; i += 4) {
+ in.readRawData(buffer, 4);
+ for (int j = 0; j < 4; j++) {
+ memPtr->insert({byteIndex, buffer[j]});
+ byteIndex++;
+ }
+ }
+}
+
decode_functor Parser::generateWordParser(std::vector<int> bitFields) {
// Generates functors that can decode a binary number based on the input
// vector which is supplied upon generation

MODIFY
src/parser.h
src/parser.h
@@ -38,6 +38,7 @@ public:
QString getInstructionString(uint32_t address) const;
const QString& loadFromByteArray(QByteArray arr, bool disassembled = true, uint32_t baseAddress = 0x0);
+ void loadFromByteArrayIntoData(QByteArray arr);
const QString& loadBinaryFile(QString fileName, bool disassembled = true);
const QString& getBinaryRepr() { return m_binaryRepr; }
const QString& getDisassembledRepr() { return m_disassembledRepr; }

MODIFY
src/pipeline.cpp
src/pipeline.cpp
@@ -781,6 +781,7 @@ void Pipeline::reset() {
// Called when resetting the simulator (loading a new program)
restart();
m_memory.clear();
+ m_dataMemory.clear();
m_breakpoints.clear();
m_textSize = 0;
m_ready = false;
@@ -796,7 +797,9 @@ void Pipeline::update() {
void Pipeline::restart() {
// Called when restarting a simulation
m_reg.clear();
- m_memory.reset(m_textSize);
+ m_memory.reset(m_textSize); // Wipe simulator memory, but keep text segment
+ m_memory.insert(m_dataMemory.begin(),
+ m_dataMemory.end()); // Merge assembler-provided data memory into simulator memory
m_reg.init();
m_pcs.reset();
m_pcsPre.reset();

MODIFY
src/pipeline.h
src/pipeline.h
@@ -21,6 +21,7 @@ public:
// Pointers for GUI
MainMemory* getMemoryPtr() { return &m_memory; }
+ std::unordered_map<uint32_t, uint8_t>* getDataMemoryPtr() { return &m_dataMemory; }
std::vector<uint32_t>* getRegPtr() { return m_reg.getRegPtr(); }
const StagePCS& getStagePCS() const { return m_pcs; }
const StagePCS& getStagePCSPre() const { return m_pcsPre; }
@@ -62,6 +63,8 @@ private:
// Memory
Registers m_reg;
MainMemory m_memory;
+ std::unordered_map<uint32_t, uint8_t> m_dataMemory; // Since the data memory needs to be restarted on a simulator
+ // reset, the assembler-provided data segment must be stored
uint32_t m_textSize = 0;
// Combinatorial items & signals

MODIFY
src/programfiletab.cpp
src/programfiletab.cpp
@@ -65,8 +65,13 @@ void ProgramfileTab::setDisassemblerText() {
void ProgramfileTab::assemblingComplete(const QByteArray& arr, bool clear, uint32_t baseAddress) {
if (clear)
Parser::getParser()->clear();
+ // Pretty hacky way to discern between the text and data segments
+ if (baseAddress > 0) {
+ Parser::getParser()->loadFromByteArrayIntoData(arr);
+ } else {
Parser::getParser()->loadFromByteArray(arr, m_ui->disassembledViewButton->isChecked(), baseAddress);
setDisassemblerText();
+ }
emit updateSimulator();
}

Load assembler directives into Data segment of simulator