Zfh: Add encoding tests for half precision <-> 64 bit integer conversion instructions

PiperOrigin-RevId: 768186277
Change-Id: I00d2d699e9dbdf5edf2ffdccb6c27979754d025c
diff --git a/riscv/riscv_zfh.isa b/riscv/riscv_zfh.isa
index 5aec5ae..1ff9bd1 100644
--- a/riscv/riscv_zfh.isa
+++ b/riscv/riscv_zfh.isa
@@ -278,11 +278,11 @@
       semfunc: "&RV64::RiscVZfhCvtLuh",
       disasm: "fcvt.lu.h", "%rd, %frs1";
     fcvt_hl{: rs1, rm : frd, fflags},
-      resources: {next_pc, frs1 : frd[0..]},
+      resources: {next_pc, rs1 : frd[0..]},
       semfunc: "&RV64::RiscVZfhCvtHl",
       disasm: "fcvt.h.l", "%frd, %rs1";
     fcvt_hlu{: rs1, rm : frd, fflags},
-      resources: {next_pc, frs1 : frd[0..]},
+      resources: {next_pc, rs1 : frd[0..]},
       semfunc: "&RV64::RiscVZfhCvtHlu",
       disasm: "fcvt.h.lu", "%frd, %rs1";
   }
diff --git a/riscv/riscv_zfh32.bin_fmt b/riscv/riscv_zfh32.bin_fmt
index 9a49ae9..0bb8708 100644
--- a/riscv/riscv_zfh32.bin_fmt
+++ b/riscv/riscv_zfh32.bin_fmt
@@ -44,14 +44,14 @@
   fsqrt_h  : RType : func7 == 0b0101110, rs2 == 0b00000, opcode == 0b1010011;
   fcvt_hw  : RType : func7 == 0b1101010, rs2 == 0b00000, opcode == 0b1010011;
   fcvt_wh  : RType : func7 == 0b1100010, rs2 == 0b00000, opcode == 0b1010011;
-  fcvt_hwu  : RType : func7 == 0b1101010, rs2 == 0b00001, opcode == 0b1010011;
-  fcvt_wuh  : RType : func7 == 0b1100010, rs2 == 0b00001, opcode == 0b1010011;
-  fcmpeq_h  : RType : func7 == 0b1010010, func3 == 0b010, opcode == 0b1010011;
-  fcmplt_h  : RType : func7 == 0b1010010, func3 == 0b001, opcode == 0b1010011;
-  fcmple_h  : RType : func7 == 0b1010010, func3 == 0b000, opcode == 0b1010011;
-  fclass_h  : RType : func7 == 0b1110010, rs2 == 0b00000, func3 == 0b001, opcode == 0b1010011;
-  fmadd_h   : R4Type : func2 == 0b10, opcode == 0b1000011;
-  fmsub_h   : R4Type : func2 == 0b10, opcode == 0b1000111;
-  fnmsub_h  : R4Type : func2 == 0b10, opcode == 0b1001011;
-  fnmadd_h  : R4Type : func2 == 0b10, opcode == 0b1001111;
+  fcvt_hwu : RType : func7 == 0b1101010, rs2 == 0b00001, opcode == 0b1010011;
+  fcvt_wuh : RType : func7 == 0b1100010, rs2 == 0b00001, opcode == 0b1010011;
+  fcmpeq_h : RType : func7 == 0b1010010, func3 == 0b010, opcode == 0b1010011;
+  fcmplt_h : RType : func7 == 0b1010010, func3 == 0b001, opcode == 0b1010011;
+  fcmple_h : RType : func7 == 0b1010010, func3 == 0b000, opcode == 0b1010011;
+  fclass_h : RType : func7 == 0b1110010, rs2 == 0b00000, func3 == 0b001, opcode == 0b1010011;
+  fmadd_h  : R4Type : func2 == 0b10, opcode == 0b1000011;
+  fmsub_h  : R4Type : func2 == 0b10, opcode == 0b1000111;
+  fnmsub_h : R4Type : func2 == 0b10, opcode == 0b1001011;
+  fnmadd_h : R4Type : func2 == 0b10, opcode == 0b1001111;
 };
diff --git a/riscv/riscv_zfh64.bin_fmt b/riscv/riscv_zfh64.bin_fmt
index 538628c..ede34bf 100644
--- a/riscv/riscv_zfh64.bin_fmt
+++ b/riscv/riscv_zfh64.bin_fmt
@@ -44,14 +44,18 @@
   fsqrt_h  : RType : func7 == 0b0101110, rs2 == 0b00000, opcode == 0b1010011;
   fcvt_hw  : RType : func7 == 0b1101010, rs2 == 0b00000, opcode == 0b1010011;
   fcvt_wh  : RType : func7 == 0b1100010, rs2 == 0b00000, opcode == 0b1010011;
