Move common RISC-V ISA and assembler functions to separate files
MODIFY
src/assembler/rv32i_assembler.cpp
src/assembler/rv32i_assembler.cpp
#include "rv32i_assembler.h"
#include "gnudirectives.h"
#include "ripessettings.h"
+#include "rvassembler_common.h"
#include "rvrelocations.h"
#include <QByteArray>
@@ -50,105 +51,8 @@ std::tuple<InstrVec, PseudoInstrVec> RV32I_Assembler::initInstructions(const ISA
return {instructions, pseudoInstructions};
}
-#define BType(name, funct3) \
- std::shared_ptr<Instruction>(new Instruction( \
- Opcode(name, {OpPart(0b1100011, 0, 6), OpPart(funct3, 12, 14)}), \
- {std::make_shared<Reg>(isa, 1, 15, 19, "rs1"), std::make_shared<Reg>(isa, 2, 20, 24, "rs2"), \
- std::make_shared<Imm>( \
- 3, 13, Imm::Repr::Signed, \
- std::vector{ImmPart(12, 31, 31), ImmPart(11, 7, 7), ImmPart(5, 25, 30), ImmPart(1, 8, 11)}, \
- Imm::SymbolType::Relative)}))
-
-#define IType(name, funct3) \
- std::shared_ptr<Instruction>( \
- new Instruction(Opcode(name, {OpPart(0b0010011, 0, 6), OpPart(funct3, 12, 14)}), \
- {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 2, 15, 19, "rs1"), \
- std::make_shared<Imm>(3, 12, Imm::Repr::Signed, std::vector{ImmPart(0, 20, 31)})}))
-
-#define LoadType(name, funct3) \
- std::shared_ptr<Instruction>( \
- new Instruction(Opcode(name, {OpPart(0b0000011, 0, 6), OpPart(funct3, 12, 14)}), \
- {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 3, 15, 19, "rs1"), \
- std::make_shared<Imm>(2, 12, Imm::Repr::Signed, std::vector{ImmPart(0, 20, 31)})}))
-
-#define IShiftType(name, funct3, funct7) \
- std::shared_ptr<Instruction>( \
- new Instruction(Opcode(name, {OpPart(0b0010011, 0, 6), OpPart(funct3, 12, 14), OpPart(funct7, 25, 31)}), \
- {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 2, 15, 19, "rs1"), \
- std::make_shared<Imm>(3, 5, Imm::Repr::Unsigned, std::vector{ImmPart(0, 20, 24)})}))
-
-#define RType(name, funct3, funct7) \
- std::shared_ptr<Instruction>( \
- new Instruction(Opcode(name, {OpPart(0b0110011, 0, 6), OpPart(funct3, 12, 14), OpPart(funct7, 25, 31)}), \
- {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 2, 15, 19, "rs1"), \
- std::make_shared<Reg>(isa, 3, 20, 24, "rs2")}))
-
-#define SType(name, funct3) \
- std::shared_ptr<Instruction>(new Instruction( \
- Opcode(name, {OpPart(0b0100011, 0, 6), OpPart(funct3, 12, 14)}), \
- {std::make_shared<Reg>(isa, 3, 15, 19, "rs1"), \
- std::make_shared<Imm>(2, 12, Imm::Repr::Signed, std::vector{ImmPart(5, 25, 31), ImmPart(0, 7, 11)}), \
- std::make_shared<Reg>(isa, 1, 20, 24, "rs2")}))
-
-#define UType(name, opcode) \
- std::shared_ptr<Instruction>( \
- new Instruction(Opcode(name, {OpPart(opcode, 0, 6)}), \
- {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), \
- std::make_shared<Imm>(2, 32, Imm::Repr::Hex, std::vector{ImmPart(0, 12, 31)})}))
-
-#define JType(name, opcode) \
- std::shared_ptr<Instruction>(new Instruction( \
- Opcode(name, {OpPart(opcode, 0, 6)}), \
- {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), \
- std::make_shared<Imm>( \
- 2, 21, Imm::Repr::Signed, \
- std::vector{ImmPart(20, 31, 31), ImmPart(12, 12, 19), ImmPart(11, 20, 20), ImmPart(1, 21, 30)}, \
- Imm::SymbolType::Relative)}))
-
-#define JALRType(name) \
- std::shared_ptr<Instruction>( \
- new Instruction(Opcode(name, {OpPart(0b1100111, 0, 6), OpPart(0b000, 12, 14)}), \
- {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 2, 15, 19, "rs1"), \
- std::make_shared<Imm>(3, 12, Imm::Repr::Signed, std::vector{ImmPart(0, 20, 31)})}))
-
-#define RegTok PseudoInstruction::reg()
-#define ImmTok PseudoInstruction::imm()
-#define CreatePseudoInstruction
-#define _PseudoExpandFuncSyms(line, symbols) \
- [](const PseudoInstruction&, const TokenizedSrcLine& line, const SymbolMap& symbols)
-
-#define _PseudoExpandFunc(line) [](const PseudoInstruction&, const TokenizedSrcLine& line, const SymbolMap&)
-
-#define PseudoLoad(name) \
- std::shared_ptr<PseudoInstruction>(new PseudoInstruction( \
- name, {RegTok, ImmTok}, _PseudoExpandFunc(line) { \
- LineTokensVec v; \
- v.push_back(LineTokens() << Token("auipc") << line.tokens.at(1) << Token(line.tokens.at(2), "%pcrel_hi")); \
- v.push_back(LineTokens() << name << line.tokens.at(1) \
- << Token(QString("(%1 + 4)").arg(line.tokens.at(2)), "%pcrel_lo") \
- << line.tokens.at(1)); \
- return v; \
- }))
-
-// The sw is a pseudo-op if a symbol is given as the immediate token. Thus, if we detect that
-// a number has been provided, then abort the pseudo-op handling.
-#define PseudoStore(name) \
- std::shared_ptr<PseudoInstruction>(new PseudoInstruction( \
- name, {RegTok, ImmTok, RegTok}, _PseudoExpandFunc(line) { \
- bool canConvert; \
- getImmediate(line.tokens.at(2), canConvert); \
- if (canConvert) { \
- return PseudoExpandRes(Error(0, "Unused; will fallback to non-pseudo op sw")); \
- } \
- LineTokensVec v; \
- v.push_back(LineTokens() << Token("auipc") << line.tokens.at(3) << Token(line.tokens.at(2), "%pcrel_hi")); \
- v.push_back(LineTokens() << name << line.tokens.at(1) \
- << Token(QString("(%1 + 4)").arg(line.tokens.at(2)), "%pcrel_lo") \
- << line.tokens.at(3)); \
- return PseudoExpandRes(v); \
- }))
-
-void RV32I_Assembler::enableExtI(const ISAInfoBase* isa, InstrVec& instructions, PseudoInstrVec& pseudoInstructions) {
+void RV32I_Assembler::enableExtI(const ISAInfoBase* isa, InstrVec& instructions, PseudoInstrVec& pseudoInstructions,
+ const std::set<Options>& options) {
// Pseudo-op functors
pseudoInstructions.push_back(PseudoLoad(Token("lb")));
pseudoInstructions.push_back(PseudoLoad(Token("lh")));
@@ -361,9 +265,15 @@ void RV32I_Assembler::enableExtI(const ISAInfoBase* isa, InstrVec& instructions,
instructions.push_back(IType(Token("ori"), 0b110));
instructions.push_back(IType(Token("andi"), 0b111));
- instructions.push_back(IShiftType(Token("slli"), 0b001, 0b0000000));
- instructions.push_back(IShiftType(Token("srli"), 0b101, 0b0000000));
- instructions.push_back(IShiftType(Token("srai"), 0b101, 0b0100000));
+ if (options.count(Options::shifts64BitVariant)) {
+ instructions.push_back(IShiftType32(Token("slliw"), RVISA::OPIMM32, 0b001, 0b0000000));
+ instructions.push_back(IShiftType32(Token("srliw"), RVISA::OPIMM32, 0b101, 0b0000000));
+ instructions.push_back(IShiftType32(Token("sraiw"), RVISA::OPIMM32, 0b101, 0b0100000));
+ } else {
+ instructions.push_back(IShiftType32(Token("slli"), RVISA::OPIMM, 0b001, 0b0000000));
+ instructions.push_back(IShiftType32(Token("srli"), RVISA::OPIMM, 0b101, 0b0000000));
+ instructions.push_back(IShiftType32(Token("srai"), RVISA::OPIMM, 0b101, 0b0100000));
+ }
instructions.push_back(RType(Token("add"), 0b000, 0b0000000));
instructions.push_back(RType(Token("sub"), 0b000, 0b0100000));

MODIFY
src/assembler/rv32i_assembler.h
src/assembler/rv32i_assembler.h
@@ -11,20 +11,25 @@ namespace Assembler {
class RV32I_Assembler : public QObject, public Assembler {
Q_OBJECT
public:
- RV32I_Assembler(const ISAInfo<ISA::RV32I>* isa);
+ enum class Options {
+ shifts64BitVariant // appends 'w' to 32-bit shift operations, for use in the 64-bit RISC-V ISA
+ };
-private:
- std::tuple<InstrVec, PseudoInstrVec> initInstructions(const ISAInfo<ISA::RV32I>* isa) const;
+ RV32I_Assembler(const ISAInfo<ISA::RV32I>* isa);
/**
* Extension enablers
* Calling an extension enabler will register the appropriate assemblers and pseudo-op expander functors with
* the assembler.
*/
- static void enableExtI(const ISAInfoBase* isa, InstrVec& instructions, PseudoInstrVec& pseudoInstructions);
+ static void enableExtI(const ISAInfoBase* isa, InstrVec& instructions, PseudoInstrVec& pseudoInstructions,
+ const std::set<Options>& options = {});
static void enableExtM(const ISAInfoBase* isa, InstrVec& instructions, PseudoInstrVec& pseudoInstructions);
static void enableExtF(const ISAInfoBase* isa, InstrVec& instructions, PseudoInstrVec& pseudoInstructions);
+private:
+ std::tuple<InstrVec, PseudoInstrVec> initInstructions(const ISAInfo<ISA::RV32I>* isa) const;
+
protected:
QChar commentDelimiter() const override { return '#'; }
};

ADD
src/assembler/rvassembler_common.h
+#pragma once
+
+#include "../isa/rvisainfo_common.h"
+#include "assembler.h"
+
+namespace Ripes {
+namespace Assembler {
+
+#define BType(name, funct3) \
+ std::shared_ptr<Instruction>(new Instruction( \
+ Opcode(name, {OpPart(0b1100011, 0, 6), OpPart(funct3, 12, 14)}), \
+ {std::make_shared<Reg>(isa, 1, 15, 19, "rs1"), std::make_shared<Reg>(isa, 2, 20, 24, "rs2"), \
+ std::make_shared<Imm>( \
+ 3, 13, Imm::Repr::Signed, \
+ std::vector{ImmPart(12, 31, 31), ImmPart(11, 7, 7), ImmPart(5, 25, 30), ImmPart(1, 8, 11)}, \
+ Imm::SymbolType::Relative)}))
+
+#define ITypeCommon(opcode, name, funct3) \
+ std::shared_ptr<Instruction>( \
+ new Instruction(Opcode(name, {OpPart(opcode, 0, 6), OpPart(funct3, 12, 14)}), \
+ {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 2, 15, 19, "rs1"), \
+ std::make_shared<Imm>(3, 12, Imm::Repr::Signed, std::vector{ImmPart(0, 20, 31)})}))
+
+#define IType(name, funct3) ITypeCommon(RVISA::OPIMM, name, funct3)
+#define IType32(name, funct3) ITypeCommon(RVISA::OPIMM32, name, funct3)
+
+#define LoadType(name, funct3) \
+ std::shared_ptr<Instruction>( \
+ new Instruction(Opcode(name, {OpPart(0b0000011, 0, 6), OpPart(funct3, 12, 14)}), \
+ {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 3, 15, 19, "rs1"), \
+ std::make_shared<Imm>(2, 12, Imm::Repr::Signed, std::vector{ImmPart(0, 20, 31)})}))
+
+#define IShiftTypeCommon(name, opcode, funct3, funct7, immEnd) \
+ std::shared_ptr<Instruction>( \
+ new Instruction(Opcode(name, {OpPart(opcode, 0, 6), OpPart(funct3, 12, 14), OpPart(funct7, 25, 31)}), \
+ {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 2, 15, 19, "rs1"), \
+ std::make_shared<Imm>(3, 5, Imm::Repr::Unsigned, std::vector{ImmPart(0, 20, immEnd)})}))
+
+#define IShiftType32(name, opcode, funct3, funct7) IShiftTypeCommon(name, opcode, funct3, funct7, 24)
+#define IShiftType64(name, opcode, funct3, funct7) IShiftTypeCommon(name, opcode, funct3, funct7, 25)
+
+#define RType(name, funct3, funct7) \
+ std::shared_ptr<Instruction>( \
+ new Instruction(Opcode(name, {OpPart(RVISA::OPIMM32, 0, 6), OpPart(funct3, 12, 14), OpPart(funct7, 25, 31)}), \
+ {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 2, 15, 19, "rs1"), \
+ std::make_shared<Reg>(isa, 3, 20, 24, "rs2")}))
+
+#define SType(name, funct3) \
+ std::shared_ptr<Instruction>(new Instruction( \
+ Opcode(name, {OpPart(0b0100011, 0, 6), OpPart(funct3, 12, 14)}), \
+ {std::make_shared<Reg>(isa, 3, 15, 19, "rs1"), \
+ std::make_shared<Imm>(2, 12, Imm::Repr::Signed, std::vector{ImmPart(5, 25, 31), ImmPart(0, 7, 11)}), \
+ std::make_shared<Reg>(isa, 1, 20, 24, "rs2")}))
+
+#define UType(name, opcode) \
+ std::shared_ptr<Instruction>( \
+ new Instruction(Opcode(name, {OpPart(opcode, 0, 6)}), \
+ {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), \
+ std::make_shared<Imm>(2, 32, Imm::Repr::Hex, std::vector{ImmPart(0, 12, 31)})}))
+
+#define JType(name, opcode) \
+ std::shared_ptr<Instruction>(new Instruction( \
+ Opcode(name, {OpPart(opcode, 0, 6)}), \
+ {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), \
+ std::make_shared<Imm>( \
+ 2, 21, Imm::Repr::Signed, \
+ std::vector{ImmPart(20, 31, 31), ImmPart(12, 12, 19), ImmPart(11, 20, 20), ImmPart(1, 21, 30)}, \
+ Imm::SymbolType::Relative)}))
+
+#define JALRType(name) \
+ std::shared_ptr<Instruction>( \
+ new Instruction(Opcode(name, {OpPart(0b1100111, 0, 6), OpPart(0b000, 12, 14)}), \
+ {std::make_shared<Reg>(isa, 1, 7, 11, "rd"), std::make_shared<Reg>(isa, 2, 15, 19, "rs1"), \
+ std::make_shared<Imm>(3, 12, Imm::Repr::Signed, std::vector{ImmPart(0, 20, 31)})}))
+
+#define RegTok PseudoInstruction::reg()
+#define ImmTok PseudoInstruction::imm()
+#define CreatePseudoInstruction
+#define _PseudoExpandFuncSyms(line, symbols) \
+ [](const PseudoInstruction&, const TokenizedSrcLine& line, const SymbolMap& symbols)
+
+#define _PseudoExpandFunc(line) [](const PseudoInstruction&, const TokenizedSrcLine& line, const SymbolMap&)
+
+#define PseudoLoad(name) \
+ std::shared_ptr<PseudoInstruction>(new PseudoInstruction( \
+ name, {RegTok, ImmTok}, _PseudoExpandFunc(line) { \
+ LineTokensVec v; \
+ v.push_back(LineTokens() << Token("auipc") << line.tokens.at(1) << Token(line.tokens.at(2), "%pcrel_hi")); \
+ v.push_back(LineTokens() << name << line.tokens.at(1) \
+ << Token(QString("(%1 + 4)").arg(line.tokens.at(2)), "%pcrel_lo") \
+ << line.tokens.at(1)); \
+ return v; \
+ }))
+
+// The sw is a pseudo-op if a symbol is given as the immediate token. Thus, if we detect that
+// a number has been provided, then abort the pseudo-op handling.
+#define PseudoStore(name) \
+ std::shared_ptr<PseudoInstruction>(new PseudoInstruction( \
+ name, {RegTok, ImmTok, RegTok}, _PseudoExpandFunc(line) { \
+ bool canConvert; \
+ getImmediate(line.tokens.at(2), canConvert); \
+ if (canConvert) { \
+ return PseudoExpandRes(Error(0, "Unused; will fallback to non-pseudo op sw")); \
+ } \
+ LineTokensVec v; \
+ v.push_back(LineTokens() << Token("auipc") << line.tokens.at(3) << Token(line.tokens.at(2), "%pcrel_hi")); \
+ v.push_back(LineTokens() << name << line.tokens.at(1) \
+ << Token(QString("(%1 + 4)").arg(line.tokens.at(2)), "%pcrel_lo") \
+ << line.tokens.at(3)); \
+ return PseudoExpandRes(v); \
+ }))
+
+} // namespace Assembler
+} // namespace Ripes

