zfh32: add semantic functions for fadd, fsub, fmul, fdiv PiperOrigin-RevId: 755097965 Change-Id: Iba9282a88a88efef330d905c2004eb8727a51be5
diff --git a/riscv/riscv_zfh.isa b/riscv/riscv_zfh.isa index 9afe769..f4461f7 100644 --- a/riscv/riscv_zfh.isa +++ b/riscv/riscv_zfh.isa
@@ -18,7 +18,7 @@ isa ZFH { namespace mpact::sim::riscv::zfh; slots { - riscv32_zfh_min; + riscv32_zfh; } } @@ -97,15 +97,44 @@ opcodes { flh{(: rs1, I_imm12 : ), (: : frd)}, resources: {next_pc, rs1 : frd[0..]}, - semfunc: "&RV64::RiscVILhu", "&RV64::RiscVZfhFlhChild", // new + semfunc: "&RV64::RiscVILhu", "&RV64::RiscVZfhFlhChild", disasm: "flh", "%frd, %I_imm12(%rs1)"; fsh{: rs1, S_imm12, frs2}, resources: {next_pc, rs1, frs2}, - semfunc: "&RV64::RiscVISh", // new + semfunc: "&RV64::RiscVISh", disasm: "fsh", "%frs2, %S_imm12(%rs1)"; fmv_xh{: frs1 : rd}, resources: {next_pc, frs1 : rd[0..]}, - semfunc: "&RV64::RiscVZfhFMvxh", // new + semfunc: "&RV64::RiscVZfhFMvxh", disasm: "fmv.x.h", "%rd, %frs1"; } } + +slot riscv32_zfh : riscv32_zfh_min { + includes { + #include "riscv/riscv_zfh_instructions.h" + } + default size = 4; + default latency = 0; + default opcode = + disasm: "Unimplemented instruction at 0x%(@:08x)", + semfunc: "&RV32VUnimplementedInstruction"; + opcodes { + fadd_h{: frs1, frs2, rm : frd, fflags}, + resources: {next_pc, frs1, frs2 : frd[0..]}, + semfunc: "&RiscVZfhFadd", + disasm: "fadd.h", "%frd, %frs1, %frs2"; + fsub_h{: frs1, frs2, rm : frd, fflags}, + resources: {next_pc, frs1, frs2 : frd[0..]}, + semfunc: "&RiscVZfhFsub", + disasm: "fsub.h", "%frd, %frs1, %frs2"; + fmul_h{: frs1, frs2, rm : frd, fflags}, + resources: {next_pc, frs1, frs2 : frd[0..]}, + semfunc: "&RiscVZfhFmul", + disasm: "fmul.h", "%frd, %frs1, %frs2"; + fdiv_h{: frs1, frs2, rm : frd, fflags}, + resources: {next_pc, frs1, frs2 : frd[0..]}, + semfunc: "&RiscVZfhFdiv", + disasm: "fdiv.h", "%frd, %frs1, %frs2"; + } +}
diff --git a/riscv/riscv_zfh_instructions.cc b/riscv/riscv_zfh_instructions.cc index cc4d4aa..83e2342 100644 --- a/riscv/riscv_zfh_instructions.cc +++ b/riscv/riscv_zfh_instructions.cc
@@ -14,6 +14,10 @@ #include "riscv/riscv_zfh_instructions.h" +#include <sys/types.h> + +#include <cassert> +#include <cmath> #include <cstdint> #include <functional> #include <limits> @@ -27,6 +31,7 @@ #include "riscv/riscv_csr.h" #include "riscv/riscv_fp_host.h" #include "riscv/riscv_fp_info.h" +#include "riscv/riscv_fp_state.h" #include "riscv/riscv_instruction_helpers.h" #include "riscv/riscv_register.h" #include "riscv/riscv_state.h" @@ -37,6 +42,8 @@ using HalfFP = ::mpact::sim::generic::HalfFP; using ::mpact::sim::generic::IsMpactFp; +using ::mpact::sim::generic::operator*; // NOLINT: is used below (clang error). +using ::mpact::sim::generic::IsMpactFp; namespace { @@ -209,6 +216,76 @@ return ConvertDoubleToHalfFP(input_value, rm, fflags); } +template <typename Argument, typename IntermediateType> +void RiscVZfhBinaryHelper( + const Instruction *instruction, + std::function<IntermediateType(IntermediateType, IntermediateType)> + operation) { + RiscVFPState *rv_fp = + static_cast<RiscVState *>(instruction->state())->rv_fp(); + int rm_value = generic::GetInstructionSource<int>(instruction, 2); + + // If the rounding mode is dynamic, read it from the current state. + if (rm_value == *FPRoundingMode::kDynamic) { + if (!rv_fp->rounding_mode_valid()) { + LOG(ERROR) << "Invalid rounding mode"; + return; + } + rm_value = *(rv_fp->GetRoundingMode()); + } + FPRoundingMode rm = static_cast<FPRoundingMode>(rm_value); + RiscVCsrDestinationOperand *fflags_dest = + static_cast<RiscVCsrDestinationOperand *>(instruction->Destination(1)); + uint32_t fflags = fflags_dest->GetRiscVCsr()->GetUint32(); + bool arguments_contain_snan = false; + IntermediateType b_emin = + std::pow(2.0, 1 - FPTypeInfo<IntermediateType>::kExpBias); + IntermediateType result; + RiscVBinaryFloatNaNBoxOp<RVFpRegister::ValueType, HalfFP, Argument>( + instruction, + [&operation, &arguments_contain_snan, &fflags, rv_fp, &rm, &result]( + Argument a, Argument b) -> HalfFP { + IntermediateType a_f; + IntermediateType b_f; + if (FPTypeInfo<Argument>::IsSNaN(a)) { + a_f = absl::bit_cast<IntermediateType>( + FPTypeInfo<IntermediateType>::kPosInf | 1); + arguments_contain_snan = true; + } else { + a_f = ConvertFromHalfFP<IntermediateType>(a, fflags); + } + if (FPTypeInfo<Argument>::IsSNaN(b)) { + b_f = absl::bit_cast<IntermediateType>( + FPTypeInfo<IntermediateType>::kPosInf | 1); + arguments_contain_snan = true; + } else { + b_f = ConvertFromHalfFP<IntermediateType>(b, fflags); + } + if (zfh_internal::UseHostFlagsForConversion()) { + result = operation(a_f, b_f); + } else { + ScopedFPStatus set_fpstatus(rv_fp->host_fp_interface(), rm); + result = operation(a_f, b_f); + } + if (!zfh_internal::UseHostFlagsForConversion()) { + fflags |= rv_fp->fflags()->GetUint32(); + } + return ConvertToHalfFP(result, rm, fflags); + }); + if (arguments_contain_snan) { + fflags_dest->GetRiscVCsr()->SetBits(*FPExceptions::kInvalidOp); + } + if (!zfh_internal::UseHostFlagsForConversion()) { + fflags_dest->GetRiscVCsr()->Write(fflags); + } + // When the result is less than b_emin before rounding we need to set the + // underflow flag. + if ((fflags_dest->GetRiscVCsr()->GetUint32() & *FPExceptions::kInexact) && + result != 0 && std::abs(result) < b_emin) { + fflags_dest->GetRiscVCsr()->SetBits(*FPExceptions::kUnderflow); + } +} + } // namespace namespace RV32 { @@ -301,6 +378,30 @@ }); } +// Add two half precision values. Do the calculation in single precision. +void RiscVZfhFadd(const Instruction *instruction) { + RiscVZfhBinaryHelper<HalfFP, float>( + instruction, [](float a, float b) -> float { return a + b; }); +} + +// Subtract two half precision values. Do the calculation in single precision. +void RiscVZfhFsub(const Instruction *instruction) { + RiscVZfhBinaryHelper<HalfFP, float>( + instruction, [](float a, float b) -> float { return a - b; }); +} + +// Multiply two half precision values. Do the calculation in single precision. +void RiscVZfhFmul(const Instruction *instruction) { + RiscVZfhBinaryHelper<HalfFP, float>( + instruction, [](float a, float b) -> float { return a * b; }); +} + +// Divide two half precision values. Do the calculation in single precision. +void RiscVZfhFdiv(const Instruction *instruction) { + RiscVZfhBinaryHelper<HalfFP, float>( + instruction, [](float a, float b) -> float { return a / b; }); +} + // TODO(b/409778536): Factor out generic unimplemented instruction semantic // function. void RV32VUnimplementedInstruction(const Instruction *instruction) {
diff --git a/riscv/riscv_zfh_instructions.h b/riscv/riscv_zfh_instructions.h index 9181490..fd2f713 100644 --- a/riscv/riscv_zfh_instructions.h +++ b/riscv/riscv_zfh_instructions.h
@@ -90,6 +90,7 @@ // TODO(b/409778536): Factor out generic unimplemented instruction semantic // function. void RV32VUnimplementedInstruction(const Instruction *instruction); + HalfFP ConvertSingleToHalfFP(float, FPRoundingMode, uint32_t &); HalfFP ConvertDoubleToHalfFP(double, FPRoundingMode, uint32_t &); @@ -97,6 +98,42 @@ bool UseHostFlagsForConversion(); } // namespace zfh_internal +// Source Operands: +// frs1: Float Register +// frs2: Float Register +// rm: Literal Operand (rounding mode) +// Destination Operands: +// frd: Float Register +// fflags: Accrued Exception Flags field in FCSR +void RiscVZfhFadd(const Instruction *instruction); + +// Source Operands: +// frs1: Float Register +// frs2: Float Register +// rm: Literal Operand (rounding mode) +// Destination Operands: +// frd: Float Register +// fflags: Accrued Exception Flags field in FCSR +void RiscVZfhFsub(const Instruction *instruction); + +// Source Operands: +// frs1: Float Register +// frs2: Float Register +// rm: Literal Operand (rounding mode) +// Destination Operands: +// frd: Float Register +// fflags: Accrued Exception Flags field in FCSR +void RiscVZfhFmul(const Instruction *instruction); + +// Source Operands: +// frs1: Float Register +// frs2: Float Register +// rm: Literal Operand (rounding mode) +// Destination Operands: +// frd: Float Register +// fflags: Accrued Exception Flags field in FCSR +void RiscVZfhFdiv(const Instruction *instruction); + } // namespace riscv } // namespace sim } // namespace mpact
diff --git a/riscv/riscv_zfh_instructions_arm.cc b/riscv/riscv_zfh_instructions_arm.cc index c8353fd..74104d2 100644 --- a/riscv/riscv_zfh_instructions_arm.cc +++ b/riscv/riscv_zfh_instructions_arm.cc
@@ -164,17 +164,6 @@ } } - // Handle flags for the specific underflow case. - if (unbounded_half_exponent < 0 || - (unbounded_half_exponent == 0 && fres2 != ftmp)) { - fflags |= static_cast<uint32_t>(FPExceptions::kUnderflow); - } - - // Handle flags for the specific inexact case. - if (fres2 != ftmp) { - fflags |= static_cast<uint32_t>(FPExceptions::kInexact); - } - // Construct the half float. half_fp.value = half_mantissa | (half_exponent << FPTypeInfo<HalfFP>::kSigSize) | @@ -191,11 +180,17 @@ T reconstructed_value = ((trailing_significand_float * precision_factor) + implicit_bit_adjustment) * exponent_factor * sign_factor; + bool exact_conversion = reconstructed_value == input_value; - if (reconstructed_value == input_value) { - // Clear the flags for exact conversions. - fflags &= ~(static_cast<uint32_t>(FPExceptions::kUnderflow) | - static_cast<uint32_t>(FPExceptions::kInexact)); + // Handle flags for the specific underflow case. + if (!exact_conversion && (unbounded_half_exponent < 0 || + (unbounded_half_exponent == 0 && fres2 != ftmp))) { + fflags |= static_cast<uint32_t>(FPExceptions::kUnderflow); + } + + // Handle flags for the specific inexact case. + if (!exact_conversion && (fres2 != ftmp)) { + fflags |= static_cast<uint32_t>(FPExceptions::kInexact); } return half_fp; }
diff --git a/riscv/test/riscv_fp_test_base.h b/riscv/test/riscv_fp_test_base.h index f60d156..f776d16 100644 --- a/riscv/test/riscv_fp_test_base.h +++ b/riscv/test/riscv_fp_test_base.h
@@ -681,7 +681,8 @@ for (int rm : {0, 1, 2, 3, 4}) { rv_fp_->SetRoundingMode(static_cast<FPRoundingMode>(rm)); SetRegisterValues<int, RV32Register>({{kRmName, rm}}); - SetRegisterValues<R, DestRegisterType>({{kRdName, 0}}); + SetRegisterValues<DestRegisterType::ValueType, DestRegisterType>( + {{kRdName, 0}}); inst->Execute(nullptr); @@ -761,7 +762,8 @@ rv_fp_->SetRoundingMode(static_cast<FPRoundingMode>(rm)); rv_fp_->fflags()->Write(static_cast<uint32_t>(0)); SetRegisterValues<int, RV32Register>({{kRmName, rm}, {}}); - SetRegisterValues<R, DestRegisterType>({{kRdName, 0}}); + SetRegisterValues<DestRegisterType::ValueType, DestRegisterType>( + {{kRdName, 0}}); inst->Execute(nullptr); @@ -780,11 +782,13 @@ FPCompare<R>(op_val, reg_val, delta_position, absl::StrCat(name, " ", i, ": ", FloatingPointToString<LHS>(lhs_span[i]), " ", - FloatingPointToString<RHS>(rhs_span[i]))); + FloatingPointToString<RHS>(rhs_span[i]), + " (rm: ", rm, ") ")); LhsUInt lhs_uint = absl::bit_cast<LhsUInt>(lhs_span[i]); RhsUInt rhs_uint = absl::bit_cast<RhsUInt>(rhs_span[i]); EXPECT_EQ(test_operation_fflags, instruction_fflags) - << std::hex << name << "(" << lhs_uint << ", " << rhs_uint << ")"; + << std::hex << name << "(" << lhs_uint << ", " << rhs_uint << ")" + << " rm: " << rm; } } } @@ -937,7 +941,8 @@ rv_fp_->SetRoundingMode(static_cast<FPRoundingMode>(rm)); rv_fp_->fflags()->Write(static_cast<uint32_t>(0)); SetRegisterValues<int, RV32Register>({{kRmName, rm}}); - SetRegisterValues<R, DestRegisterType>({{kRdName, 0}}); + SetRegisterValues<DestRegisterType::ValueType, DestRegisterType>( + {{kRdName, 0}}); inst->Execute(nullptr); // Get the fflags for the instruction execution. @@ -1376,7 +1381,7 @@ FPRoundingMode rm = FPRoundingMode::kRoundToNearest) { fflags_ = 0; U ret = Convert<U>(rm); - fflags = fflags_; + fflags |= fflags_; return ret; } @@ -1454,8 +1459,13 @@ } if (FPTypeInfo<FpType>::IsNaN(fp_value_)) { - return absl::bit_cast<U>(FPTypeInfo<FpReturnType>::kCanonicalNaN); - } else if (FPTypeInfo<FpType>::kPosInf == unsigned_value_) { + IntReturnType return_bits = + sign() ? 1ULL << (FPTypeInfo<FpReturnType>::kBitSize - 1) : 0; + return_bits |= FPTypeInfo<FpReturnType>::kCanonicalNaN; + return absl::bit_cast<U>(return_bits); + } + + if (FPTypeInfo<FpType>::kPosInf == unsigned_value_) { return absl::bit_cast<U>(FPTypeInfo<FpReturnType>::kPosInf); } else if (FPTypeInfo<FpType>::kNegInf == unsigned_value_) { return absl::bit_cast<U>(FPTypeInfo<FpReturnType>::kNegInf); @@ -1624,7 +1634,7 @@ if (result != fp_value_double) { double b_emin = std::pow(2.0, e_min); - if (std::abs(result) <= b_emin || std::abs(fp_value_double) <= b_emin) { + if (std::abs(result) < b_emin || std::abs(fp_value_double) < b_emin) { fflags_ |= static_cast<uint32_t>(FPExceptions::kUnderflow); } fflags_ |= static_cast<uint32_t>(FPExceptions::kInexact);
diff --git a/riscv/test/riscv_zfh_instructions_test.cc b/riscv/test/riscv_zfh_instructions_test.cc index 8b02448..876c5f5 100644 --- a/riscv/test/riscv_zfh_instructions_test.cc +++ b/riscv/test/riscv_zfh_instructions_test.cc
@@ -33,6 +33,7 @@ #include "mpact/sim/generic/instruction.h" #include "mpact/sim/generic/operand_interface.h" #include "mpact/sim/generic/type_helpers.h" +#include "riscv/riscv_fp_host.h" #include "riscv/riscv_fp_info.h" #include "riscv/riscv_i_instructions.h" #include "riscv/riscv_register.h" @@ -53,11 +54,16 @@ using ::mpact::sim::riscv::RiscVZfhCvtHd; using ::mpact::sim::riscv::RiscVZfhCvtHs; using ::mpact::sim::riscv::RiscVZfhCvtSh; +using ::mpact::sim::riscv::RiscVZfhFadd; +using ::mpact::sim::riscv::RiscVZfhFdiv; using ::mpact::sim::riscv::RiscVZfhFlhChild; +using ::mpact::sim::riscv::RiscVZfhFmul; using ::mpact::sim::riscv::RiscVZfhFMvhx; +using ::mpact::sim::riscv::RiscVZfhFsub; using ::mpact::sim::riscv::RV32Register; using ::mpact::sim::riscv::RV64Register; using ::mpact::sim::riscv::RVFpRegister; +using ::mpact::sim::riscv::RVXRegister; using ::mpact::sim::riscv::RV32::RiscVILhu; using ::mpact::sim::riscv::RV32::RiscVZfhFMvxh; using ::mpact::sim::riscv::test::FpConversionsTestHelper; @@ -564,6 +570,118 @@ EXPECT_EQ(absl::bit_cast<uint16_t>(actual_n0), expected_n0); } +// Add half precision values. Generate the expected result by using a natively +// supported float datatype for the operation. +TEST_F(RV32ZfhInstructionTest, RiscVZfhFadd) { + SetSemanticFunction(&RiscVZfhFadd); + BinaryOpWithFflagsFPTestHelper<HalfFP, HalfFP, HalfFP>( + "fadd.h", instruction_, {"f", "f", "f"}, 32, + [this](HalfFP a, HalfFP b) -> std::tuple<HalfFP, uint32_t> { + FPRoundingMode rm = rv_fp_->GetRoundingMode(); + uint32_t fflags = 0; + double a_f = + FpConversionsTestHelper(a).ConvertWithFlags<double>(fflags); + double b_f = + FpConversionsTestHelper(b).ConvertWithFlags<double>(fflags); + HalfFP result = + FpConversionsTestHelper(a_f + b_f).ConvertWithFlags<HalfFP>(fflags, + rm); + // inf + -inf, -inf + inf are both invalid. + if (std::isinf(a_f) && std::isinf(b_f) && a.value != b.value) { + fflags |= static_cast<uint32_t>( + mpact::sim::riscv::FPExceptions::kInvalidOp); + result.value = FPTypeInfo<HalfFP>::kCanonicalNaN; + } + return std::make_tuple(result, fflags); + }); +} + +// Subtract half precision values. Generate the expected result by using a +// natively supported float datatype for the operation. +TEST_F(RV32ZfhInstructionTest, RiscVZfhFsub) { + SetSemanticFunction(&RiscVZfhFsub); + BinaryOpWithFflagsFPTestHelper<HalfFP, HalfFP, HalfFP>( + "fsub.h", instruction_, {"f", "f", "f"}, 32, + [this](HalfFP a, HalfFP b) -> std::tuple<HalfFP, uint32_t> { + FPRoundingMode rm = rv_fp_->GetRoundingMode(); + uint32_t fflags = 0; + double a_f = + FpConversionsTestHelper(a).ConvertWithFlags<double>(fflags); + double b_f = + FpConversionsTestHelper(b).ConvertWithFlags<double>(fflags); + HalfFP result = + FpConversionsTestHelper(a_f - b_f).ConvertWithFlags<HalfFP>(fflags, + rm); + // inf - inf and -inf - -inf are both invalid. + if (std::isinf(a_f) && std::isinf(b_f) && a.value == b.value) { + fflags |= static_cast<uint32_t>( + mpact::sim::riscv::FPExceptions::kInvalidOp); + result.value = FPTypeInfo<HalfFP>::kCanonicalNaN; + } + return std::make_tuple(result, fflags); + }); +} + +// Multiply half precision values. Generate the expected result by using a +// natively supported float datatype for the operation. +TEST_F(RV32ZfhInstructionTest, RiscVZfhFmul) { + SetSemanticFunction(&RiscVZfhFmul); + BinaryOpWithFflagsFPTestHelper<HalfFP, HalfFP, HalfFP>( + "fmul.h", instruction_, {"f", "f", "f"}, 32, + [this](HalfFP a, HalfFP b) -> std::tuple<HalfFP, uint32_t> { + FPRoundingMode rm = rv_fp_->GetRoundingMode(); + uint32_t fflags = 0; + double a_f = + FpConversionsTestHelper(a).ConvertWithFlags<double>(fflags); + double b_f = + FpConversionsTestHelper(b).ConvertWithFlags<double>(fflags); + HalfFP result = + FpConversionsTestHelper(a_f * b_f).ConvertWithFlags<HalfFP>(fflags, + rm); + // Multiplying infinity and zero is invalid. + if ((std::isinf(a_f) && b_f == 0) || (a_f == 0 && std::isinf(b_f))) { + fflags |= static_cast<uint32_t>( + mpact::sim::riscv::FPExceptions::kInvalidOp); + result.value = FPTypeInfo<HalfFP>::kCanonicalNaN; + } + return std::make_tuple(result, fflags); + }); +} + +// Divide half precision values. Generate the expected result by using a +// natively supported float datatype for the operation. +TEST_F(RV32ZfhInstructionTest, RiscVZfhFdiv) { + SetSemanticFunction(&RiscVZfhFdiv); + BinaryOpWithFflagsFPTestHelper<HalfFP, HalfFP, HalfFP>( + "fdiv.h", instruction_, {"f", "f", "f"}, 32, + [this](HalfFP a, HalfFP b) -> std::tuple<HalfFP, uint32_t> { + FPRoundingMode rm = rv_fp_->GetRoundingMode(); + uint32_t fflags = 0; + double a_f = + FpConversionsTestHelper(a).ConvertWithFlags<double>(fflags); + double b_f = + FpConversionsTestHelper(b).ConvertWithFlags<double>(fflags); + HalfFP result = + FpConversionsTestHelper(a_f / b_f).ConvertWithFlags<HalfFP>(fflags, + rm); + if ((a_f == 0 && b_f == 0) || (std::isinf(a_f) && std::isinf(b_f))) { + // 0 / 0 and inf / inf are both invalid. + fflags |= static_cast<uint32_t>( + mpact::sim::riscv::FPExceptions::kInvalidOp); + result.value = FPTypeInfo<HalfFP>::kCanonicalNaN; + } else if (!FPTypeInfo<HalfFP>::IsNaN(a) && + (b.value == FPTypeInfo<HalfFP>::kPosZero || + b.value == FPTypeInfo<HalfFP>::kNegZero)) { + // Dividing by zero requires an exception for non-NaN dividend values. + result.value = ((a.value ^ b.value) & FPTypeInfo<HalfFP>::kNegZero) | + (FPTypeInfo<HalfFP>::kPosInf); + fflags |= static_cast<uint32_t>( + mpact::sim::riscv::FPExceptions::kDivByZero); + } + return std::make_tuple(result, fflags); + }); +} + class RV64ZfhInstructionTest : public RVZfhInstructionTestBase {}; // Move half precision from a float register to an integer register. The IEEE754
diff --git a/riscv/test/zfh_encoding_test.cc b/riscv/test/zfh_encoding_test.cc index dd37b8b..56980d3 100644 --- a/riscv/test/zfh_encoding_test.cc +++ b/riscv/test/zfh_encoding_test.cc
@@ -119,7 +119,7 @@ uint32_t rs1_adjustment = static_cast<uint32_t>(rs1_index) << rs1_offset; enc_->ParseInstruction(base_instruction | rs1_adjustment); std::unique_ptr<SourceOperandInterface> src(enc_->GetSource( - SlotEnum::kRiscv32ZfhMin, 0, opcode_enum, SourceOpEnum::kRs1, 0)); + SlotEnum::kRiscv32Zfh, 0, opcode_enum, SourceOpEnum::kRs1, 0)); // Pull the value from the source operand and compare it to the expected // value. @@ -148,7 +148,7 @@ enc_->ParseInstruction(base_instruction | frd_adjustment); std::unique_ptr<RegisterDestinationOperand<RVFpRegister>> dst( static_cast<RegisterDestinationOperand<RVFpRegister> *>( - enc_->GetDestination(SlotEnum::kRiscv32ZfhMin, 0, opcode_enum, + enc_->GetDestination(SlotEnum::kRiscv32Zfh, 0, opcode_enum, DestOpEnum::kFrd, 0, 0))); // Pull the value from the destination operand and compare it to the @@ -179,7 +179,7 @@ // Parse the instruction and get the source operand. enc_->ParseInstruction(base_instruction | src_adjustment); std::unique_ptr<SourceOperandInterface> src(enc_->GetSource( - SlotEnum::kRiscv32ZfhMin, 0, opcode_enum, source_op_enum, 0)); + SlotEnum::kRiscv32Zfh, 0, opcode_enum, source_op_enum, 0)); // Pull the value from the source operand and compare it to the expected // value. @@ -205,9 +205,8 @@ for (int rm = 0; rm <= 6; ++rm) { uint32_t rm_adjustment = rm << 12; enc_->ParseInstruction(kFcvtSh | rm_adjustment); - std::unique_ptr<SourceOperandInterface> src( - enc_->GetSource(SlotEnum::kRiscv32ZfhMin, 0, OpcodeEnum::kFcvtSh, - SourceOpEnum::kRm, 0)); + std::unique_ptr<SourceOperandInterface> src(enc_->GetSource( + SlotEnum::kRiscv32Zfh, 0, OpcodeEnum::kFcvtSh, SourceOpEnum::kRm, 0)); EXPECT_EQ(src->AsUint32(0), rm); } } @@ -251,7 +250,7 @@ TEST_F(ZfhEncodingTest, Flh) { enc_->ParseInstruction(kFlh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32ZfhMin, 0), OpcodeEnum::kFlh); + EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFlh); } TEST_F(ZfhEncodingTest, Flh_imm12) { @@ -264,7 +263,7 @@ enc_->ParseInstruction(kFlh | imm_adjustment); std::unique_ptr<ImmediateOperand<int32_t>> src( static_cast<ImmediateOperand<int32_t> *>( - enc_->GetSource(SlotEnum::kRiscv32ZfhMin, 0, OpcodeEnum::kFlh, + enc_->GetSource(SlotEnum::kRiscv32Zfh, 0, OpcodeEnum::kFlh, SourceOpEnum::kIImm12, 0))); EXPECT_EQ(src->AsInt32(0), expected_imm); } @@ -276,7 +275,7 @@ TEST_F(ZfhEncodingTest, Fsh) { enc_->ParseInstruction(kFsh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32ZfhMin, 0), OpcodeEnum::kFsh); + EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFsh); } TEST_F(ZfhEncodingTest, Fsh_imm12) { @@ -290,7 +289,7 @@ enc_->ParseInstruction(kFsh | imm_adjustment); std::unique_ptr<ImmediateOperand<int32_t>> src( static_cast<ImmediateOperand<int32_t> *>( - enc_->GetSource(SlotEnum::kRiscv32ZfhMin, 0, OpcodeEnum::kFsh, + enc_->GetSource(SlotEnum::kRiscv32Zfh, 0, OpcodeEnum::kFsh, SourceOpEnum::kSImm12, 0))); EXPECT_EQ(src->AsInt32(0), expected_imm); } @@ -302,7 +301,7 @@ TEST_F(ZfhEncodingTest, FmvXh) { enc_->ParseInstruction(kFmvXh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32ZfhMin, 0), OpcodeEnum::kFmvXh); + EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFmvXh); } TEST_F(ZfhEncodingTest, FmvXh_frs1) { @@ -320,8 +319,8 @@ enc_->ParseInstruction(kFmvXh | rd_adjustment); std::unique_ptr<RegisterDestinationOperand<RVXRegister>> dst( static_cast<RegisterDestinationOperand<RVXRegister> *>( - enc_->GetDestination(SlotEnum::kRiscv32ZfhMin, 0, - OpcodeEnum::kFmvXh, DestOpEnum::kRd, 0, 0))); + enc_->GetDestination(SlotEnum::kRiscv32Zfh, 0, OpcodeEnum::kFmvXh, + DestOpEnum::kRd, 0, 0))); uint32_t observed_value = dst->GetRegister()->data_buffer()->Get<uint32_t>(0); EXPECT_EQ(observed_value, expected_value); @@ -330,7 +329,7 @@ TEST_F(ZfhEncodingTest, FmvHx) { enc_->ParseInstruction(kFmvHx); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32ZfhMin, 0), OpcodeEnum::kFmvHx); + EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFmvHx); } TEST_F(ZfhEncodingTest, FmvHx_rs1) { @@ -343,7 +342,7 @@ TEST_F(ZfhEncodingTest, FcvtSh) { enc_->ParseInstruction(kFcvtSh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32ZfhMin, 0), OpcodeEnum::kFcvtSh); + EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtSh); } TEST_F(ZfhEncodingTest, FcvtSh_frs1) { @@ -360,7 +359,7 @@ TEST_F(ZfhEncodingTest, FcvtHs) { enc_->ParseInstruction(kFcvtHs); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32ZfhMin, 0), OpcodeEnum::kFcvtHs); + EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtHs); } TEST_F(ZfhEncodingTest, FcvtHs_frs1) { @@ -377,7 +376,7 @@ TEST_F(ZfhEncodingTest, FcvtDh) { enc_->ParseInstruction(kFcvtDh); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32ZfhMin, 0), OpcodeEnum::kFcvtDh); + EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtDh); } TEST_F(ZfhEncodingTest, FcvtDh_frs1) { @@ -394,7 +393,7 @@ TEST_F(ZfhEncodingTest, FcvtHd) { enc_->ParseInstruction(kFcvtHd); - EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32ZfhMin, 0), OpcodeEnum::kFcvtHd); + EXPECT_EQ(enc_->GetOpcode(SlotEnum::kRiscv32Zfh, 0), OpcodeEnum::kFcvtHd); } TEST_F(ZfhEncodingTest, FcvtHd_frs1) {