Skip to content

Commit

Permalink
Change ISA-specific assemblers into a single template class
Browse files Browse the repository at this point in the history
This change should complete mortbopet#303.
  • Loading branch information
raccog committed Dec 5, 2023
1 parent 3948e7c commit 098474c
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 144 deletions.
20 changes: 20 additions & 0 deletions src/assembler/assembler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "assembler.h"

namespace Ripes {
namespace Assembler {

std::shared_ptr<AssemblerBase>
constructAssemblerDynamic(const std::shared_ptr<const ISAInfoBase> &isa) {
if (auto rv32isa =
std::dynamic_pointer_cast<const ISAInfo<ISA::RV32I>>(isa)) {
return std::make_shared<ISA_Assembler<ISA::RV32I>>(rv32isa);
} else if (auto rv64isa =
std::dynamic_pointer_cast<const ISAInfo<ISA::RV64I>>(isa)) {
return std::make_shared<ISA_Assembler<ISA::RV64I>>(rv64isa);
}

Q_UNREACHABLE();
}

} // namespace Assembler
} // namespace Ripes
58 changes: 51 additions & 7 deletions src/assembler/assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@

#include <QRegularExpression>

#include "assembler_defines.h"
#include "isa/instruction.h"
#include "isa/isa_defines.h"
#include "isa/isa_types.h"
#include "isa/pseudoinstruction.h"
#include "matcher.h"

#include <cstdint>
#include <numeric>
#include <set>
#include <variant>

#include "STLExtras.h"
#include "assembler_defines.h"
#include "assemblerbase.h"
#include "gnudirectives.h"
#include "isa/instruction.h"
#include "isa/isa_defines.h"
#include "isa/isa_types.h"
#include "isa/isainfo.h"
#include "isa/pseudoinstruction.h"
#include "matcher.h"
#include "ripessettings.h"

namespace Ripes {
namespace Assembler {
Expand Down Expand Up @@ -643,6 +644,49 @@ class Assembler : public AssemblerBase {
std::shared_ptr<const ISAInfoBase> m_isa;
};

/// An Assembler and QObject (workaround because QObject cannot be directly
/// subclassed by ISA_Assembler)
class QAssembler : public QObject, public Assembler {
Q_OBJECT
public:
QAssembler(std::shared_ptr<const ISAInfoBase> isaInfo) : Assembler(isaInfo) {
// Initialize segment pointers and monitor settings changes to segment
// pointers
connect(RipesSettings::getObserver(RIPES_SETTING_ASSEMBLER_TEXTSTART),
&SettingObserver::modified, this, [this](const QVariant &value) {
setSegmentBase(".text", value.toULongLong());
});
RipesSettings::getObserver(RIPES_SETTING_ASSEMBLER_TEXTSTART)->trigger();
connect(RipesSettings::getObserver(RIPES_SETTING_ASSEMBLER_DATASTART),
&SettingObserver::modified, this, [this](const QVariant &value) {
setSegmentBase(".data", value.toULongLong());
});
RipesSettings::getObserver(RIPES_SETTING_ASSEMBLER_DATASTART)->trigger();
connect(RipesSettings::getObserver(RIPES_SETTING_ASSEMBLER_BSSSTART),
&SettingObserver::modified, this, [this](const QVariant &value) {
setSegmentBase(".bss", value.toULongLong());
});
RipesSettings::getObserver(RIPES_SETTING_ASSEMBLER_BSSSTART)->trigger();
}
};

/// An ISA-specific assembler
template <ISA isa>
struct ISA_Assembler : public QAssembler {
ISA_Assembler(std::shared_ptr<const ISAInfo<isa>> isaInfo)
: QAssembler(isaInfo) {
initialize(gnuDirectives());
}

ISA getISA() const override { return isa; }

protected:
QChar commentDelimiter() const override { return '#'; }
};

std::shared_ptr<AssemblerBase>
constructAssemblerDynamic(const std::shared_ptr<const ISAInfoBase> &isa);

} // namespace Assembler

} // namespace Ripes
4 changes: 4 additions & 0 deletions src/assembler/assemblerbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "directive.h"
#include "expreval.h"
#include "isa/instruction.h"
#include "isa/isainfo.h"
#include "isa/pseudoinstruction.h"
#include "isa/symbolmap.h"