-  fcvt_hwu  : RType : func7 == 0b1101010, rs2 == 0b00001, opcode == 0b1010011;
-  fcvt_wuh  : RType : func7 == 0b1100010, rs2 == 0b00001, opcode == 0b1010011;
-  fcmpeq_h  : RType : func7 == 0b1010010, func3 == 0b010, opcode == 0b1010011;
-  fcmplt_h  : RType : func7 == 0b1010010, func3 == 0b001, opcode == 0b1010011;
-  fcmple_h  : RType : func7 == 0b1010010, func3 == 0b000, opcode == 0b1010011;
-  fclass_h  : RType : func7 == 0b1110010, rs2 == 0b00000, func3 == 0b001, opcode == 0b1010011;
-  fmadd_h   : R4Type : func2 == 0b10, opcode == 0b1000011;
-  fmsub_h   : R4Type : func2 == 0b10, opcode == 0b1000111;
-  fnmsub_h  : R4Type : func2 == 0b10, opcode == 0b1001011;
-  fnmadd_h  : R4Type : func2 == 0b10, opcode == 0b1001111;
+  fcvt_hwu : RType : func7 == 0b1101010, rs2 == 0b00001, opcode == 0b1010011;
+  fcvt_wuh : RType : func7 == 0b1100010, rs2 == 0b00001, opcode == 0b1010011;
+  fcmpeq_h : RType : func7 == 0b1010010, func3 == 0b010, opcode == 0b1010011;
+  fcmplt_h : RType : func7 == 0b1010010, func3 == 0b001, opcode == 0b1010011;
+  fcmple_h : RType : func7 == 0b1010010, func3 == 0b000, opcode == 0b1010011;
+  fclass_h : RType : func7 == 0b1110010, rs2 == 0b00000, func3 == 0b001, opcode == 0b1010011;
+  fmadd_h  : R4Type : func2 == 0b10, opcode == 0b1000011;
+  fmsub_h  : R4Type : func2 == 0b10, opcode == 0b1000111;
+  fnmsub_h : R4Type : func2 == 0b10, opcode == 0b1001011;
+  fnmadd_h : R4Type : func2 == 0b10, opcode == 0b1001111;
+  fcvt_lh  : RType : func7 == 0b1100010, rs2 == 0b00010, opcode == 0b1010011;
+  fcvt_luh : RType : func7 == 0b1100010, rs2 == 0b00011, opcode == 0b1010011;
+  fcvt_hl  : RType : func7 == 0b1101010, rs2 == 0b00010, opcode == 0b1010011;
+  fcvt_hlu : RType : func7 == 0b1101010, rs2 == 0b00011, opcode == 0b1010011;
 };
diff --git a/riscv/test/zfh_encoding_test.cc b/riscv/test/zfh_encoding_test.cc
index 974420d..3f54fc5 100644
--- a/riscv/test/zfh_encoding_test.cc
+++ b/riscv/test/zfh_encoding_test.cc
@@ -112,6 +112,14 @@
 constexpr uint32_t kFnmaddH = 0b00000'10'00000'00000'000'00000'1001111;
 //                              rs3  |f2| rs2 | rs1 |rm | rd  | opcode
 constexpr uint32_t kFnmsubH = 0b00000'10'00000'00000'000'00000'1001011;
+//   64 bit only                func7 |     | rs1 |rm | rd  | opcode
+constexpr uint32_t kFcvtLh = 0b1100010'00010'00000'000'00000'1010011;
+//   64 bit only                 func7 |     | rs1 |rm | rd  | opcode
+constexpr uint32_t kFcvtLuh = 0b1100010'00011'00000'000'00000'1010011;
+//   64 bit only                func7 |     | rs1 |rm | rd  | opcode
+constexpr uint32_t kFcvtHl = 0b1101010'00010'00000'000'00000'1010011;
+//   64 bit only                 func7 |     | rs1 |rm | rd  | opcode
+constexpr uint32_t kFcvtHlu = 0b1101010'00011'00000'000'00000'1010011;
 
 struct Zfh32Config {
   using XRegister = ::mpact::sim::riscv::RV32Register;
@@ -1054,4 +1062,152 @@
   this->FloatFrdHelper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH);
 }
 
