From 6fbe35623e292f077f068cecc537064f06125399 Mon Sep 17 00:00:00 2001 From: Morten Borup Petersen Date: Mon, 25 Sep 2023 21:32:59 +0200 Subject: [PATCH 1/5] Make darkmode default --- src/ripessettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ripessettings.cpp b/src/ripessettings.cpp index 723728255..36ad11830 100644 --- a/src/ripessettings.cpp +++ b/src/ripessettings.cpp @@ -65,7 +65,7 @@ const std::map s_defaultSettings = { {RIPES_SETTING_PROCESSOR_LAYOUT_ID, 0}, {RIPES_SETTING_FOLLOW_EXEC, "true"}, {RIPES_SETTING_SOURCECODE, ""}, - {RIPES_SETTING_DARKMODE, false}, + {RIPES_SETTING_DARKMODE, true}, {RIPES_SETTING_SHOWSIGNALS, false}, {RIPES_SETTING_INPUT_TYPE, static_cast(SourceType::Assembly)}, {RIPES_SETTING_AUTOCLOCK_INTERVAL, 100}, From 1530917ee61e148d738b9387434d54dfa8f16232 Mon Sep 17 00:00:00 2001 From: Morten Borup Petersen Date: Tue, 26 Sep 2023 17:44:40 +0200 Subject: [PATCH 2/5] Disable various features on WASM --- src/edittab.cpp | 3 +++ src/mainwindow.cpp | 10 ++++++---- src/settingsdialog.cpp | 6 +++++- src/wasmSupport.h | 22 ++++++++++++++++++++++ 4 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 src/wasmSupport.h diff --git a/src/edittab.cpp b/src/edittab.cpp index b433cb4e4..34b4e2648 100644 --- a/src/edittab.cpp +++ b/src/edittab.cpp @@ -20,6 +20,7 @@ #include "processorhandler.h" #include "ripessettings.h" #include "symbolnavigator.h" +#include "wasmSupport.h" namespace Ripes { @@ -87,6 +88,8 @@ EditTab::EditTab(QToolBar *toolbar, QWidget *parent) &EditTab::sourceTypeChanged); connect(m_ui->setCInput, &QRadioButton::toggled, m_buildAction, &QAction::setEnabled); + // C compiler is not yet supported on WASM. + disableIfWasm(m_ui->setCInput); // Ensure that changes to the current compiler path will disable C input, if // the compiler is invalid diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 879a54de3..95120eacb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -15,6 +15,7 @@ #include "syscall/syscallviewer.h" #include "syscall/systemio.h" #include "version/version.h" +#include "wasmSupport.h" #include "fancytabbar/fancytabbar.h" @@ -204,7 +205,6 @@ void MainWindow::setupMenus() { connect(loadAction, &QAction::triggered, this, [=] { this->loadFileTriggered(); }); m_ui->menuFile->addAction(loadAction); - m_ui->menuFile->addSeparator(); auto *examplesMenu = m_ui->menuFile->addMenu("Load Example..."); @@ -231,7 +231,6 @@ void MainWindow::setupMenus() { &EditTab::editorStateChanged, saveAction, [saveAsAction](bool enabled) { saveAsAction->setEnabled(enabled); }); m_ui->menuFile->addAction(saveAsAction); - m_ui->menuFile->addSeparator(); const QIcon exitIcon = QIcon(":/icons/cancel.svg"); @@ -246,6 +245,9 @@ void MainWindow::setupMenus() { m_ui->menuView->addAction( static_cast(m_tabWidgets.at(ProcessorTabID).tab) ->m_displayValuesAction); + + // File I/O is not yet supported on WASM due to sandboxing. + disableIfWasm(QList{loadAction, saveAction, saveAsAction, exitAction}); } MainWindow::~MainWindow() { delete m_ui; } @@ -360,8 +362,8 @@ void MainWindow::loadFileTriggered() { } void MainWindow::wiki() { - QDesktopServices::openUrl( - QUrl(QString("https://github.com/mortbopet/Ripes/blob/master/docs/README.md"))); + QDesktopServices::openUrl(QUrl(QString( + "https://github.com/mortbopet/Ripes/blob/master/docs/README.md"))); } void MainWindow::version() { diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index e34faf1ff..441e2978b 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -21,6 +21,7 @@ #include "utilities/hexspinbox.h" #include "utilities/scrolleventfilter.h" +#include "wasmSupport.h" namespace Ripes { @@ -148,7 +149,10 @@ SettingsDialog::SettingsDialog(QWidget *parent) // Create settings pages addPage("Environment", createEnvironmentPage()); addPage("Simulator", createSimulatorPage()); - addPage("Compiler", createCompilerPage()); + auto *compilerPage = createCompilerPage(); + addPage("Compiler", compilerPage); + // No C compiler support (yet) for wasm. + disableIfWasm(compilerPage); addPage("Editor", createEditorPage()); m_ui->settingsList->setCurrentRow( diff --git a/src/wasmSupport.h b/src/wasmSupport.h new file mode 100644 index 000000000..2643f060b --- /dev/null +++ b/src/wasmSupport.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +namespace Ripes { + +// Disable a widget if we are running in a wasm environment. +template +inline void disableIfWasm(T *widget) { +#ifdef __EMSCRIPTEN__ + widget->setEnabled(false); +#endif +} + +// Disables a list of widgets if we are running in a wasm environment. +template +inline void disableIfWasm(TList widgets) { + for (auto *widget : widgets) + disableIfWasm(widget); +} + +} // namespace Ripes \ No newline at end of file From 98ea1b24996d6d84085ea161027b897e0cce66a8 Mon Sep 17 00:00:00 2001 From: Morten Borup Petersen Date: Tue, 26 Sep 2023 18:37:08 +0200 Subject: [PATCH 3/5] Address various deprecation warnings --- src/assembler/assembler.h | 2 +- src/assembler/gnudirectives.cpp | 2 +- src/cachesim/cacheplotview.cpp | 4 ++-- src/cachesim/cacheplotwidget.cpp | 10 +++++----- src/cachesim/cacheview.cpp | 2 +- src/ccmanager.cpp | 2 +- src/cli/clioptions.cpp | 2 +- src/editor/csyntaxhighlighter.cpp | 2 +- src/editor/rvsyntaxhighlighter.cpp | 4 ++-- src/flowlayout.cpp | 4 ++-- src/processmanager.h | 6 +++--- src/processorselectiondialog.cpp | 2 +- src/savedialog.cpp | 2 +- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/assembler/assembler.h b/src/assembler/assembler.h index 2f219bba0..8d8c4048e 100644 --- a/src/assembler/assembler.h +++ b/src/assembler/assembler.h @@ -176,7 +176,7 @@ class Assembler : public AssemblerBase { // Join tokens QString joinedLine; const auto tokens = std::get(tokensVar); - for (const auto &token : qAsConst(tokens)) { + for (const auto &token : std::as_const(tokens)) { joinedLine += token + " "; } joinedLine.chop(1); // remove trailing ' ' diff --git a/src/assembler/gnudirectives.cpp b/src/assembler/gnudirectives.cpp index 6d75ea483..55bd9044a 100644 --- a/src/assembler/gnudirectives.cpp +++ b/src/assembler/gnudirectives.cpp @@ -11,7 +11,7 @@ static QString numTokensError(unsigned expected, const TokenizedSrcLine &line) { std::to_string(line.tokens.size()) + "["); for (auto t : llvm::enumerate(line.tokens)) { err += t.value(); - if (t.index() < (line.tokens.size() - 1)) + if (static_cast(t.index()) < (line.tokens.size() - 1)) err += ", "; }; err += "]."; diff --git a/src/cachesim/cacheplotview.cpp b/src/cachesim/cacheplotview.cpp index c424ad91e..45a4f4cee 100644 --- a/src/cachesim/cacheplotview.cpp +++ b/src/cachesim/cacheplotview.cpp @@ -92,14 +92,14 @@ QPixmap CachePlotView::getPlotPixmap() { itemsToHide << marker->marker; } - for (const auto &i : qAsConst(itemsToHide)) { + for (const auto &i : std::as_const(itemsToHide)) { if (i) i->hide(); } QPixmap p = grab(); - for (const auto &i : qAsConst(itemsToHide)) { + for (const auto &i : std::as_const(itemsToHide)) { if (i) i->show(); } diff --git a/src/cachesim/cacheplotwidget.cpp b/src/cachesim/cacheplotwidget.cpp index 475028e74..b12c873a4 100644 --- a/src/cachesim/cacheplotwidget.cpp +++ b/src/cachesim/cacheplotwidget.cpp @@ -344,7 +344,7 @@ CachePlotWidget::gatherData(unsigned fromCycle) const { void resample(QLineSeries *series, unsigned target, double &step) { QVector newPoints; - const auto &oldPoints = series->pointsVector(); + const auto &oldPoints = series->points(); step = (oldPoints.last().x() / static_cast(target)) * 2; // *2 to account for steps newPoints.reserve(target); @@ -356,7 +356,7 @@ void resample(QLineSeries *series, unsigned target, double &step) { // sanity check QPointF plast = QPointF(0, 0); bool first = true; - for (const auto &p : qAsConst(newPoints)) { + for (const auto &p : std::as_const(newPoints)) { if (!first) { Q_ASSERT(p.x() - plast.x() < step * 1.1); first = false; @@ -426,8 +426,8 @@ void CachePlotWidget::updateRatioPlot() { QList newPoints; QList newWindowPoints; QPointF lastPoint; - if (m_series->pointsVector().size() > 0) { - lastPoint = m_series->pointsVector().constLast(); + if (m_series->points().size() > 0) { + lastPoint = m_series->points().constLast(); } else { lastPoint = QPointF(-1, 0); } @@ -489,7 +489,7 @@ void CachePlotWidget::updateRatioPlot() { // points, and we resample at a 2x ratio const int maxPoints = RipesSettings::value(RIPES_SETTING_CACHE_MAXPOINTS).toInt() * 2 * 2; - if (m_series->pointsVector().size() >= maxPoints) { + if (m_series->points().size() >= maxPoints) { resample(m_series, maxPoints / 2, m_xStep); } diff --git a/src/cachesim/cacheview.cpp b/src/cachesim/cacheview.cpp index 74d34b8f3..a2dac7196 100644 --- a/src/cachesim/cacheview.cpp +++ b/src/cachesim/cacheview.cpp @@ -21,7 +21,7 @@ void CacheView::mousePressEvent(QMouseEvent *event) { // and emit a signal indicating that the address was selected through the // cache const auto viewItems = items(event->pos()); - for (const auto &item : qAsConst(viewItems)) { + for (const auto &item : std::as_const(viewItems)) { if (auto *textItem = dynamic_cast(item)) { const QVariant userData = textItem->data(Qt::UserRole); if (userData.isValid()) { diff --git a/src/ccmanager.cpp b/src/ccmanager.cpp index c852f2cf1..84a0df879 100644 --- a/src/ccmanager.cpp +++ b/src/ccmanager.cpp @@ -20,7 +20,7 @@ const static QString s_testprogram = "int main() { return 0; }"; QString indentString(const QString &string, int indent) { auto subStrings = string.split("\n"); auto indentedStrings = QStringList(); - for (const auto &str : qAsConst(subStrings)) { + for (const auto &str : std::as_const(subStrings)) { indentedStrings << QString(" ").repeated(indent) + str; } return indentedStrings.join("\n"); diff --git a/src/cli/clioptions.cpp b/src/cli/clioptions.cpp index 4cc909962..80f506248 100644 --- a/src/cli/clioptions.cpp +++ b/src/cli/clioptions.cpp @@ -111,7 +111,7 @@ bool parseCLIOptions(QCommandLineParser &parser, QString &errorMessage, .isaInfo() .supportedExtensions; - for (auto &ext : qAsConst(options.isaExtensions)) { + for (auto &ext : std::as_const(options.isaExtensions)) { if (!exts.contains(ext)) { errorMessage = "Invalid ISA extension '" + ext + "' specified (--isaexts)."; diff --git a/src/editor/csyntaxhighlighter.cpp b/src/editor/csyntaxhighlighter.cpp index 22f562d79..d066ae376 100644 --- a/src/editor/csyntaxhighlighter.cpp +++ b/src/editor/csyntaxhighlighter.cpp @@ -76,7 +76,7 @@ CSyntaxHighlighter::CSyntaxHighlighter( } // namespace Ripes void CSyntaxHighlighter::syntaxHighlightBlock(const QString &text) { - for (const HighlightingRule &rule : qAsConst(highlightingRules)) { + for (const HighlightingRule &rule : std::as_const(highlightingRules)) { QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); while (matchIterator.hasNext()) { diff --git a/src/editor/rvsyntaxhighlighter.cpp b/src/editor/rvsyntaxhighlighter.cpp index 0c6a769ce..0df5112f6 100644 --- a/src/editor/rvsyntaxhighlighter.cpp +++ b/src/editor/rvsyntaxhighlighter.cpp @@ -24,7 +24,7 @@ RVSyntaxHighlighter::RVSyntaxHighlighter( << "\\bgp\\b" << "\\btp\\b" << "\\bfp\\b"; - for (const auto &pattern : qAsConst(registerPatterns)) { + for (const auto &pattern : std::as_const(registerPatterns)) { rule.pattern = QRegularExpression(pattern); rule.format = registerFormat; m_highlightingRules.append(rule); @@ -70,7 +70,7 @@ RVSyntaxHighlighter::RVSyntaxHighlighter( } void RVSyntaxHighlighter::syntaxHighlightBlock(const QString &text) { - for (const HighlightingRule &rule : qAsConst(m_highlightingRules)) { + for (const HighlightingRule &rule : std::as_const(m_highlightingRules)) { QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); while (matchIterator.hasNext()) { diff --git a/src/flowlayout.cpp b/src/flowlayout.cpp index 65965cdb1..32d35d3aa 100644 --- a/src/flowlayout.cpp +++ b/src/flowlayout.cpp @@ -132,7 +132,7 @@ QSize FlowLayout::sizeHint() const { return minimumSize(); } QSize FlowLayout::minimumSize() const { QSize size; - for (const QLayoutItem *item : qAsConst(itemList)) + for (const QLayoutItem *item : std::as_const(itemList)) size = size.expandedTo(item->minimumSize()); const QMargins margins = contentsMargins(); @@ -153,7 +153,7 @@ int FlowLayout::doLayout(const QRect &rect, bool testOnly) const { //! [9] //! [10] - for (QLayoutItem *item : qAsConst(itemList)) { + for (QLayoutItem *item : std::as_const(itemList)) { int spaceX = horizontalSpacing(); int spaceY = verticalSpacing(); if (spaceX == -1) diff --git a/src/processmanager.h b/src/processmanager.h index 129026443..028f7d522 100644 --- a/src/processmanager.h +++ b/src/processmanager.h @@ -154,8 +154,8 @@ class ProcessManager { static bool hasValidProgram() { return false; } static const QString &program() { return get().m_programPath; } static QString getError() { return QString(); } - static ProcessResult run(const QStringList &args, - bool showProgressDialog = false) { + static ProcessResult run(const QStringList &, + bool = false) { return ProcessResult(); } @@ -165,7 +165,7 @@ class ProcessManager { } signals: - bool trySetProgram(const QString &path) { return false; } + bool trySetProgram(const QString &) { return false; } private: QString m_programPath; diff --git a/src/processorselectiondialog.cpp b/src/processorselectiondialog.cpp index f69a66c22..cf593bb5c 100644 --- a/src/processorselectiondialog.cpp +++ b/src/processorselectiondialog.cpp @@ -160,7 +160,7 @@ void ProcessorSelectionDialog::selectionChanged(QTreeWidgetItem *current, delete item; } - for (const auto &ext : qAsConst(isaInfo.supportedExtensions)) { + for (const auto &ext : std::as_const(isaInfo.supportedExtensions)) { auto chkbox = new QCheckBox(ext); chkbox->setToolTip(isaInfo.isa->extensionDescription(ext)); m_ui->extensions->addWidget(chkbox); diff --git a/src/savedialog.cpp b/src/savedialog.cpp index d50bbb940..47aaf9049 100644 --- a/src/savedialog.cpp +++ b/src/savedialog.cpp @@ -50,7 +50,7 @@ void SaveDialog::accept() { void SaveDialog::pathChanged() { bool okEnabled = !QFileInfo(m_ui->filePath->text()).fileName().isEmpty(); - okEnabled &= m_ui->saveSource->isChecked() | m_ui->saveBinary->isChecked(); + okEnabled &= m_ui->saveSource->isChecked() || m_ui->saveBinary->isChecked(); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(okEnabled); From 5f8ad5dfd33ca3581bd1837e1463491bbfc4ecaa Mon Sep 17 00:00:00 2001 From: Morten Borup Petersen Date: Tue, 26 Sep 2023 18:37:15 +0200 Subject: [PATCH 4/5] bump VSRTL --- external/VSRTL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/VSRTL b/external/VSRTL index a7f17baf2..8cb60adf6 160000 --- a/external/VSRTL +++ b/external/VSRTL @@ -1 +1 @@ -Subproject commit a7f17baf2f5cee4a9946d987a74348ab75375d25 +Subproject commit 8cb60adf6f197638fe598ba232619c68aa601a38 From c56dfb2b97a5b8ca61a77536b671d8b6f1c289ee Mon Sep 17 00:00:00 2001 From: Stelios Karagiorgis <108999173+SteliosKaragiorgis@users.noreply.github.com> Date: Thu, 28 Sep 2023 12:16:44 +0300 Subject: [PATCH 5/5] Add MIPS ISA (#290) Add MIPS32 to isainfo.h --- src/isa/CMakeLists.txt | 6 + src/isa/isainfo.h | 6 +- src/isa/mips32isainfo.h | 33 ++++++ src/isa/mipsisainfo_common.cpp | 61 ++++++++++ src/isa/mipsisainfo_common.h | 211 +++++++++++++++++++++++++++++++++ 5 files changed, 314 insertions(+), 3 deletions(-) create mode 100644 src/isa/mips32isainfo.h create mode 100644 src/isa/mipsisainfo_common.cpp create mode 100644 src/isa/mipsisainfo_common.h diff --git a/src/isa/CMakeLists.txt b/src/isa/CMakeLists.txt index bd24cb686..4649502b6 100644 --- a/src/isa/CMakeLists.txt +++ b/src/isa/CMakeLists.txt @@ -1 +1,7 @@ create_ripes_lib(isa LINK_TO_RIPES_LIB) + +target_sources(isa_lib + PRIVATE + mipsisainfo_common.h mipsisainfo_common.cpp + mips32isainfo.h +) diff --git a/src/isa/isainfo.h b/src/isa/isainfo.h index 5aa0f54c1..cba8a9b1f 100644 --- a/src/isa/isainfo.h +++ b/src/isa/isainfo.h @@ -12,9 +12,9 @@ namespace Ripes { /// List of currently supported ISAs. -enum class ISA { RV32I, RV64I }; -const static std::map ISAFamilyNames = {{ISA::RV32I, "RISC-V"}, - {ISA::RV64I, "RISC-V"}}; +enum class ISA { RV32I, RV64I, MIPS32I }; +const static std::map ISAFamilyNames = { + {ISA::RV32I, "RISC-V"}, {ISA::RV64I, "RISC-V"}, {ISA::MIPS32I, "MIPS"}}; enum class RegisterFileType { GPR, FPR, CSR }; struct RegisterFileName { QString shortName; diff --git a/src/isa/mips32isainfo.h b/src/isa/mips32isainfo.h new file mode 100644 index 000000000..2ade3f7c6 --- /dev/null +++ b/src/isa/mips32isainfo.h @@ -0,0 +1,33 @@ +#pragma once + +#include "isainfo.h" +#include "mipsisainfo_common.h" + +namespace Ripes { + +template <> +class ISAInfo : public MIPSISAInfoBase { +public: + ISAInfo(const QStringList extensions) { + // Validate extensions + for (const auto &ext : extensions) { + if (supportsExtension(ext)) { + m_enabledExtensions << ext; + } + } + } + + ISA isaID() const override { return ISA::MIPS32I; } + + unsigned int bits() const override { return 32; } + unsigned elfMachineId() const override { return EM_MIPS; } + QString CCmarch() const override { + QString march = "mips32i"; + return march; + } + QString CCmabi() const override { return "ilp32"; } + + unsigned instrByteAlignment() const override { return 4; }; +}; + +} // namespace Ripes diff --git a/src/isa/mipsisainfo_common.cpp b/src/isa/mipsisainfo_common.cpp new file mode 100644 index 000000000..18260feaa --- /dev/null +++ b/src/isa/mipsisainfo_common.cpp @@ -0,0 +1,61 @@ +#include "mipsisainfo_common.h" + +namespace Ripes { +namespace MIPSISA { + +// clang-format off +const QStringList RegAliases = QStringList() << "zero" + << "at" << "v0" << "v1" << "a0" << "a1" << "a2" << "a3" << "t0" << "t1" << "t2" + << "t3" << "t4" << "t5" << "t6" << "t7" << "s0" << "s1" << "s2" << "s3" << "s4" + << "s5" << "s6" << "s7" << "t8" << "t9" << "k0" << "k1" << "gp" << "sp" << "fp" + << "ra" << "hi" << "lo"; + +const QStringList RegNames = QStringList() << "$0" + << "$1" << "$2" << "$3" << "$4" << "$5" << "$6" << "$7" << "$8" + << "$9" << "$10" << "$11" << "$12" << "$13" << "$14" << "$15" + << "$16" << "$17" << "$18" << "$19" << "$20" << "$21" << "$22" << "$23" + << "$24" << "$25" << "$26" << "$27" << "$28" << "$29" << "$30" << "$31" << "$32" << "$33"; + +const QStringList RegDescs = QStringList() << "Hard-Wired zero" + << "Assembler Temporary" + << "Return value from function call" + << "Return value from function call" + << "Argument 1" + << "Argument 2" + << "Argument 3" + << "Argument 4" + << "Temporary\nNot preserved across call" + << "Temporary\nNot preserved across call" + << "Temporary\nNot preserved across call" + << "Temporary\nNot preserved across call" + << "Temporary\nNot preserved across call" + << "Temporary\nNot preserved across call" + << "Temporary\nNot preserved across call" + << "Temporary\nNot preserved across call" + << "Saved Temporary\nPreserved across call" + << "Saved Temporary\nPreserved across call" + << "Saved Temporary\nPreserved across call" + << "Saved Temporary\nPreserved across call" + << "Saved Temporary\nPreserved across call" + << "Saved Temporary\nPreserved across call" + << "Saved Temporary\nPreserved across call" + << "Saved Temporary\nPreserved across call" + << "Temporary\nNot preserved across call" + << "Temporary\nNot preserved across call" + << "Kernel use register" + << "Kernel use register" + << "Global pointer" + << "Stack pointer" + << "Frame pointer" + << "Return Address" + << "Multiplication/Division register" + << "Multiplication/Division register"; +// clang-format on +} // namespace MIPSISA + +namespace MIPSABI { +const std::map ELFFlagStrings{ + {NOREORDER, "NOREORDER"}, {PIC, "PIC"}, {CPIC, "CPIC"}, {ARCH, "ARCH"}}; +} + +} // namespace Ripes diff --git a/src/isa/mipsisainfo_common.h b/src/isa/mipsisainfo_common.h new file mode 100644 index 000000000..f5a7f5dc9 --- /dev/null +++ b/src/isa/mipsisainfo_common.h @@ -0,0 +1,211 @@ +#pragma once + +#include "isainfo.h" +#include + +namespace Ripes { + +template +constexpr ISA XLenToMIPSISA() { + static_assert(XLEN == 32, "Only supports 32-bit variants"); + return ISA::MIPS32I; +} + +namespace MIPSISA { + +extern const QStringList RegAliases; +extern const QStringList RegNames; +extern const QStringList RegDescs; +enum Opcode { + ADDI = 0b001000, + ADDIU = 0b001001, + ANDI = 0b001100, + RTYPE = 0b000000, + ORI = 0b001101, + XORI = 0b001110, + LHI = 0b011001, + LLO = 0b011000, + SLTI = 0b001010, + SLTIU = 0b001011, + BEQ = 0b000100, + BGEZ = 0b000001, + BGTZ = 0b000111, + BLEZ = 0b000110, + BLTZ = 0b000001, + BNE = 0b000101, + J = 0b000010, + JAL = 0b000011, + LB = 0b100000, + LBU = 0b100100, + LH = 0b100001, + LHU = 0b100101, + LUI = 0b001111, + LW = 0b100011, + LWC1 = 0b110001, + SB = 0b101000, + SH = 0b101001, + SW = 0b101011, + SWC1 = 0b111001, + TRAP = 0b011010 +}; + +enum Function { + ADD = 0b100000, + ADDU = 0b100001, + AND = 0b100100, + DIV = 0b011010, + DIVU = 0b011011, + MULT = 0b011000, + MULTU = 0b011001, + NOR = 0b100111, + OR = 0b100101, + SLL = 0b000000, + SLLV = 0b000100, + SRA = 0b000011, + SRAV = 0b000111, + SRL = 0b000010, + SRLV = 0b000110, + SUB = 0b100010, + SUBU = 0b100011, + XOR = 0b100110, + SLT = 0b101010, + SLTU = 0b101001, + JALR = 0b001001, + JR = 0b001000, + MFHI = 0b010000, + MFLO = 0b010010, + MTHI = 0b010001, + MTLO = 0b010011, + BREAK = 0b001101, + SYSCALL = 0b001100 +}; + +} // namespace MIPSISA + +namespace MIPSABI { +// MIPS ELF info +// Elf flag masks +enum MIPSElfFlags { NOREORDER = 0b1, PIC = 0b10, CPIC = 0b100, ARCH = 0b0 }; +extern const std::map ELFFlagStrings; + +enum SysCall { + None = 0, + PrintInt = 1, + PrintFloat = 2, + PrintDouble = 3, + PrintStr = 4, + ReadInt = 5, + ReadFloat = 6, + ReadDouble = 7, + ReadString = 8, + Sbrk = 9, + Exit = 10, + PrintChar = 11, + ReadChar = 12, + Open = 13, + Read = 14, + Write = 15, + Close = 16, + Exit2 = 17, + Time = 30, + MIDIout = 31, + Sleep = 32, + MIDIoutSynchronous = 33, + PrintIntHex = 34, + PrintIntBinary = 35, + PrintIntUnsigned = 36, + SetSeed = 40, + RandomInt = 41, + RandomIntRange = 42, + RandomFloat = 43, + RandomDouble = 44, + ConfirmDialog = 50, + InputDialogInt = 51, + InputDialogFloat = 52, + InputDialogDouble = 53, + InutDialogString = 54, + MessageDialog = 55, + MessageDialogInt = 56, + MessageDialogFloat = 57, + MessageDialogDouble = 58, + MessageDialogString = 59 + +}; + +} // namespace MIPSABI + +class MIPSISAInfoBase : public ISAInfoBase { +public: + unsigned int regCnt() const override { return 34; } + QString regName(unsigned i) const override { + return (MIPSISA::RegNames.size() > static_cast(i) + ? MIPSISA::RegNames.at(static_cast(i)) + : QString()); + } + QString regAlias(unsigned i) const override { + return MIPSISA::RegAliases.size() > static_cast(i) + ? MIPSISA::RegAliases.at(static_cast(i)) + : QString(); + } + QString regInfo(unsigned i) const override { + return MIPSISA::RegDescs.size() > static_cast(i) + ? MIPSISA::RegDescs.at(static_cast(i)) + : QString(); + } + QString name() const override { return CCmarch().toUpper(); } + bool regIsReadOnly(unsigned i) const override { return i == 0; } + int spReg() const override { return 29; } + int gpReg() const override { return 28; } + int syscallReg() const override { return 2; } + unsigned instrBits() const override { return 32; } + unsigned elfMachineId() const override { return EM_MIPS; } + unsigned int regNumber(const QString ®, bool &success) const override { + QString regRes = reg; + success = true; + if (reg[0] != '$') { + success = false; + return 0; + } + + QString regNoDollar = regRes.remove('$'); + + if (MIPSISA::RegNames.count(reg) != 0) { + regRes.remove('$'); + return regRes.toInt(&success, 10); + } else if (int idx = MIPSISA::RegAliases.indexOf(regNoDollar); idx != -1) { + return idx; + } + success = false; + return 0; + } + virtual int syscallArgReg(unsigned argIdx) const override { + assert(argIdx < 2 && "MIPS only implements argument registers a0-a7"); + return argIdx + 4; + } + + QString elfSupportsFlags(unsigned flags) const override { + if (flags == 0) + return QString(); + for (const auto &flag : MIPSABI::ELFFlagStrings) + flags &= ~flag.first; + + if (flags != 0) { + return "ELF flag '0b" + QString::number(flags, 2) + "' unsupported"; + } + return QString(); + } + + const QStringList &supportedExtensions() const override { + return m_supportedExtensions; + } + const QStringList &enabledExtensions() const override { + return m_enabledExtensions; + } + QString extensionDescription(const QString &ext) const override { return ""; } + +protected: + QStringList m_enabledExtensions; + QStringList m_supportedExtensions = {""}; +}; + +} // namespace Ripes