MODIFY
src/isa/rv32isainfo.h
src/isa/rv32isainfo.h
#pragma once
#include "isainfo.h"
+#include "rvisainfo_common.h"
namespace Ripes {
-namespace {
-// clang-format off
-const static QStringList RVRegAliases = QStringList() << "zero"
- << "ra" << "sp" << "gp" << "tp" << "t0" << "t1" << "t2" << "s0" << "s1" << "a0"
- << "a1" << "a2" << "a3" << "a4" << "a5" << "a6" << "a7" << "s2" << "s3" << "s4"
- << "s5" << "s6" << "s7" << "s8" << "s9" << "s10" << "s11" << "t3" << "t4" << "t5"
- << "t6";
-
-const static QStringList RVRegNames = QStringList() << "x0"
- << "x1" << "x2" << "x3" << "x4" << "x5" << "x6" << "x7" << "x8"
- << "x9" << "x10" << "x11" << "x12" << "x13" << "x14" << "x15"
- << "x16" << "x17" << "x18" << "x19" << "x20" << "x21" << "x22" << "x23"
- << "x24" << "x25" << "x26" << "x27" << "x28" << "x29" << "x30" << "x31";
-
-const static QStringList RVRegDescs = QStringList() << "Hard-Wired zero"
- << "Return Address \nSaver: Caller"
- << "Stack pointer\nSaver: Callee"
- << "Global pointer"
- << "Thread pointer"
- << "Temporary/alternate link register\nSaver: Caller"
- << "Temporary\nSaver: Caller"
- << "Temporary\nSaver: Caller"
- << "Saved register/frame pointer\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Function argument/return value\nSaver: Caller"
- << "Function argument/return value\nSaver: Caller"
- << "Function argument\nSaver: Caller"
- << "Function argument\nSaver: Caller"
- << "Function argument\nSaver: Caller"
- << "Function argument\nSaver: Caller"
- << "Function argument\nSaver: Caller"
- << "Function argument\nSaver: Caller"
- << "Saved register\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Saved register\nSaver: Callee"
- << "Temporary register\nSaver: Caller"
- << "Temporary register\nSaver: Caller"
- << "Temporary register\nSaver: Caller"
- << "Temporary register\nSaver: Caller";
-// RISC-V ELF info
-
-// Elf flag masks
-enum RVElfFlags {
- RVC = 0b1,
- FloatABI = 0b110,
- RVE = 0b1000,
- TSO = 0b10000
-};
-
-const static std::map<RVElfFlags, QString> RVELFFlagStrings {{RVC, "RVC"}, {FloatABI, "Float ABI"}, {RVE, "RVE"}, {TSO, "TSO"}};
-
-// clang-format on
-
-} // namespace
-
template <>
class ISAInfo<ISA::RV32I> : public ISAInfoBase {
public:
@@ -80,41 +19,18 @@ public:
}
}
- enum SysCall {
- None = 0,
- PrintInt = 1,
- PrintFloat = 2,
- PrintStr = 4,
- Exit = 10,
- PrintChar = 11,
- GetCWD = 17,
- TimeMs = 30,
- Cycles = 31,
- PrintIntHex = 34,
- PrintIntBinary = 35,
- PrintIntUnsigned = 36,
- Close = 57,
- LSeek = 62,
- Read = 63,
- Write = 64,
- FStat = 80,
- Exit2 = 93,
- brk = 214,
- Open = 1024
- };
-
QString name() const override { return "RV32I"; }
ISA isaID() const override { return ISA::RV32I; }
unsigned int regCnt() const override { return 32; }
QString regName(unsigned i) const override {
- return RVRegNames.size() > static_cast<int>(i) ? RVRegNames.at(static_cast<int>(i)) : QString();
+ return RVISA::RegNames.size() > static_cast<int>(i) ? RVISA::RegNames.at(static_cast<int>(i)) : QString();
}
QString regAlias(unsigned i) const override {
- return RVRegAliases.size() > static_cast<int>(i) ? RVRegAliases.at(static_cast<int>(i)) : QString();
+ return RVISA::RegAliases.size() > static_cast<int>(i) ? RVISA::RegAliases.at(static_cast<int>(i)) : QString();
}
QString regInfo(unsigned i) const override {
- return RVRegDescs.size() > static_cast<int>(i) ? RVRegDescs.at(static_cast<int>(i)) : QString();
+ return RVISA::RegDescs.size() > static_cast<int>(i) ? RVISA::RegDescs.at(static_cast<int>(i)) : QString();
}
bool regIsReadOnly(unsigned i) const override { return i == 0; }
unsigned int bits() const override { return 32; }
@@ -125,11 +41,11 @@ public:
unsigned int regNumber(const QString& reg, bool& success) const override {
QString regRes = reg;
success = true;
- if (reg[0] == 'x' && (RVRegNames.count(reg) != 0)) {
+ if (reg[0] == 'x' && (RVISA::RegNames.count(reg) != 0)) {
regRes.remove('x');
return regRes.toInt(&success, 10);
- } else if (RVRegAliases.contains(reg)) {
- return RVRegAliases.indexOf(reg);
+ } else if (RVISA::RegAliases.contains(reg)) {
+ return RVISA::RegAliases.indexOf(reg);
}
success = false;
return 0;
@@ -156,9 +72,9 @@ public:
if (flags == 0)
return QString();
QString err;
- for (const auto& flag : RVELFFlagStrings) {
+ for (const auto& flag : RVABI::ELFFlagStrings) {
if (flags & flag.first) {
- err += "ELF flag '" + RVELFFlagStrings.at(flag.first) + "' unsupported<br/>";
+ err += "ELF flag '" + RVABI::ELFFlagStrings.at(flag.first) + "' unsupported<br/>";
}
}
return err;

ADD
src/isa/rvisainfo_common.cpp
+#include "rvisainfo_common.h"
+
+namespace Ripes {
+namespace RVISA {
+
+// clang-format off
+const QStringList RegAliases = QStringList() << "zero"
+ << "ra" << "sp" << "gp" << "tp" << "t0" << "t1" << "t2" << "s0" << "s1" << "a0"
+ << "a1" << "a2" << "a3" << "a4" << "a5" << "a6" << "a7" << "s2" << "s3" << "s4"
+ << "s5" << "s6" << "s7" << "s8" << "s9" << "s10" << "s11" << "t3" << "t4" << "t5"
+ << "t6";
+
+const QStringList RegNames = QStringList() << "x0"
+ << "x1" << "x2" << "x3" << "x4" << "x5" << "x6" << "x7" << "x8"
+ << "x9" << "x10" << "x11" << "x12" << "x13" << "x14" << "x15"
+ << "x16" << "x17" << "x18" << "x19" << "x20" << "x21" << "x22" << "x23"
+ << "x24" << "x25" << "x26" << "x27" << "x28" << "x29" << "x30" << "x31";
+
+const QStringList RegDescs = QStringList() << "Hard-Wired zero"
+ << "Return Address \nSaver: Caller"
+ << "Stack pointer\nSaver: Callee"
+ << "Global pointer"
+ << "Thread pointer"
+ << "Temporary/alternate link register\nSaver: Caller"
+ << "Temporary\nSaver: Caller"
+ << "Temporary\nSaver: Caller"
+ << "Saved register/frame pointer\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Function argument/return value\nSaver: Caller"
+ << "Function argument/return value\nSaver: Caller"
+ << "Function argument\nSaver: Caller"
+ << "Function argument\nSaver: Caller"
+ << "Function argument\nSaver: Caller"
+ << "Function argument\nSaver: Caller"
+ << "Function argument\nSaver: Caller"
+ << "Function argument\nSaver: Caller"
+ << "Saved register\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Saved register\nSaver: Callee"
+ << "Temporary register\nSaver: Caller"
+ << "Temporary register\nSaver: Caller"
+ << "Temporary register\nSaver: Caller"
+ << "Temporary register\nSaver: Caller";
+// clang-format on
+} // namespace RVISA
+
+namespace RVABI {
+const std::map<RVElfFlags, QString> ELFFlagStrings{{RVC, "RVC"}, {FloatABI, "Float ABI"}, {RVE, "RVE"}, {TSO, "TSO"}};
+}
+
+} // namespace Ripes

ADD
src/isa/rvisainfo_common.h
+#pragma once
+
+#include "isainfo.h"
+
+namespace Ripes {
+
+namespace RVISA {
+
+extern const QStringList RegAliases;
+extern const QStringList RegNames;
+extern const QStringList RegDescs;
+enum Opcode { OPIMM = 0b0010011, OPIMM32 = 0b0110011 };
+
+} // namespace RVISA
+
+namespace RVABI {
+// RISC-V ELF info
+// Elf flag masks
+enum RVElfFlags { RVC = 0b1, FloatABI = 0b110, RVE = 0b1000, TSO = 0b10000 };
+extern const std::map<RVElfFlags, QString> ELFFlagStrings;
+
+enum SysCall {
+ None = 0,
+ PrintInt = 1,
+ PrintFloat = 2,
+ PrintStr = 4,
+ Exit = 10,
+ PrintChar = 11,
+ GetCWD = 17,
+ TimeMs = 30,
+ Cycles = 31,
+ PrintIntHex = 34,
+ PrintIntBinary = 35,
+ PrintIntUnsigned = 36,
+ Close = 57,
+ LSeek = 62,
+ Read = 63,
+ Write = 64,
+ FStat = 80,
+ Exit2 = 93,
+ brk = 214,
+ Open = 1024
+};
+
+} // namespace RVABI
+} // namespace Ripes

MODIFY
src/syscall/riscv_syscall.h
src/syscall/riscv_syscall.h
@@ -38,31 +38,31 @@ class RISCVSyscallManager : public SyscallManagerT<RISCVSyscall> {
public:
RISCVSyscallManager() {
// Print syscalls
- emplace<PrintIntSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::PrintInt);
- emplace<PrintFloatSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::PrintFloat);
- emplace<PrintStrSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::PrintStr);
- emplace<PrintCharSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::PrintChar);
- emplace<PrintHexSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::PrintIntHex);
- emplace<PrintBinarySyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::PrintIntBinary);
- emplace<PrintUnsignedSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::PrintIntUnsigned);
+ emplace<PrintIntSyscall<RISCVSyscall>>(RVABI::PrintInt);
+ emplace<PrintFloatSyscall<RISCVSyscall>>(RVABI::PrintFloat);
+ emplace<PrintStrSyscall<RISCVSyscall>>(RVABI::PrintStr);
+ emplace<PrintCharSyscall<RISCVSyscall>>(RVABI::PrintChar);
+ emplace<PrintHexSyscall<RISCVSyscall>>(RVABI::PrintIntHex);
+ emplace<PrintBinarySyscall<RISCVSyscall>>(RVABI::PrintIntBinary);
+ emplace<PrintUnsignedSyscall<RISCVSyscall>>(RVABI::PrintIntUnsigned);
// Control syscalls
- emplace<ExitSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::Exit);
- emplace<Exit2Syscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::Exit2);
- emplace<BrkSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::brk);
+ emplace<ExitSyscall<RISCVSyscall>>(RVABI::Exit);
+ emplace<Exit2Syscall<RISCVSyscall>>(RVABI::Exit2);
+ emplace<BrkSyscall<RISCVSyscall>>(RVABI::brk);
// File syscalls
- emplace<CloseSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::Close);
- emplace<LSeekSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::LSeek);
- emplace<ReadSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::Read);
- emplace<OpenSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::Open);
- emplace<WriteSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::Write);
- emplace<GetCWDSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::GetCWD);
- emplace<FStatSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::FStat);
+ emplace<CloseSyscall<RISCVSyscall>>(RVABI::Close);
+ emplace<LSeekSyscall<RISCVSyscall>>(RVABI::LSeek);
+ emplace<ReadSyscall<RISCVSyscall>>(RVABI::Read);
+ emplace<OpenSyscall<RISCVSyscall>>(RVABI::Open);
+ emplace<WriteSyscall<RISCVSyscall>>(RVABI::Write);
+ emplace<GetCWDSyscall<RISCVSyscall>>(RVABI::GetCWD);
+ emplace<FStatSyscall<RISCVSyscall>>(RVABI::FStat);
// Time syscalls
- emplace<CyclesSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::Cycles);
- emplace<TimeMsSyscall<RISCVSyscall>>(ISAInfo<ISA::RV32I>::TimeMs);
+ emplace<CyclesSyscall<RISCVSyscall>>(RVABI::Cycles);
+ emplace<TimeMsSyscall<RISCVSyscall>>(RVABI::TimeMs);
}
};

MODIFY
test/tst_cosimulate.cpp
test/tst_cosimulate.cpp
@@ -90,7 +90,7 @@ void tst_Cosimulate::handleSysCall() {
RegisterFileType::GPR, ProcessorHandler::get()->getProcessor()->implementsISA()->syscallReg());
/// @todo: Generalize this by having ISA report exit syscall codes
- if (status == ISAInfo<ISA::RV32I>::SysCall::Exit || status == ISAInfo<ISA::RV32I>::SysCall::Exit2) {
+ if (status == RVABI::SysCall::Exit || status == RVABI::SysCall::Exit2) {
m_stop = true;
}
}

Move common RISC-V ISA and assembler functions to separate files