+TYPED_TEST(ZfhEncodingTest, FcvtLh) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->enc_->ParseInstruction(kFcvtLh);
+    EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtLh);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtLh_frs1) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->FloatFrs1Helper(kFcvtLh, TypeParam::OpcodeEnum::kFcvtLh);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtLh_rm) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->FloatRmHelper(kFcvtLh, TypeParam::OpcodeEnum::kFcvtLh);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtLh_rd) {
+  using XValue = typename TypeParam::XValue;
+  if constexpr (TypeParam::kXLen == 64) {
+    std::vector<int> failed_scalar_destinations;
+    for (int register_index = 1; register_index < 32; register_index++) {
+      XValue test_register_value =
+          this->RandomizeScalarRegister(register_index);
+      this->ParseInstructionWithRd(kFcvtLh, register_index);
+      XValue destination_value =
+          this->GetRdDestinationValue(TypeParam::OpcodeEnum::kFcvtLh);
+      if (destination_value != test_register_value) {
+        failed_scalar_destinations.push_back(register_index);
+      }
+    }
+    EXPECT_THAT(failed_scalar_destinations, ::testing::IsEmpty());
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtLuh) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->enc_->ParseInstruction(kFcvtLuh);
+    EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtLuh);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtLuh_frs1) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->FloatFrs1Helper(kFcvtLuh, TypeParam::OpcodeEnum::kFcvtLuh);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtLuh_rm) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->FloatRmHelper(kFcvtLuh, TypeParam::OpcodeEnum::kFcvtLuh);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtLuh_rd) {
+  using XValue = typename TypeParam::XValue;
+  if constexpr (TypeParam::kXLen == 64) {
+    std::vector<int> failed_scalar_destinations;
+    for (int register_index = 1; register_index < 32; register_index++) {
+      XValue test_register_value =
+          this->RandomizeScalarRegister(register_index);
+      this->ParseInstructionWithRd(kFcvtLuh, register_index);
+      XValue destination_value =
+          this->GetRdDestinationValue(TypeParam::OpcodeEnum::kFcvtLuh);
+      if (destination_value != test_register_value) {
+        failed_scalar_destinations.push_back(register_index);
+      }
+    }
+    EXPECT_THAT(failed_scalar_destinations, ::testing::IsEmpty());
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtHl) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->enc_->ParseInstruction(kFcvtHl);
+    EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHl);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtHl_rs1) {
+  using XValue = typename TypeParam::XValue;
+  if constexpr (TypeParam::kXLen == 64) {
+    std::vector<int> failed_scalar_sources;
+    for (int register_index = 0; register_index < 32; register_index++) {
+      XValue test_register_value =
+          this->RandomizeScalarRegister(register_index);
+      this->ParseInstructionWithRs1(kFcvtHl, register_index);
+      XValue source_value =
+          this->GetRs1SourceValue(TypeParam::OpcodeEnum::kFcvtHl);
+      if (source_value != test_register_value) {
+        failed_scalar_sources.push_back(register_index);
+      }
+    }
+    EXPECT_THAT(failed_scalar_sources, ::testing::IsEmpty());
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtHl_rm) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->FloatRmHelper(kFcvtHl, TypeParam::OpcodeEnum::kFcvtHl);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtHl_frd) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->FloatFrdHelper(kFcvtHl, TypeParam::OpcodeEnum::kFcvtHl);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtHlu) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->enc_->ParseInstruction(kFcvtHlu);
+    EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHlu);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtHlu_rs1) {
+  using XValue = typename TypeParam::XValue;
+  if constexpr (TypeParam::kXLen == 64) {
+    std::vector<int> failed_scalar_sources;
+    for (int register_index = 0; register_index < 32; register_index++) {
+      XValue test_register_value =
+          this->RandomizeScalarRegister(register_index);
+      this->ParseInstructionWithRs1(kFcvtHlu, register_index);
+      XValue source_value =
+          this->GetRs1SourceValue(TypeParam::OpcodeEnum::kFcvtHlu);
+      if (source_value != test_register_value) {
+        failed_scalar_sources.push_back(register_index);
+      }
+    }
+    EXPECT_THAT(failed_scalar_sources, ::testing::IsEmpty());
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtHlu_rm) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->FloatRmHelper(kFcvtHlu, TypeParam::OpcodeEnum::kFcvtHlu);
+  }
+}
+
+TYPED_TEST(ZfhEncodingTest, FcvtHlu_frd) {
+  if constexpr (TypeParam::kXLen == 64) {
+    this->FloatFrdHelper(kFcvtHlu, TypeParam::OpcodeEnum::kFcvtHlu);
+  }
+}
+
 }  // namespace