riscv: Emit standard B/U/J type ops.

This commit is contained in:
Unknown W. Brackets 2022-08-24 18:01:03 -07:00
parent 9fcad83940
commit 1dab9d1875
2 changed files with 153 additions and 0 deletions

View File

@ -28,13 +28,26 @@ static inline bool SupportsCompressed() {
enum class Opcode32 {
// Note: invalid, just used for FixupBranch.
ZERO = 0b0000000,
AUIPC = 0b0010111,
BRANCH = 0b1100011,
LUI = 0b0110111,
JALR = 0b1100111,
JAL = 0b1101111,
SYSTEM = 0b1110011,
};
enum class Funct3 {
// Note: invalid, just used for FixupBranch.
ZERO = 0b000,
PRIV = 0b000,
BEQ = 0b000,
BNE = 0b001,
BLT = 0b100,
BGE = 0b101,
BLTU = 0b110,
BGEU = 0b111,
};
enum class Funct2 {
@ -213,4 +226,110 @@ void RiscVEmitter::EBREAK() {
Write32(EncodeI(Opcode32::SYSTEM, R_ZERO, Funct3::PRIV, R_ZERO, Funct12::EBREAK));
}
void RiscVEmitter::LUI(RiscVReg rd, s32 simm32) {
_assert_(rd != R_ZERO);
Write32(EncodeU(Opcode32::LUI, rd, simm32));
}
void RiscVEmitter::AUIPC(RiscVReg rd, s32 simm32) {
_assert_(rd != R_ZERO);
Write32(EncodeU(Opcode32::AUIPC, rd, simm32));
}
void RiscVEmitter::JAL(RiscVReg rd, const void *dst) {
_assert_msg_(JInRange(GetCodePointer(), dst), "JAL destination is too far away (%p -> %p)", GetCodePointer(), dst);
_assert_msg_(((intptr_t)dst & 1) == 0, "JAL destination should be aligned");
_assert_msg_(((intptr_t)dst & 3) == 0 || SupportsCompressed(), "JAL destination should be aligned (no compressed)");
ptrdiff_t distance = (intptr_t)dst - (intptr_t)GetCodePointer();
Write32(EncodeJ(Opcode32::JAL, rd, (s32)distance));
}
void RiscVEmitter::JALR(RiscVReg rd, RiscVReg rs1, s32 simm12) {
Write32(EncodeI(Opcode32::JALR, rd, Funct3::ZERO, rs1, simm12));
}
FixupBranch RiscVEmitter::JAL(RiscVReg rd) {
FixupBranch fixup{ GetCodePointer(), FixupBranchType::J };
Write32(EncodeJ(Opcode32::JAL, rd, 0));
return fixup;
}
void RiscVEmitter::BEQ(RiscVReg rs1, RiscVReg rs2, const void *dst) {
_assert_msg_(BInRange(GetCodePointer(), dst), "%s destination is too far away (%p -> %p)", __func__, GetCodePointer(), dst);
_assert_msg_(((intptr_t)dst & 3) == 0 || SupportsCompressed(), "%s destination should be aligned (no compressed)", __func__);
ptrdiff_t distance = (intptr_t)dst - (intptr_t)GetCodePointer();
Write32(EncodeB(Opcode32::BRANCH, Funct3::BEQ, rs1, rs2, (s32)distance));
}
void RiscVEmitter::BNE(RiscVReg rs1, RiscVReg rs2, const void *dst) {
_assert_msg_(BInRange(GetCodePointer(), dst), "%s destination is too far away (%p -> %p)", __func__, GetCodePointer(), dst);
_assert_msg_(((intptr_t)dst & 3) == 0 || SupportsCompressed(), "%s destination should be aligned (no compressed)", __func__);
ptrdiff_t distance = (intptr_t)dst - (intptr_t)GetCodePointer();
Write32(EncodeB(Opcode32::BRANCH, Funct3::BNE, rs1, rs2, (s32)distance));
}
void RiscVEmitter::BLT(RiscVReg rs1, RiscVReg rs2, const void *dst) {
_assert_msg_(BInRange(GetCodePointer(), dst), "%s destination is too far away (%p -> %p)", __func__, GetCodePointer(), dst);
_assert_msg_(((intptr_t)dst & 3) == 0 || SupportsCompressed(), "%s destination should be aligned (no compressed)", __func__);
ptrdiff_t distance = (intptr_t)dst - (intptr_t)GetCodePointer();
Write32(EncodeB(Opcode32::BRANCH, Funct3::BLT, rs1, rs2, (s32)distance));
}
void RiscVEmitter::BGE(RiscVReg rs1, RiscVReg rs2, const void *dst) {
_assert_msg_(BInRange(GetCodePointer(), dst), "%s destination is too far away (%p -> %p)", __func__, GetCodePointer(), dst);
_assert_msg_(((intptr_t)dst & 3) == 0 || SupportsCompressed(), "%s destination should be aligned (no compressed)", __func__);
ptrdiff_t distance = (intptr_t)dst - (intptr_t)GetCodePointer();
Write32(EncodeB(Opcode32::BRANCH, Funct3::BGE, rs1, rs2, (s32)distance));
}
void RiscVEmitter::BLTU(RiscVReg rs1, RiscVReg rs2, const void *dst) {
_assert_msg_(BInRange(GetCodePointer(), dst), "%s destination is too far away (%p -> %p)", __func__, GetCodePointer(), dst);
_assert_msg_(((intptr_t)dst & 3) == 0 || SupportsCompressed(), "%s destination should be aligned (no compressed)", __func__);
ptrdiff_t distance = (intptr_t)dst - (intptr_t)GetCodePointer();
Write32(EncodeB(Opcode32::BRANCH, Funct3::BLTU, rs1, rs2, (s32)distance));
}
void RiscVEmitter::BGEU(RiscVReg rs1, RiscVReg rs2, const void *dst) {
_assert_msg_(BInRange(GetCodePointer(), dst), "%s destination is too far away (%p -> %p)", __func__, GetCodePointer(), dst);
_assert_msg_(((intptr_t)dst & 3) == 0 || SupportsCompressed(), "%s destination should be aligned (no compressed)", __func__);
ptrdiff_t distance = (intptr_t)dst - (intptr_t)GetCodePointer();
Write32(EncodeB(Opcode32::BRANCH, Funct3::BGEU, rs1, rs2, (s32)distance));
}
FixupBranch RiscVEmitter::BEQ(RiscVReg rs1, RiscVReg rs2) {
FixupBranch fixup{ GetCodePointer(), FixupBranchType::B };
Write32(EncodeB(Opcode32::BRANCH, Funct3::BEQ, rs1, rs2, 0));
return fixup;
}
FixupBranch RiscVEmitter::BNE(RiscVReg rs1, RiscVReg rs2) {
FixupBranch fixup{ GetCodePointer(), FixupBranchType::B };
Write32(EncodeB(Opcode32::BRANCH, Funct3::BNE, rs1, rs2, 0));
return fixup;
}
FixupBranch RiscVEmitter::BLT(RiscVReg rs1, RiscVReg rs2) {
FixupBranch fixup{ GetCodePointer(), FixupBranchType::B };
Write32(EncodeB(Opcode32::BRANCH, Funct3::BLT, rs1, rs2, 0));
return fixup;
}
FixupBranch RiscVEmitter::BGE(RiscVReg rs1, RiscVReg rs2) {
FixupBranch fixup{ GetCodePointer(), FixupBranchType::B };
Write32(EncodeB(Opcode32::BRANCH, Funct3::BGE, rs1, rs2, 0));
return fixup;
}
FixupBranch RiscVEmitter::BLTU(RiscVReg rs1, RiscVReg rs2) {
FixupBranch fixup{ GetCodePointer(), FixupBranchType::B };
Write32(EncodeB(Opcode32::BRANCH, Funct3::BLTU, rs1, rs2, 0));
return fixup;
}
FixupBranch RiscVEmitter::BGEU(RiscVReg rs1, RiscVReg rs2) {
FixupBranch fixup{ GetCodePointer(), FixupBranchType::B };
Write32(EncodeB(Opcode32::BRANCH, Funct3::BGEU, rs1, rs2, 0));
return fixup;
}
};

View File

@ -78,6 +78,40 @@ public:
void EBREAK();
void LUI(RiscVReg rd, s32 simm32);
void AUIPC(RiscVReg rd, s32 simm32);
void JAL(RiscVReg rd, const void *dst);
void JALR(RiscVReg rd, RiscVReg rs1, s32 simm12);
FixupBranch JAL(RiscVReg rd);
// Psuedo-instructions for convenience/clarity.
void J(const void *dst) {
JAL(R_ZERO, dst);
}
void JR(RiscVReg rs1, u32 simm12 = 0) {
JALR(R_ZERO, rs1, simm12);
}
void RET() {
JR(R_RA);
}
FixupBranch J() {
return JAL(R_ZERO);
}
void BEQ(RiscVReg rs1, RiscVReg rs2, const void *dst);
void BNE(RiscVReg rs1, RiscVReg rs2, const void *dst);
void BLT(RiscVReg rs1, RiscVReg rs2, const void *dst);
void BGE(RiscVReg rs1, RiscVReg rs2, const void *dst);
void BLTU(RiscVReg rs1, RiscVReg rs2, const void *dst);
void BGEU(RiscVReg rs1, RiscVReg rs2, const void *dst);
FixupBranch BEQ(RiscVReg rs1, RiscVReg rs2);
FixupBranch BNE(RiscVReg rs1, RiscVReg rs2);
FixupBranch BLT(RiscVReg rs1, RiscVReg rs2);
FixupBranch BGE(RiscVReg rs1, RiscVReg rs2);
FixupBranch BLTU(RiscVReg rs1, RiscVReg rs2);
FixupBranch BGEU(RiscVReg rs1, RiscVReg rs2);
private:
void SetJumpTarget(const FixupBranch &branch, const void *dst);
bool BInRange(const void *src, const void *dst) const;