Skip to content

Commit

Permalink
Add MIPS ISA (#290)
Browse files Browse the repository at this point in the history
Add MIPS32 to isainfo.h
  • Loading branch information
SteliosKaragiorgis authored Sep 28, 2023
1 parent 5f8ad5d commit c56dfb2
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 3 deletions.
6 changes: 6 additions & 0 deletions src/isa/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
create_ripes_lib(isa LINK_TO_RIPES_LIB)

target_sources(isa_lib
PRIVATE
mipsisainfo_common.h mipsisainfo_common.cpp
mips32isainfo.h
)
6 changes: 3 additions & 3 deletions src/isa/isainfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
namespace Ripes {

/// List of currently supported ISAs.
enum class ISA { RV32I, RV64I };
const static std::map<ISA, QString> ISAFamilyNames = {{ISA::RV32I, "RISC-V"},
{ISA::RV64I, "RISC-V"}};
enum class ISA { RV32I, RV64I, MIPS32I };
const static std::map<ISA, QString> ISAFamilyNames = {
{ISA::RV32I, "RISC-V"}, {ISA::RV64I, "RISC-V"}, {ISA::MIPS32I, "MIPS"}};
enum class RegisterFileType { GPR, FPR, CSR };
struct RegisterFileName {
QString shortName;
Expand Down
33 changes: 33 additions & 0 deletions src/isa/mips32isainfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include "isainfo.h"
#include "mipsisainfo_common.h"

namespace Ripes {

template <>
class ISAInfo<ISA::MIPS32I> : public MIPSISAInfoBase {
public:
ISAInfo<ISA::MIPS32I>(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
61 changes: 61 additions & 0 deletions src/isa/mipsisainfo_common.cpp
Original file line number Diff line number Diff line change
@@ -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<MIPSElfFlags, QString> ELFFlagStrings{
{NOREORDER, "NOREORDER"}, {PIC, "PIC"}, {CPIC, "CPIC"}, {ARCH, "ARCH"}};
}

} // namespace Ripes
211 changes: 211 additions & 0 deletions src/isa/mipsisainfo_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
#pragma once

#include "isainfo.h"
#include <QDebug>

namespace Ripes {

template <unsigned XLEN>
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<MIPSElfFlags, QString> 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<int>(i)
? MIPSISA::RegNames.at(static_cast<int>(i))
: QString());
}
QString regAlias(unsigned i) const override {
return MIPSISA::RegAliases.size() > static_cast<int>(i)
? MIPSISA::RegAliases.at(static_cast<int>(i))
: QString();
}
QString regInfo(unsigned i) const override {
return MIPSISA::RegDescs.size() > static_cast<int>(i)
? MIPSISA::RegDescs.at(static_cast<int>(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 &reg, 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

0 comments on commit c56dfb2

Please sign in to comment.