aboutsummaryrefslogtreecommitdiffhomepage
path: root/externals/biscuit/src/assembler_floating_point.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'externals/biscuit/src/assembler_floating_point.cpp')
-rw-r--r--externals/biscuit/src/assembler_floating_point.cpp648
1 files changed, 648 insertions, 0 deletions
diff --git a/externals/biscuit/src/assembler_floating_point.cpp b/externals/biscuit/src/assembler_floating_point.cpp
new file mode 100644
index 00000000..2c6d4901
--- /dev/null
+++ b/externals/biscuit/src/assembler_floating_point.cpp
@@ -0,0 +1,648 @@
+#include <biscuit/assert.hpp>
+#include <biscuit/assembler.hpp>
+
+#include <algorithm>
+#include <array>
+#include <cstring>
+#include <iterator>
+
+#include "assembler_util.hpp"
+
+// Various floating-point-based extension instructions.
+
+namespace biscuit {
+
+// RV32F Extension Instructions
+
+void Assembler::FADD_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0000000, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FCLASS_S(GPR rd, FPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1110000, f0, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FCVT_S_W(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101000, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_S_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101000, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_W_S(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100000, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_WU_S(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100000, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FDIV_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0001100, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FEQ_S(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FLE_S(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FLT_S(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FLW(FPR rd, int32_t offset, GPR rs) noexcept {
+ BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
+ EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b010, rd, 0b0000111);
+}
+void Assembler::FMADD_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1000011);
+}
+void Assembler::FMAX_S(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FMIN_S(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMSUB_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1000111);
+}
+void Assembler::FMUL_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0001000, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FMV_W_X(FPR rd, GPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1111000, f0, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMV_X_W(GPR rd, FPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1110000, f0, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FNMADD_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1001111);
+}
+void Assembler::FNMSUB_S(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b00, rs2, rs1, rmode, rd, 0b1001011);
+}
+void Assembler::FSGNJ_S(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FSGNJN_S(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FSGNJX_S(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010000, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FSQRT_S(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0101100, f0, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FSUB_S(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0000100, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FSW(FPR rs2, int32_t offset, GPR rs1) noexcept {
+ BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
+ EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b010, 0b0100111);
+}
+
+void Assembler::FABS_S(FPR rd, FPR rs) noexcept {
+ FSGNJX_S(rd, rs, rs);
+}
+void Assembler::FMV_S(FPR rd, FPR rs) noexcept {
+ FSGNJ_S(rd, rs, rs);
+}
+void Assembler::FNEG_S(FPR rd, FPR rs) noexcept {
+ FSGNJN_S(rd, rs, rs);
+}
+
+// RV64F Extension Instructions
+
+void Assembler::FCVT_L_S(GPR rd, FPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1100000, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_LU_S(GPR rd, FPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1100000, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_S_L(FPR rd, GPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1101000, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_S_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1101000, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+
+// RV32D Extension Instructions
+
+void Assembler::FADD_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0000001, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FCLASS_D(GPR rd, FPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1110001, f0, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FCVT_D_W(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101001, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_D_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101001, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_W_D(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100001, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_WU_D(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100001, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_D_S(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100001, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_S_D(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100000, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FDIV_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0001101, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FEQ_D(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FLE_D(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FLT_D(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FLD(FPR rd, int32_t offset, GPR rs) noexcept {
+ BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
+ EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b011, rd, 0b0000111);
+}
+void Assembler::FMADD_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1000011);
+}
+void Assembler::FMAX_D(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FMIN_D(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMSUB_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1000111);
+}
+void Assembler::FMUL_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0001001, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FNMADD_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1001111);
+}
+void Assembler::FNMSUB_D(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b01, rs2, rs1, rmode, rd, 0b1001011);
+}
+void Assembler::FSGNJ_D(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FSGNJN_D(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FSGNJX_D(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010001, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FSQRT_D(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0101101, f0, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FSUB_D(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0000101, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FSD(FPR rs2, int32_t offset, GPR rs1) noexcept {
+ BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
+ EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b011, 0b0100111);
+}
+
+void Assembler::FABS_D(FPR rd, FPR rs) noexcept {
+ FSGNJX_D(rd, rs, rs);
+}
+void Assembler::FMV_D(FPR rd, FPR rs) noexcept {
+ FSGNJ_D(rd, rs, rs);
+}
+void Assembler::FNEG_D(FPR rd, FPR rs) noexcept {
+ FSGNJN_D(rd, rs, rs);
+}
+
+// RV64D Extension Instructions
+
+void Assembler::FCVT_L_D(GPR rd, FPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1100001, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_LU_D(GPR rd, FPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1100001, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_D_L(FPR rd, GPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1101001, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_D_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1101001, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FMV_D_X(FPR rd, GPR rs1) noexcept {
+ BISCUIT_ASSERT(IsRV64OrRV128(m_features));
+ EmitRType(m_buffer, 0b1111001, f0, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMV_X_D(GPR rd, FPR rs1) noexcept {
+ BISCUIT_ASSERT(IsRV64OrRV128(m_features));
+ EmitRType(m_buffer, 0b1110001, f0, rs1, 0b000, rd, 0b1010011);
+}
+
+// RV32Q Extension Instructions
+
+void Assembler::FADD_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0000011, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FCLASS_Q(GPR rd, FPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1110011, f0, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FCVT_Q_W(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101011, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_Q_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101011, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_W_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100011, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_WU_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100011, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_Q_D(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100011, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_D_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100001, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_Q_S(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100011, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_S_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100000, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FDIV_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0001111, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FEQ_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FLE_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FLT_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FLQ(FPR rd, int32_t offset, GPR rs) noexcept {
+ BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
+ EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b100, rd, 0b0000111);
+}
+void Assembler::FMADD_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1000011);
+}
+void Assembler::FMAX_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FMIN_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMSUB_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1000111);
+}
+void Assembler::FMUL_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0001011, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FNMADD_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1001111);
+}
+void Assembler::FNMSUB_Q(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b11, rs2, rs1, rmode, rd, 0b1001011);
+}
+void Assembler::FSGNJ_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FSGNJN_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FSGNJX_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010011, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FSQRT_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0101111, f0, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FSUB_Q(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0000111, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FSQ(FPR rs2, int32_t offset, GPR rs1) noexcept {
+ BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
+ EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b100, 0b0100111);
+}
+
+void Assembler::FABS_Q(FPR rd, FPR rs) noexcept {
+ FSGNJX_Q(rd, rs, rs);
+}
+void Assembler::FMV_Q(FPR rd, FPR rs) noexcept {
+ FSGNJ_Q(rd, rs, rs);
+}
+void Assembler::FNEG_Q(FPR rd, FPR rs) noexcept {
+ FSGNJN_Q(rd, rs, rs);
+}
+
+// RV64Q Extension Instructions
+
+void Assembler::FCVT_L_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1100011, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_LU_Q(GPR rd, FPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1100011, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_Q_L(FPR rd, GPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1101011, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_Q_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
+ BISCUIT_ASSERT(IsRV64(m_features));
+ EmitRType(m_buffer, 0b1101011, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+
+// RV32Zfh Extension Instructions
+
+void Assembler::FADD_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0000010, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FCLASS_H(GPR rd, FPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1110010, f0, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FCVT_D_H(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100001, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_H_D(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100010, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_H_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100010, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_H_S(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100010, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_H_W(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101010, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_H_WU(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101010, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_Q_H(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100011, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_S_H(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100000, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_W_H(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100010, f0, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_WU_H(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100010, f1, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FDIV_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0001110, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FEQ_H(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FLE_H(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FLH(FPR rd, int32_t offset, GPR rs) noexcept {
+ BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
+ EmitIType(m_buffer, static_cast<uint32_t>(offset), rs, 0b001, rd, 0b0000111);
+}
+void Assembler::FLT_H(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FMADD_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1000011);
+}
+void Assembler::FMAX_H(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FMIN_H(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMSUB_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1000111);
+}
+void Assembler::FMUL_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0001010, rs2, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FMV_H_X(FPR rd, GPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1111010, f0, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMV_X_H(GPR rd, FPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1110010, f0, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FNMADD_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1001111);
+}
+void Assembler::FNMSUB_H(FPR rd, FPR rs1, FPR rs2, FPR rs3, RMode rmode) noexcept {
+ EmitR4Type(m_buffer, rs3, 0b10, rs2, rs1, rmode, rd, 0b1001011);
+}
+void Assembler::FSGNJ_H(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010010, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FSGNJN_H(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010010, rs2, rs1, 0b001, rd, 0b1010011);
+}
+void Assembler::FSGNJX_H(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010010, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FSH(FPR rs2, int32_t offset, GPR rs1) noexcept {
+ BISCUIT_ASSERT(IsValidSigned12BitImm(offset));
+ EmitSType(m_buffer, static_cast<uint32_t>(offset), rs2, rs1, 0b001, 0b0100111);
+}
+void Assembler::FSQRT_H(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0101110, f0, rs1, rmode, rd, 0b1010011);
+}
+void Assembler::FSUB_H(FPR rd, FPR rs1, FPR rs2, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0000110, rs2, rs1, rmode, rd, 0b1010011);
+}
+
+// RV64Zfh Extension Instructions
+
+void Assembler::FCVT_L_H(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100010, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_LU_H(GPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1100010, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_H_L(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101010, f2, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FCVT_H_LU(FPR rd, GPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b1101010, f3, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+
+// Zfa Extension Instructions
+
+static void FLIImpl(CodeBuffer& buffer, uint32_t funct7, FPR rd, double value) noexcept {
+ static constexpr std::array fli_table{
+ 0xBFF0000000000000ULL, // -1.0
+ 0x0010000000000000ULL, // Minimum positive normal
+ 0x3EF0000000000000ULL, // 1.0 * 2^-16
+ 0x3F00000000000000ULL, // 1.0 * 2^-15
+ 0x3F70000000000000ULL, // 1.0 * 2^-8
+ 0x3F80000000000000ULL, // 1.0 * 2^-7
+ 0x3FB0000000000000ULL, // 1.0 * 2^-4
+ 0x3FC0000000000000ULL, // 1.0 * 2^-3
+ 0x3FD0000000000000ULL, // 0.25
+ 0x3FD4000000000000ULL, // 0.3125
+ 0x3FD8000000000000ULL, // 0.375
+ 0x3FDC000000000000ULL, // 0.4375
+ 0x3FE0000000000000ULL, // 0.5
+ 0x3FE4000000000000ULL, // 0.625
+ 0x3FE8000000000000ULL, // 0.75
+ 0x3FEC000000000000ULL, // 0.875
+ 0x3FF0000000000000ULL, // 1.0
+ 0x3FF4000000000000ULL, // 1.25
+ 0x3FF8000000000000ULL, // 1.5
+ 0x3FFC000000000000ULL, // 1.75
+ 0x4000000000000000ULL, // 2.0
+ 0x4004000000000000ULL, // 2.5
+ 0x4008000000000000ULL, // 3
+ 0x4010000000000000ULL, // 4
+ 0x4020000000000000ULL, // 8
+ 0x4030000000000000ULL, // 16
+ 0x4060000000000000ULL, // 2^7
+ 0x4070000000000000ULL, // 2^8
+ 0x40E0000000000000ULL, // 2^15
+ 0x40F0000000000000ULL, // 2^16
+ 0x7FF0000000000000ULL, // +inf
+ 0x7FF8000000000000ULL, // Canonical NaN
+ };
+
+ uint64_t ivalue{};
+ std::memcpy(&ivalue, &value, sizeof(uint64_t));
+
+ const auto iter = std::find_if(fli_table.cbegin(), fli_table.cend(), [ivalue](uint64_t entry) {
+ return entry == ivalue;
+ });
+ BISCUIT_ASSERT(iter != fli_table.cend());
+
+ const auto index = static_cast<uint32_t>(std::distance(fli_table.cbegin(), iter));
+ EmitRType(buffer, funct7, f1, GPR{index}, 0b000, rd, 0b1010011);
+}
+
+void Assembler::FLI_D(FPR rd, double value) noexcept {
+ FLIImpl(m_buffer, 0b1111001, rd, value);
+}
+void Assembler::FLI_H(FPR rd, double value) noexcept {
+ FLIImpl(m_buffer, 0b1111010, rd, value);
+}
+void Assembler::FLI_S(FPR rd, double value) noexcept {
+ FLIImpl(m_buffer, 0b1111000, rd, value);
+}
+
+void Assembler::FMINM_D(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FMINM_H(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FMINM_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b010, rd, 0b1010011);
+}
+void Assembler::FMINM_S(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b010, rd, 0b1010011);
+}
+
+void Assembler::FMAXM_D(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010101, rs2, rs1, 0b011, rd, 0b1010011);
+}
+void Assembler::FMAXM_H(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010110, rs2, rs1, 0b011, rd, 0b1010011);
+}
+void Assembler::FMAXM_Q(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010111, rs2, rs1, 0b011, rd, 0b1010011);
+}
+void Assembler::FMAXM_S(FPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b0010100, rs2, rs1, 0b011, rd, 0b1010011);
+}
+
+void Assembler::FROUND_D(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100001, f4, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FROUND_H(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100010, f4, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FROUND_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100011, f4, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FROUND_S(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100000, f4, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+
+void Assembler::FROUNDNX_D(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100001, f5, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FROUNDNX_H(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100010, f5, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FROUNDNX_Q(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100011, f5, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+void Assembler::FROUNDNX_S(FPR rd, FPR rs1, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100000, f5, rs1, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+
+void Assembler::FCVTMOD_W_D(GPR rd, FPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1100001, f8, rs1, static_cast<uint32_t>(RMode::RTZ), rd, 0b1010011);
+}
+
+void Assembler::FMVH_X_D(GPR rd, FPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1110001, f1, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMVH_X_Q(GPR rd, FPR rs1) noexcept {
+ EmitRType(m_buffer, 0b1110011, f1, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMVP_D_X(FPR rd, GPR rs1, GPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1011001, rs2, rs1, 0b000, rd, 0b1010011);
+}
+void Assembler::FMVP_Q_X(FPR rd, GPR rs1, GPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1011011, rs2, rs1, 0b000, rd, 0b1010011);
+}
+
+void Assembler::FLEQ_D(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b100, rd, 0b1010011);
+}
+void Assembler::FLTQ_D(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010001, rs2, rs1, 0b101, rd, 0b1010011);
+}
+
+void Assembler::FLEQ_H(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b100, rd, 0b1010011);
+}
+void Assembler::FLTQ_H(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010010, rs2, rs1, 0b101, rd, 0b1010011);
+}
+
+void Assembler::FLEQ_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b100, rd, 0b1010011);
+}
+void Assembler::FLTQ_Q(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010011, rs2, rs1, 0b101, rd, 0b1010011);
+}
+
+void Assembler::FLEQ_S(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b100, rd, 0b1010011);
+}
+void Assembler::FLTQ_S(GPR rd, FPR rs1, FPR rs2) noexcept {
+ EmitRType(m_buffer, 0b1010000, rs2, rs1, 0b101, rd, 0b1010011);
+}
+
+// Zfbfmin, Zvfbfmin, Zvfbfwma Extension Instructions
+
+void Assembler::FCVT_BF16_S(FPR rd, FPR rs, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100010, f8, rs, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+
+void Assembler::FCVT_S_BF16(FPR rd, FPR rs, RMode rmode) noexcept {
+ EmitRType(m_buffer, 0b0100000, f6, rs, static_cast<uint32_t>(rmode), rd, 0b1010011);
+}
+
+} // namespace biscuit