Expand All @@ -34,6 +35,9 @@ class AssemblerBase {
/// Sets the base pointer of seg to the provided 'base' value.
void setSegmentBase(Section seg, AInt base);

/// Returns the ISA that this assembler is used for.
virtual ISA getISA() const = 0;

/// Assembles an input program (represented as a list of strings). Optionally,
/// a set of predefined symbols may be provided to the assemble call. If
/// programLines does not represent the source program directly (possibly due
Expand Down
38 changes: 0 additions & 38 deletions src/assembler/rv32i_assembler.cpp

This file was deleted.

22 changes: 0 additions & 22 deletions src/assembler/rv32i_assembler.h

This file was deleted.

36 changes: 0 additions & 36 deletions src/assembler/rv64i_assembler.cpp

This file was deleted.

22 changes: 0 additions & 22 deletions src/assembler/rv64i_assembler.h

This file was deleted.

14 changes: 3 additions & 11 deletions src/processorhandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
#include "ripessettings.h"
#include "statusmanager.h"

#include "assembler/assembler.h"
#include "assembler/program.h"
#include "assembler/rv32i_assembler.h"
#include "assembler/rv64i_assembler.h"
#include "io/iomanager.h"

#include "syscall/riscv_syscall.h"
Expand Down Expand Up @@ -268,15 +267,8 @@ void ProcessorHandler::_clearBreakpoints() { m_breakpoints.clear(); }

void ProcessorHandler::createAssemblerForCurrentISA() {
const auto &isa = m_currentProcessor->fullISA();

if (auto rv32isa =
std::dynamic_pointer_cast<const ISAInfo<ISA::RV32I>>(isa)) {
m_currentAssembler = std::make_shared<Assembler::RV32I_Assembler>(rv32isa);
} else if (auto rv64isa =
std::dynamic_pointer_cast<const ISAInfo<ISA::RV64I>>(isa)) {
m_currentAssembler = std::make_shared<Assembler::RV64I_Assembler>(rv64isa);
} else {
Q_UNREACHABLE();
if (!m_currentAssembler || m_currentAssembler->getISA() != isa->isaID()) {
m_currentAssembler = Assembler::constructAssemblerDynamic(isa);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/processorregistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <map>
#include <memory>

#include "isa/rv32isainfo.h"
#include "isa/rv64isainfo.h"
#include "processors/interface/ripesprocessor.h"

namespace Ripes {
Expand Down
4 changes: 0 additions & 4 deletions src/processors/RISC-V/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@
#include <functional>

#include "VSRTL/core/vsrtl_enum.h"
#include "VSRTL/interface/vsrtl_binutils.h"
#include "VSRTL/interface/vsrtl_interface.h"

#include "rv_instrparser.h"

#include "../../isa/rv32isainfo.h"
#include "../../isa/rv64isainfo.h"
#include "../../isa/rvisainfo_common.h"

namespace Ripes {
Expand Down
8 changes: 4 additions & 4 deletions test/tst_assembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "isa/isainfo.h"
#include "isa/rv32isainfo.h"

#include "assembler/rv32i_assembler.h"
#include "assembler/assembler.h"

#include "processorhandler.h"

Expand Down Expand Up @@ -67,7 +67,7 @@ private slots:
QByteArray expectData = {}) {
QString err;
auto isa = std::make_shared<ISAInfo<ISA::RV32I>>(QStringList());
auto assembler = RV32I_Assembler(isa);
auto assembler = ISA_Assembler<ISA::RV32I>(isa);
auto res = assembler.assemble(program);
if ((res.errors.size() != 0) ^ (expect == Expect::Fail)) {
res.errors.print();
Expand Down Expand Up @@ -255,7 +255,7 @@ void tst_Assembler::tst_invalidLabel() {

void tst_Assembler::tst_benchmarkNew() {
auto isa = std::make_shared<ISAInfo<ISA::RV32I>>(QStringList());
auto assembler = RV32I_Assembler(isa);
auto assembler = ISA_Assembler<ISA::RV32I>(isa);
auto program = createProgram(1000);
QBENCHMARK { assembler.assembleRaw(program); }
}
Expand Down Expand Up @@ -378,7 +378,7 @@ void tst_Assembler::tst_relativeLabels() {

void tst_Assembler::tst_matcher() {
auto isa = std::make_shared<ISAInfo<ISA::RV32I>>(QStringList());
auto assembler = RV32I_Assembler(isa);
auto assembler = ISA_Assembler<ISA::RV32I>(isa);
assembler.getMatcher().print();

std::vector<std::pair<QString, unsigned>> toMatch = {
Expand Down

0 comments on commit 098474c

Please sign in to comment.