riscv: Emit 32-bit load/store and imm ops.

This commit is contained in:
Unknown W. Brackets 2022-08-24 19:19:32 -07:00
parent 1dab9d1875
commit 1c35cfb325
2 changed files with 140 additions and 2 deletions

View File

@ -25,10 +25,18 @@ static inline bool SupportsCompressed() {
return true;
}
static inline uint8_t BitsSupported() {
// TODO
return 64;
}
enum class Opcode32 {
// Note: invalid, just used for FixupBranch.
ZERO = 0b0000000,
LOAD = 0b0000011,
OP_IMM = 0b0010011,
AUIPC = 0b0010111,
STORE = 0b0100011,
BRANCH = 0b1100011,
LUI = 0b0110111,
JALR = 0b1100111,
@ -48,6 +56,21 @@ enum class Funct3 {
BGE = 0b101,
BLTU = 0b110,
BGEU = 0b111,
LS_B = 0b000,
LS_H = 0b001,
LS_W = 0b010,
LS_BU = 0b100,
LS_HU = 0b101,
ADDI = 0b000,
SLLI = 0b001,
SLTI = 0b010,
SLTIU = 0b011,
XORI = 0b100,
SRLI = 0b101,
ORI = 0b110,
ANDI = 0b111,
};
enum class Funct2 {
@ -227,12 +250,12 @@ void RiscVEmitter::EBREAK() {
}
void RiscVEmitter::LUI(RiscVReg rd, s32 simm32) {
_assert_(rd != R_ZERO);
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
Write32(EncodeU(Opcode32::LUI, rd, simm32));
}
void RiscVEmitter::AUIPC(RiscVReg rd, s32 simm32) {
_assert_(rd != R_ZERO);
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
Write32(EncodeU(Opcode32::AUIPC, rd, simm32));
}
@ -332,4 +355,88 @@ FixupBranch RiscVEmitter::BGEU(RiscVReg rs1, RiscVReg rs2) {
return fixup;
}
void RiscVEmitter::LB(RiscVReg rd, RiscVReg rs1, s32 simm12) {
Write32(EncodeI(Opcode32::LOAD, rd, Funct3::LS_B, rs1, simm12));
}
void RiscVEmitter::LH(RiscVReg rd, RiscVReg rs1, s32 simm12) {
Write32(EncodeI(Opcode32::LOAD, rd, Funct3::LS_H, rs1, simm12));
}
void RiscVEmitter::LW(RiscVReg rd, RiscVReg rs1, s32 simm12) {
Write32(EncodeI(Opcode32::LOAD, rd, Funct3::LS_W, rs1, simm12));
}
void RiscVEmitter::LBU(RiscVReg rd, RiscVReg rs1, s32 simm12) {
Write32(EncodeI(Opcode32::LOAD, rd, Funct3::LS_BU, rs1, simm12));
}
void RiscVEmitter::LHU(RiscVReg rd, RiscVReg rs1, s32 simm12) {
Write32(EncodeI(Opcode32::LOAD, rd, Funct3::LS_HU, rs1, simm12));
}
void RiscVEmitter::SB(RiscVReg rs2, RiscVReg rs1, s32 simm12) {
Write32(EncodeS(Opcode32::STORE, Funct3::LS_B, rs1, rs2, simm12));
}
void RiscVEmitter::SH(RiscVReg rs2, RiscVReg rs1, s32 simm12) {
Write32(EncodeS(Opcode32::STORE, Funct3::LS_H, rs1, rs2, simm12));
}
void RiscVEmitter::SW(RiscVReg rs2, RiscVReg rs1, s32 simm12) {
Write32(EncodeS(Opcode32::STORE, Funct3::LS_W, rs1, rs2, simm12));
}
void RiscVEmitter::ADDI(RiscVReg rd, RiscVReg rs1, s32 simm12) {
// Allow NOP form of ADDI.
_assert_msg_(rd != R_ZERO || (rs1 == R_ZERO && simm12 == 0), "%s write to zero is a HINT", __func__);
Write32(EncodeI(Opcode32::OP_IMM, rd, Funct3::ADDI, rs1, simm12));
}
void RiscVEmitter::SLTI(RiscVReg rd, RiscVReg rs1, s32 simm12) {
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
Write32(EncodeI(Opcode32::OP_IMM, rd, Funct3::SLTI, rs1, simm12));
}
void RiscVEmitter::SLTIU(RiscVReg rd, RiscVReg rs1, s32 simm12) {
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
Write32(EncodeI(Opcode32::OP_IMM, rd, Funct3::SLTIU, rs1, simm12));
}
void RiscVEmitter::XORI(RiscVReg rd, RiscVReg rs1, s32 simm12) {
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
Write32(EncodeI(Opcode32::OP_IMM, rd, Funct3::XORI, rs1, simm12));
}
void RiscVEmitter::ORI(RiscVReg rd, RiscVReg rs1, s32 simm12) {
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
Write32(EncodeI(Opcode32::OP_IMM, rd, Funct3::ORI, rs1, simm12));
}
void RiscVEmitter::ANDI(RiscVReg rd, RiscVReg rs1, s32 simm12) {
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
Write32(EncodeI(Opcode32::OP_IMM, rd, Funct3::ANDI, rs1, simm12));
}
void RiscVEmitter::SLLI(RiscVReg rd, RiscVReg rs1, u32 shamt) {
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
// Not sure if shamt=0 is legal or not, let's play it safe.
_assert_msg_(shamt > 0 && shamt < BitsSupported(), "Shift out of range");
Write32(EncodeI(Opcode32::OP_IMM, rd, Funct3::SLLI, rs1, shamt));
}
void RiscVEmitter::SRLI(RiscVReg rd, RiscVReg rs1, u32 shamt) {
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
// Not sure if shamt=0 is legal or not, let's play it safe.
_assert_msg_(shamt > 0 && shamt < BitsSupported(), "Shift out of range");
Write32(EncodeI(Opcode32::OP_IMM, rd, Funct3::SRLI, rs1, shamt));
}
void RiscVEmitter::SRAI(RiscVReg rd, RiscVReg rs1, u32 shamt) {
_assert_msg_(rd != R_ZERO, "%s write to zero is a HINT", __func__);
// Not sure if shamt=0 is legal or not, let's play it safe.
_assert_msg_(shamt > 0 && shamt < BitsSupported(), "Shift out of range");
Write32(EncodeI(Opcode32::OP_IMM, rd, Funct3::SRLI, rs1, shamt | (1 << 10)));
}
};

View File

@ -112,6 +112,37 @@ public:
FixupBranch BLTU(RiscVReg rs1, RiscVReg rs2);
FixupBranch BGEU(RiscVReg rs1, RiscVReg rs2);
void LB(RiscVReg rd, RiscVReg rs1, s32 simm12);
void LH(RiscVReg rd, RiscVReg rs1, s32 simm12);
void LW(RiscVReg rd, RiscVReg rs1, s32 simm12);
void LBU(RiscVReg rd, RiscVReg rs1, s32 simm12);
void LHU(RiscVReg rd, RiscVReg rs1, s32 simm12);
void SB(RiscVReg rs2, RiscVReg rs1, s32 simm12);
void SH(RiscVReg rs2, RiscVReg rs1, s32 simm12);
void SW(RiscVReg rs2, RiscVReg rs1, s32 simm12);
void ADDI(RiscVReg rd, RiscVReg rs1, s32 simm12);
void SLTI(RiscVReg rd, RiscVReg rs1, s32 simm12);
void SLTIU(RiscVReg rd, RiscVReg rs1, s32 simm12);
void XORI(RiscVReg rd, RiscVReg rs1, s32 simm12);
void ORI(RiscVReg rd, RiscVReg rs1, s32 simm12);
void ANDI(RiscVReg rd, RiscVReg rs1, s32 simm12);
void NOP() {
ADDI(R_ZERO, R_ZERO, 0);
}
void MV(RiscVReg rd, RiscVReg rs1) {
ADDI(rd, rs1, 0);
}
void NOT(RiscVReg rd, RiscVReg rs1) {
XORI(rd, rs1, -1);
}
void SLLI(RiscVReg rd, RiscVReg rs1, u32 shamt);
void SRLI(RiscVReg rd, RiscVReg rs1, u32 shamt);
void SRAI(RiscVReg rd, RiscVReg rs1, u32 shamt);
private:
void SetJumpTarget(const FixupBranch &branch, const void *dst);
bool BInRange(const void *src, const void *dst) const;