elna/include/elna/backend/riscv.hpp
2024-12-20 16:13:38 +01:00

164 lines
3.6 KiB
C++

#pragma once
#include <cstdint>
#include "elna/source/optimizer.hpp"
namespace elna::riscv
{
enum class address_t
{
text,
high20,
lower12i
};
struct reference
{
std::string name;
std::size_t offset;
address_t target;
};
enum class x_register : 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_t : 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 = 0b000,
mulh = 0b001,
mulhsu = 0b010,
mulhu = 0b011,
div = 0b100,
divu = 0b101,
rem = 0b110,
remu = 0b111
};
enum class funct12_t : std::uint8_t
{
ecall = 0b000000000000,
ebreak = 0b000000000001,
};
enum class funct7_t : std::uint8_t
{
none = 0,
sub = 0b0100000,
muldiv = 0b0000001
};
enum class base_opcode : 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() = default; // NOP = addi x0, x0, 0.
instruction(base_opcode opcode);
instruction& i(x_register rd, funct3_t funct3, x_register rs1, std::uint32_t immediate);
instruction& s(std::uint32_t imm, funct3_t funct3, x_register rs1, x_register rs2);
instruction& b(std::uint32_t imm, funct3_t funct3, x_register rs1, x_register rs2);
instruction& r(x_register rd, funct3_t funct3, x_register rs1, x_register rs2,
funct7_t funct7 = funct7_t::none);
instruction& u(x_register rd, std::uint32_t imm);
instruction& j(x_register rd, std::uint32_t imm);
const std::byte *cbegin() const;
const std::byte *cend() const;
private:
std::uint32_t representation{ 0 };
};
std::vector<reference> generate(source::intermediate_code_generator generator,
std::shared_ptr<source::symbol_table> table, std::shared_ptr<source::writer<std::byte>> writer);
}