165 lines
3.7 KiB
C++
165 lines
3.7 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <unordered_map>
|
|
#include "elna/source/parser.hpp"
|
|
#include "elna/result.hpp"
|
|
|
|
namespace elna
|
|
{
|
|
enum class XRegister : std::uint8_t
|
|
{
|
|
zero = 0,
|
|
ra = 1,
|
|
sp = 2,
|
|
gp = 3,
|
|
tp = 4,
|
|
t0 = 5,
|
|
t1 = 6,
|
|
t2 = 7,
|
|
s0 = 8,
|
|
s1 = 9,
|
|
a0 = 10,
|
|
a1 = 11,
|
|
a2 = 12,
|
|
a3 = 13,
|
|
a4 = 14,
|
|
a5 = 15,
|
|
a6 = 16,
|
|
a7 = 17,
|
|
s2 = 18,
|
|
s3 = 19,
|
|
s4 = 20,
|
|
s5 = 21,
|
|
s6 = 22,
|
|
s7 = 23,
|
|
s8 = 24,
|
|
s9 = 25,
|
|
s10 = 26,
|
|
s11 = 27,
|
|
t3 = 28,
|
|
t4 = 29,
|
|
t5 = 30,
|
|
t6 = 31,
|
|
};
|
|
|
|
enum class Funct3 : std::uint8_t
|
|
{
|
|
addi = 0b000,
|
|
slti = 0b001,
|
|
sltiu = 0b011,
|
|
andi = 0b111,
|
|
ori = 0b110,
|
|
xori = 0b100,
|
|
slli = 0b000,
|
|
srli = 0b101,
|
|
srai = 0b101,
|
|
add = 0b000,
|
|
slt = 0b010,
|
|
sltu = 0b011,
|
|
_and = 0b111,
|
|
_or = 0b110,
|
|
_xor = 0b100,
|
|
sll = 0b001,
|
|
srl = 0b101,
|
|
sub = 0b000,
|
|
sra = 0b101,
|
|
beq = 0b000,
|
|
bne = 0b001,
|
|
blt = 0b100,
|
|
bltu = 0b110,
|
|
bge = 0b101,
|
|
bgeu = 0b111,
|
|
fence = 0b000,
|
|
fenceI = 0b001,
|
|
csrrw = 0b001,
|
|
csrrs = 0b010,
|
|
csrrc = 0b011,
|
|
csrrwi = 0b101,
|
|
csrrsi = 0b110,
|
|
csrrci = 0b111,
|
|
priv = 0b000,
|
|
sb = 0b000,
|
|
sh = 0b001,
|
|
sw = 0b010,
|
|
lb = 0b000,
|
|
lh = 0b001,
|
|
lw = 0b010,
|
|
lbu = 0b100,
|
|
lhu = 0b101,
|
|
jalr = 0b000,
|
|
mul = 000,
|
|
mulh = 001,
|
|
mulhsu = 010,
|
|
mulhu = 011,
|
|
div = 100,
|
|
divu = 101,
|
|
rem = 110,
|
|
remu = 111
|
|
};
|
|
|
|
enum class Funct12 : std::uint8_t
|
|
{
|
|
ecall = 0b000000000000,
|
|
ebreak = 0b000000000001,
|
|
};
|
|
|
|
enum class Funct7 : std::uint8_t
|
|
{
|
|
none = 0,
|
|
sub = 0b0100000,
|
|
muldiv = 0b0000001
|
|
};
|
|
|
|
enum class BaseOpcode : std::uint8_t
|
|
{
|
|
opImm = 0b0010011,
|
|
lui = 0b0110111,
|
|
auipc = 0b0010111,
|
|
op = 0b0110011,
|
|
jal = 0b1101111,
|
|
jalr = 0b1100111,
|
|
branch = 0b1100011,
|
|
load = 0b0000011,
|
|
store = 0b0100011,
|
|
miscMem = 0b0001111,
|
|
system = 0b1110011,
|
|
};
|
|
|
|
struct Instruction
|
|
{
|
|
Instruction(BaseOpcode opcode);
|
|
|
|
Instruction& i(XRegister rd, Funct3 funct3, XRegister rs1, std::uint32_t immediate);
|
|
Instruction& s(std::uint32_t imm1, Funct3 funct3, XRegister rs1, XRegister rs2);
|
|
Instruction& r(XRegister rd, Funct3 funct3, XRegister rs1, XRegister rs2, Funct7 funct7 = Funct7::none);
|
|
Instruction& u(XRegister rd, std::uint32_t imm);
|
|
|
|
const std::byte *cbegin();
|
|
const std::byte *cend();
|
|
|
|
private:
|
|
std::uint32_t instruction{ 0 };
|
|
};
|
|
|
|
class RiscVVisitor : public source::ParserVisitor
|
|
{
|
|
public:
|
|
Instruction *instructions;
|
|
std::size_t instructionsLength;
|
|
bool registerInUse{ true };
|
|
std::uint32_t variableCounter = 1;
|
|
Reference references[3];
|
|
std::unordered_map<std::string, std::int32_t> constants;
|
|
|
|
virtual void visit(source::definition *definition) override;
|
|
virtual void visit(source::bang_statement *statement) override;
|
|
virtual void visit(source::block *block) override;
|
|
virtual void visit(source::variable *variable) override;
|
|
virtual void visit(source::integer_literal *number) override;
|
|
virtual void visit(source::binary_expression *expression) override;
|
|
};
|
|
|
|
Symbol writeNext(source::block *ast);
|
|
}
|