blob: 044a9a443cbd0716c34f79c22021f9553c9ddd33 [file]
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "riscv/test/zfh_encoding.h"
#include <sys/types.h>
#include <cstdint>
#include <ios>
#include <memory>
#include <tuple>
#include <vector>
#include "absl/random/random.h"
#include "absl/strings/str_cat.h"
#include "mpact/sim/generic/immediate_operand.h"
#include "mpact/sim/generic/operand_interface.h"
#include "mpact/sim/generic/register.h"
#include "mpact/sim/generic/type_helpers.h"
#include "mpact/sim/util/memory/flat_demand_memory.h"
#include "riscv/riscv_register.h"
#include "riscv/riscv_state.h"
#include "riscv/zfh32_enums.h"
#include "riscv/zfh64_enums.h"
#include "testing/base/public/gmock.h"
#include "testing/base/public/gunit.h"
// Test that hand crafted zfh instructions are decoded and parsed correctly.
namespace {
using ::mpact::sim::generic::operator*; // NOLINT: clang-tidy false positive.
using ::mpact::sim::generic::ImmediateOperand;
using ::mpact::sim::generic::RegisterDestinationOperand;
using ::mpact::sim::generic::SourceOperandInterface;
using ::mpact::sim::riscv::RiscVState;
using ::mpact::sim::riscv::RiscVXlen;
using ::mpact::sim::riscv::RVFpRegister;
using ::mpact::sim::riscv::zfh::ZfhEncoding;
using ::mpact::sim::util::FlatDemandMemory;
// imm12 | rs1 | | rd | opcode
constexpr uint32_t kFlh = 0b000000000000'00000'001'00000'0000111;
// imm7 | rs2 | rs1 | |imm5 | opcode
constexpr uint32_t kFsh = 0b0000000'00000'00000'001'00000'0100111;
// func7 | | rs1 |fn3| rd | opcode
constexpr uint32_t kFmvXh = 0b1110010'00000'00000'000'00000'1010011;
// func7 | | rs1 |fn3| rd | opcode
constexpr uint32_t kFmvHx = 0b1111010'00000'00000'000'00000'1010011;
// func7 | | rs1 |rm | rd | opcode
constexpr uint32_t kFcvtSh = 0b0100000'00010'00000'000'00000'1010011;
// func7 | | rs1 |rm | rd | opcode
constexpr uint32_t kFcvtHs = 0b0100010'00000'00000'000'00000'1010011;
// func7 | | rs1 |rm | rd | opcode
constexpr uint32_t kFcvtDh = 0b0100001'00010'00000'000'00000'1010011;
// func7 | | rs1 |rm | rd | opcode
constexpr uint32_t kFcvtHd = 0b0100010'00001'00000'000'00000'1010011;
// func7 | rs2 | rs1 |rm | rd | opcode
constexpr uint32_t kFaddH = 0b0000010'00000'00000'000'00000'1010011;
// func7 | rs2 | rs1 |rm | rd | opcode
constexpr uint32_t kFsubH = 0b0000110'00000'00000'000'00000'1010011;
// func7 | rs2 | rs1 |rm | rd | opcode
constexpr uint32_t kFmulH = 0b0001010'00000'00000'000'00000'1010011;
// func7 | rs2 | rs1 |rm | rd | opcode
constexpr uint32_t kFdivH = 0b0001110'00000'00000'000'00000'1010011;
// func7 | rs2 | rs1 |fn3| rd | opcode
constexpr uint32_t kFminH = 0b0010110'00000'00000'000'00000'1010011;
// func7 | rs2 | rs1 |fn3| rd | opcode
constexpr uint32_t kFmaxH = 0b0010110'00000'00000'001'00000'1010011;
// func7 | rs2 | rs1 |fn3| rd | opcode
constexpr uint32_t kFsgnjH = 0b0010010'00000'00000'000'00000'1010011;
// func7 | rs2 | rs1 |fn3| rd | opcode
constexpr uint32_t kFsgnjnH = 0b0010010'00000'00000'001'00000'1010011;
// func7 | rs2 | rs1 |fn3| rd | opcode
constexpr uint32_t kFsgnjxH = 0b0010010'00000'00000'010'00000'1010011;
// func7 | | rs1 |rm | rd | opcode
constexpr uint32_t kFsqrtH = 0b0101110'00000'00000'000'00000'1010011;
// func7 | | rs1 |rm | rd | opcode
constexpr uint32_t kFcvtHw = 0b1101010'00000'00000'000'00000'1010011;
// func7 | | rs1 |rm | rd | opcode
constexpr uint32_t kFcvtWh = 0b1100010'00000'00000'000'00000'1010011;
// func7 | | rs1 |rm | rd | opcode
constexpr uint32_t kFcvtHwu = 0b1101010'00001'00000'000'00000'1010011;
// func7 | | rs1 |rm | rd | opcode
constexpr uint32_t kFcvtWuh = 0b1100010'00001'00000'000'00000'1010011;
// func7 | rs2 | rs1 |fn3| rd | opcode
constexpr uint32_t kFcmpeqH = 0b1010010'00000'00000'010'00000'1010011;
// func7 | rs2 | rs1 |fn3| rd | opcode
constexpr uint32_t kFcmpltH = 0b1010010'00000'00000'001'00000'1010011;
// func7 | rs2 | rs1 |fn3| rd | opcode
constexpr uint32_t kFcmpleH = 0b1010010'00000'00000'000'00000'1010011;
// func7 | | rs1 |fn3| rd | opcode
constexpr uint32_t kFclassH = 0b1110010'00000'00000'001'00000'1010011;
// rs3 |f2| rs2 | rs1 |rm | rd | opcode
constexpr uint32_t kFmaddH = 0b00000'10'00000'00000'000'00000'1000011;
// rs3 |f2| rs2 | rs1 |rm | rd | opcode
constexpr uint32_t kFmsubH = 0b00001'10'00000'00000'000'00000'1000111;
// rs3 |f2| rs2 | rs1 |rm | rd | opcode
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;
struct Zfh32Config {
using XRegister = ::mpact::sim::riscv::RV32Register;
using XValue = typename XRegister::ValueType;
using SlotEnum = ::mpact::sim::riscv::zfh32::SlotEnum;
using DestOpEnum = ::mpact::sim::riscv::zfh32::DestOpEnum;
using SourceOpEnum = ::mpact::sim::riscv::zfh32::SourceOpEnum;
using OpcodeEnum = ::mpact::sim::riscv::zfh32::OpcodeEnum;
using ComplexResourceEnum = ::mpact::sim::riscv::zfh32::ComplexResourceEnum;
using SimpleResourceEnum = ::mpact::sim::riscv::zfh32::SimpleResourceEnum;
static constexpr RiscVXlen rvXLen = RiscVXlen::RV32;
static constexpr int kXLen = 32;
static constexpr int slot = static_cast<int>(SlotEnum::kRiscv32Zfh);
static constexpr const char *const *kSourceOpNames =
::mpact::sim::riscv::zfh32::kSourceOpNames;
static constexpr const char *const *kDestOpNames =
::mpact::sim::riscv::zfh32::kDestOpNames;
static constexpr const char *const *kComplexResourceNames =
::mpact::sim::riscv::zfh32::kComplexResourceNames;
};
struct Zfh64Config {
using XRegister = ::mpact::sim::riscv::RV64Register;
using XValue = typename XRegister::ValueType;
using SlotEnum = ::mpact::sim::riscv::zfh64::SlotEnum;
using DestOpEnum = ::mpact::sim::riscv::zfh64::DestOpEnum;
using SourceOpEnum = ::mpact::sim::riscv::zfh64::SourceOpEnum;
using OpcodeEnum = ::mpact::sim::riscv::zfh64::OpcodeEnum;
using ComplexResourceEnum = ::mpact::sim::riscv::zfh64::ComplexResourceEnum;
using SimpleResourceEnum = ::mpact::sim::riscv::zfh64::SimpleResourceEnum;
static constexpr RiscVXlen rvXLen = RiscVXlen::RV64;
static constexpr int kXLen = 64;
static constexpr int slot = static_cast<int>(SlotEnum::kRiscv64Zfh);
static constexpr const char *const *kSourceOpNames =
::mpact::sim::riscv::zfh64::kSourceOpNames;
static constexpr const char *const *kDestOpNames =
::mpact::sim::riscv::zfh64::kDestOpNames;
static constexpr const char *const *kComplexResourceNames =
::mpact::sim::riscv::zfh64::kComplexResourceNames;
};
template <typename ConfigT>
struct ZfhEncodingTest : public testing::Test {
protected:
ZfhEncodingTest() {
state_ = new RiscVState("test", ConfigT::rvXLen, &memory_);
enc_ = new ZfhEncoding<ConfigT::kXLen>(state_);
expected_slot_ = static_cast<ConfigT::SlotEnum>(ConfigT::slot);
}
~ZfhEncodingTest() override {
delete enc_;
delete state_;
}
typename ConfigT::XValue RandomizeScalarRegister(int);
void ParseInstructionWithRs1(uint32_t, int);
typename ConfigT::XValue GetRs1SourceValue(typename ConfigT::OpcodeEnum);
void FloatFrdHelper(uint32_t, typename ConfigT::OpcodeEnum);
void FloatSourceHelper(uint32_t, typename ConfigT::OpcodeEnum, int);
void FloatSourceHelper(uint32_t, typename ConfigT::OpcodeEnum,
typename ConfigT::SourceOpEnum, int);
void FloatFrs1Helper(uint32_t, typename ConfigT::OpcodeEnum);
void FloatFrs2Helper(uint32_t, typename ConfigT::OpcodeEnum);
void FloatFrs3Helper(uint32_t, typename ConfigT::OpcodeEnum);
void FloatRmHelper(uint32_t, typename ConfigT::OpcodeEnum);
ConfigT::OpcodeEnum GetOpcode();
FlatDemandMemory memory_;
RiscVState *state_;
ZfhEncoding<ConfigT::kXLen> *enc_;
absl::BitGen gen_;
typename ConfigT::SlotEnum expected_slot_;
};
template <typename ConfigT>
ConfigT::OpcodeEnum ZfhEncodingTest<ConfigT>::GetOpcode() {
return static_cast<ConfigT::OpcodeEnum>(enc_->GetOpcode(expected_slot_, 0));
}
template <typename ConfigT>
typename ConfigT::XValue ZfhEncodingTest<ConfigT>::RandomizeScalarRegister(
int register_index) {
using XRegister = typename ConfigT::XRegister;
using XValue = typename ConfigT::XValue;
XValue register_value = register_index ? absl::Uniform<XValue>(gen_) : 0;
XRegister *rs1_reg;
std::tie(rs1_reg, std::ignore) = state_->GetRegister<XRegister>(
absl::StrCat("x", static_cast<uint32_t>(register_index)));
rs1_reg->data_buffer()->template Set<XValue>(0, register_value);
return register_value;
}
template <typename ConfigT>
void ZfhEncodingTest<ConfigT>::ParseInstructionWithRs1(
uint32_t binary_instruction, int rs1_index) {
int rs1_offset = 15;
uint32_t rs1_adjustment = static_cast<uint32_t>(rs1_index) << rs1_offset;
enc_->ParseInstruction(binary_instruction | rs1_adjustment);
}
template <typename ConfigT>
typename ConfigT::XValue ZfhEncodingTest<ConfigT>::GetRs1SourceValue(
typename ConfigT::OpcodeEnum opcode_enum) {
using XValue = typename ConfigT::XValue;
std::unique_ptr<SourceOperandInterface> src(enc_->GetSource(
expected_slot_, 0, opcode_enum, ConfigT::SourceOpEnum::kRs1, 0));
XValue observed_value;
if constexpr (ConfigT::kXLen == 32) {
observed_value = src->AsUint32(0);
} else {
observed_value = src->AsUint64(0);
}
return observed_value;
}
// TODO: b/421177084 - Move EXPECT_* out of helpers and back to test body.
template <typename ConfigT>
void ZfhEncodingTest<ConfigT>::FloatFrdHelper(
uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) {
int frd_offset = 7;
uint32_t base_instruction = binary_instruction & ~(0x0000'001F << frd_offset);
for (int frd_index = 0; frd_index < 32; ++frd_index) {
uint64_t expected_value = absl::Uniform<uint64_t>(gen_);
uint32_t frd_adjustment = static_cast<uint32_t>(frd_index) << frd_offset;
// Set the register value with a test value.
RVFpRegister *frd_reg;
std::tie(frd_reg, std::ignore) =
state_->GetRegister<RVFpRegister>(absl::StrCat("f", frd_index));
frd_reg->data_buffer()->Set<uint64_t>(0, expected_value);
// Parse the instruction and get the destination operand.
enc_->ParseInstruction(base_instruction | frd_adjustment);
std::unique_ptr<RegisterDestinationOperand<RVFpRegister>> dst(
static_cast<RegisterDestinationOperand<RVFpRegister> *>(
enc_->GetDestination(expected_slot_, 0, opcode_enum,
ConfigT::DestOpEnum::kFrd, 0, 0)));
// Pull the value from the destination operand and compare it to the
// expected value.
uint64_t observed_value =
dst->GetRegister()->data_buffer()->Get<uint64_t>(0);
EXPECT_EQ(observed_value, expected_value)
<< "frd_index: " << frd_index << ", expected_value: " << std::hex
<< expected_value << ", observed value: " << std::hex << observed_value;
}
}
// TODO: b/421177084 - Move EXPECT_* out of helpers and back to test body.
template <typename ConfigT>
void ZfhEncodingTest<ConfigT>::FloatSourceHelper(
uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum,
typename ConfigT::SourceOpEnum source_op_enum, int offset) {
using RegisterValue = typename RVFpRegister::ValueType;
uint32_t base_instruction = binary_instruction & ~(0x0000'001F << offset);
for (uint32_t frs1_index = 0; frs1_index < 32; ++frs1_index) {
uint32_t src_adjustment = frs1_index << offset;
RegisterValue expected_value = absl::Uniform<RegisterValue>(gen_);
// Set the register value with a test value.
RVFpRegister *frs1_reg;
std::tie(frs1_reg, std::ignore) =
state_->GetRegister<RVFpRegister>(absl::StrCat("f", frs1_index));
frs1_reg->data_buffer()->Set<RegisterValue>(0, expected_value);
// Parse the instruction and get the source operand.
enc_->ParseInstruction(base_instruction | src_adjustment);
std::unique_ptr<SourceOperandInterface> src(
enc_->GetSource(expected_slot_, 0, opcode_enum, source_op_enum, 0));
// Pull the value from the source operand and compare it to the expected
// value.
EXPECT_EQ(src->AsUint64(0), expected_value)
<< "frs1_index: " << frs1_index << ", expected_value: " << std::hex
<< expected_value << ", observed value: " << std::hex
<< src->AsUint64(0);
}
}
template <typename ConfigT>
void ZfhEncodingTest<ConfigT>::FloatFrs1Helper(
uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) {
FloatSourceHelper(binary_instruction, opcode_enum,
ConfigT::SourceOpEnum::kFrs1, 15);
}
template <typename ConfigT>
void ZfhEncodingTest<ConfigT>::FloatFrs2Helper(
uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) {
FloatSourceHelper(binary_instruction, opcode_enum,
ConfigT::SourceOpEnum::kFrs2, 20);
}
template <typename ConfigT>
void ZfhEncodingTest<ConfigT>::FloatFrs3Helper(
uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) {
FloatSourceHelper(binary_instruction, opcode_enum,
ConfigT::SourceOpEnum::kFrs3, 27);
}
// TODO: b/421177084 - Move EXPECT_* out of helpers and back to test body.
template <typename ConfigT>
void ZfhEncodingTest<ConfigT>::FloatRmHelper(
uint32_t binary_instruction, typename ConfigT::OpcodeEnum opcode_enum) {
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(expected_slot_, 0, ConfigT::OpcodeEnum::kFcvtSh,
ConfigT::SourceOpEnum::kRm, 0));
EXPECT_EQ(src->AsUint32(0), rm);
}
}
using MyTypes = ::testing::Types<Zfh32Config, Zfh64Config>;
TYPED_TEST_SUITE(ZfhEncodingTest, MyTypes);
TYPED_TEST(ZfhEncodingTest, SourceOperands) {
auto &getters = this->enc_->source_op_getters();
for (int i = *TypeParam::SourceOpEnum::kNone;
i < *TypeParam::SourceOpEnum::kPastMaxValue; ++i) {
EXPECT_TRUE(getters.contains(i))
<< "No source operand for enum value " << i << " ("
<< TypeParam::kSourceOpNames[i] << ")";
}
}
TYPED_TEST(ZfhEncodingTest, DestOperands) {
auto &getters = this->enc_->dest_op_getters();
for (int i = *TypeParam::DestOpEnum::kNone;
i < *TypeParam::DestOpEnum::kPastMaxValue; ++i) {
EXPECT_TRUE(getters.contains(i))
<< "No dest operand for enum value " << i << " ("
<< TypeParam::kDestOpNames[i] << ")";
}
}
// TODO: b/420935002 - Add simple resource getters and tests when we start using
// them.
TYPED_TEST(ZfhEncodingTest, ComplexResources) {
auto &getters = this->enc_->source_op_getters();
for (int i = *TypeParam::ComplexResourceEnum::kNone;
i < *TypeParam::ComplexResourceEnum::kPastMaxValue; ++i) {
EXPECT_TRUE(getters.contains(i))
<< "No source operand for enum value " << i << " ("
<< TypeParam::kComplexResourceNames[i] << ")";
}
}
TYPED_TEST(ZfhEncodingTest, Flh) {
this->enc_->ParseInstruction(kFlh);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFlh);
}
TYPED_TEST(ZfhEncodingTest, Flh_imm12) {
for (int iter = 0; iter < 1000; ++iter) {
int32_t expected_imm =
absl::Uniform<int32_t>(this->gen_, -1 * (1 << 11), 1 << 11);
bool sign = expected_imm < 0;
uint32_t imm_adjustment =
(sign ? 0x8000'0000 : 0) | ((expected_imm & 0x0000'07FF) << 20);
this->enc_->ParseInstruction(kFlh | imm_adjustment);
std::unique_ptr<ImmediateOperand<int32_t>> src(
static_cast<ImmediateOperand<int32_t> *>(this->enc_->GetSource(
this->expected_slot_, 0, TypeParam::OpcodeEnum::kFlh,
TypeParam::SourceOpEnum::kIImm12, 0)));
EXPECT_EQ(src->AsInt32(0), expected_imm);
}
}
TYPED_TEST(ZfhEncodingTest, Flh_rs1) {
using XValue = typename TypeParam::XValue;
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(kFlh, register_index);
XValue source_value = this->GetRs1SourceValue(TypeParam::OpcodeEnum::kFlh);
if (source_value != test_register_value) {
failed_scalar_sources.push_back(register_index);
}
}
EXPECT_THAT(failed_scalar_sources, ::testing::IsEmpty());
}
TYPED_TEST(ZfhEncodingTest, Flh_frd) {
this->FloatFrdHelper(kFlh, TypeParam::OpcodeEnum::kFlh);
}
TYPED_TEST(ZfhEncodingTest, Fsh) {
this->enc_->ParseInstruction(kFsh);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsh);
}
TYPED_TEST(ZfhEncodingTest, Fsh_imm12) {
for (int iter = 0; iter < 1000; ++iter) {
int32_t expected_imm =
absl::Uniform<int32_t>(this->gen_, -1 * (1 << 11), 1 << 11);
bool sign = expected_imm < 0;
uint32_t imm_adjustment = (sign ? 0x8000'0000 : 0) |
((expected_imm & 0x0000'001F) << 7) |
((expected_imm & 0x0000'07E0) << 20);
this->enc_->ParseInstruction(kFsh | imm_adjustment);
std::unique_ptr<ImmediateOperand<int32_t>> src(
static_cast<ImmediateOperand<int32_t> *>(this->enc_->GetSource(
this->expected_slot_, 0, TypeParam::OpcodeEnum::kFsh,
TypeParam::SourceOpEnum::kSImm12, 0)));
EXPECT_EQ(src->AsInt32(0), expected_imm);
}
}
TYPED_TEST(ZfhEncodingTest, Fsh_rs1) {
using XValue = typename TypeParam::XValue;
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(kFsh, register_index);
XValue source_value = this->GetRs1SourceValue(TypeParam::OpcodeEnum::kFsh);
if (source_value != test_register_value) {
failed_scalar_sources.push_back(register_index);
}
}
EXPECT_THAT(failed_scalar_sources, ::testing::IsEmpty());
}
TYPED_TEST(ZfhEncodingTest, Fsh_frs2) {
this->FloatFrs2Helper(kFsh, TypeParam::OpcodeEnum::kFsh);
}
TYPED_TEST(ZfhEncodingTest, FmvXh) {
this->enc_->ParseInstruction(kFmvXh);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmvXh);
}
TYPED_TEST(ZfhEncodingTest, FmvXh_frs1) {
this->FloatFrs1Helper(kFmvXh, TypeParam::OpcodeEnum::kFmvXh);
}
TYPED_TEST(ZfhEncodingTest, FmvXh_rd) {
using XRegister = TypeParam::XRegister;
using XValue = typename TypeParam::XRegister::ValueType;
for (uint32_t rd_index = 1; rd_index < 32; ++rd_index) {
uint32_t rd_adjustment = rd_index << 7;
XValue expected_value = absl::Uniform<XValue>(this->gen_);
XRegister *rd_reg;
std::tie(rd_reg, std::ignore) =
this->state_->template GetRegister<XRegister>(
absl::StrCat("x", rd_index));
rd_reg->data_buffer()->template Set<XValue>(0, expected_value);
this->enc_->ParseInstruction(kFmvXh | rd_adjustment);
std::unique_ptr<RegisterDestinationOperand<XRegister>> dst(
static_cast<RegisterDestinationOperand<XRegister> *>(
this->enc_->GetDestination(this->expected_slot_, 0,
TypeParam::OpcodeEnum::kFmvXh,
TypeParam::DestOpEnum::kRd, 0, 0)));
XValue observed_value =
dst->GetRegister()->data_buffer()->template Get<XValue>(0);
EXPECT_EQ(observed_value, expected_value);
}
}
TYPED_TEST(ZfhEncodingTest, FmvHx) {
this->enc_->ParseInstruction(kFmvHx);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmvHx);
}
TYPED_TEST(ZfhEncodingTest, FmvHx_rs1) {
using XValue = typename TypeParam::XValue;
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(kFmvHx, register_index);
XValue source_value =
this->GetRs1SourceValue(TypeParam::OpcodeEnum::kFmvHx);
if (source_value != test_register_value) {
failed_scalar_sources.push_back(register_index);
}
}
EXPECT_THAT(failed_scalar_sources, ::testing::IsEmpty());
}
TYPED_TEST(ZfhEncodingTest, FmvHx_frd) {
this->FloatFrdHelper(kFmvHx, TypeParam::OpcodeEnum::kFmvHx);
}
TYPED_TEST(ZfhEncodingTest, FcvtSh) {
this->enc_->ParseInstruction(kFcvtSh);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtSh);
}
TYPED_TEST(ZfhEncodingTest, FcvtSh_frs1) {
this->FloatFrs1Helper(kFcvtSh, TypeParam::OpcodeEnum::kFcvtSh);
}
TYPED_TEST(ZfhEncodingTest, FcvtSh_frd) {
this->FloatFrdHelper(kFcvtSh, TypeParam::OpcodeEnum::kFcvtSh);
}
TYPED_TEST(ZfhEncodingTest, FcvtSh_rm) {
this->FloatRmHelper(kFcvtSh, TypeParam::OpcodeEnum::kFcvtSh);
}
TYPED_TEST(ZfhEncodingTest, FcvtHs) {
this->enc_->ParseInstruction(kFcvtHs);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHs);
}
TYPED_TEST(ZfhEncodingTest, FcvtHs_frs1) {
this->FloatFrs1Helper(kFcvtHs, TypeParam::OpcodeEnum::kFcvtHs);
}
TYPED_TEST(ZfhEncodingTest, FcvtHs_frd) {
this->FloatFrdHelper(kFcvtHs, TypeParam::OpcodeEnum::kFcvtHs);
}
TYPED_TEST(ZfhEncodingTest, FcvtHs_rm) {
this->FloatRmHelper(kFcvtHs, TypeParam::OpcodeEnum::kFcvtHs);
}
TYPED_TEST(ZfhEncodingTest, FcvtDh) {
this->enc_->ParseInstruction(kFcvtDh);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtDh);
}
TYPED_TEST(ZfhEncodingTest, FcvtDh_frs1) {
this->FloatFrs1Helper(kFcvtDh, TypeParam::OpcodeEnum::kFcvtDh);
}
TYPED_TEST(ZfhEncodingTest, FcvtDh_frd) {
this->FloatFrdHelper(kFcvtDh, TypeParam::OpcodeEnum::kFcvtDh);
}
TYPED_TEST(ZfhEncodingTest, FcvtDh_rm) {
this->FloatRmHelper(kFcvtDh, TypeParam::OpcodeEnum::kFcvtDh);
}
TYPED_TEST(ZfhEncodingTest, FcvtHd) {
this->enc_->ParseInstruction(kFcvtHd);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHd);
}
TYPED_TEST(ZfhEncodingTest, FcvtHd_frs1) {
this->FloatFrs1Helper(kFcvtHd, TypeParam::OpcodeEnum::kFcvtHd);
}
TYPED_TEST(ZfhEncodingTest, FcvtHd_frd) {
this->FloatFrdHelper(kFcvtHd, TypeParam::OpcodeEnum::kFcvtHd);
}
TYPED_TEST(ZfhEncodingTest, FcvtHd_rm) {
this->FloatRmHelper(kFcvtHd, TypeParam::OpcodeEnum::kFcvtHd);
}
TYPED_TEST(ZfhEncodingTest, FaddH) {
this->enc_->ParseInstruction(kFaddH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFaddH);
}
TYPED_TEST(ZfhEncodingTest, FaddH_frs1) {
this->FloatFrs1Helper(kFaddH, TypeParam::OpcodeEnum::kFaddH);
}
TYPED_TEST(ZfhEncodingTest, FaddH_frs2) {
this->FloatFrs2Helper(kFaddH, TypeParam::OpcodeEnum::kFaddH);
}
TYPED_TEST(ZfhEncodingTest, FaddH_frd) {
this->FloatFrdHelper(kFaddH, TypeParam::OpcodeEnum::kFaddH);
}
TYPED_TEST(ZfhEncodingTest, FaddH_rm) {
this->FloatRmHelper(kFaddH, TypeParam::OpcodeEnum::kFaddH);
}
TYPED_TEST(ZfhEncodingTest, FsubH) {
this->enc_->ParseInstruction(kFsubH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsubH);
}
TYPED_TEST(ZfhEncodingTest, FsubH_frs1) {
this->FloatFrs1Helper(kFsubH, TypeParam::OpcodeEnum::kFsubH);
}
TYPED_TEST(ZfhEncodingTest, FsubH_frs2) {
this->FloatFrs2Helper(kFsubH, TypeParam::OpcodeEnum::kFsubH);
}
TYPED_TEST(ZfhEncodingTest, FsubH_frd) {
this->FloatFrdHelper(kFsubH, TypeParam::OpcodeEnum::kFsubH);
}
TYPED_TEST(ZfhEncodingTest, FsubH_rm) {
this->FloatRmHelper(kFsubH, TypeParam::OpcodeEnum::kFsubH);
}
TYPED_TEST(ZfhEncodingTest, FmulH) {
this->enc_->ParseInstruction(kFmulH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmulH);
}
TYPED_TEST(ZfhEncodingTest, FmulH_frs1) {
this->FloatFrs1Helper(kFmulH, TypeParam::OpcodeEnum::kFmulH);
}
TYPED_TEST(ZfhEncodingTest, FmulH_frs2) {
this->FloatFrs2Helper(kFmulH, TypeParam::OpcodeEnum::kFmulH);
}
TYPED_TEST(ZfhEncodingTest, FmulH_frd) {
this->FloatFrdHelper(kFmulH, TypeParam::OpcodeEnum::kFmulH);
}
TYPED_TEST(ZfhEncodingTest, FmulH_rm) {
this->FloatRmHelper(kFmulH, TypeParam::OpcodeEnum::kFmulH);
}
TYPED_TEST(ZfhEncodingTest, FdivH) {
this->enc_->ParseInstruction(kFdivH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFdivH);
}
TYPED_TEST(ZfhEncodingTest, FdivH_frs1) {
this->FloatFrs1Helper(kFdivH, TypeParam::OpcodeEnum::kFdivH);
}
TYPED_TEST(ZfhEncodingTest, FdivH_frs2) {
this->FloatFrs2Helper(kFdivH, TypeParam::OpcodeEnum::kFdivH);
}
TYPED_TEST(ZfhEncodingTest, FdivH_frd) {
this->FloatFrdHelper(kFdivH, TypeParam::OpcodeEnum::kFdivH);
}
TYPED_TEST(ZfhEncodingTest, FdivH_rm) {
this->FloatRmHelper(kFdivH, TypeParam::OpcodeEnum::kFdivH);
}
TYPED_TEST(ZfhEncodingTest, FminH) {
this->enc_->ParseInstruction(kFminH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFminH);
}
TYPED_TEST(ZfhEncodingTest, FminH_frs1) {
this->FloatFrs1Helper(kFminH, TypeParam::OpcodeEnum::kFminH);
}
TYPED_TEST(ZfhEncodingTest, FminH_frs2) {
this->FloatFrs2Helper(kFminH, TypeParam::OpcodeEnum::kFminH);
}
TYPED_TEST(ZfhEncodingTest, FminH_frd) {
this->FloatFrdHelper(kFminH, TypeParam::OpcodeEnum::kFminH);
}
TYPED_TEST(ZfhEncodingTest, FmaxH) {
this->enc_->ParseInstruction(kFmaxH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmaxH);
}
TYPED_TEST(ZfhEncodingTest, FmaxH_frs1) {
this->FloatFrs1Helper(kFmaxH, TypeParam::OpcodeEnum::kFmaxH);
}
TYPED_TEST(ZfhEncodingTest, FmaxH_frs2) {
this->FloatFrs2Helper(kFmaxH, TypeParam::OpcodeEnum::kFmaxH);
}
TYPED_TEST(ZfhEncodingTest, FmaxH_frd) {
this->FloatFrdHelper(kFmaxH, TypeParam::OpcodeEnum::kFmaxH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjH) {
this->enc_->ParseInstruction(kFsgnjH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsgnjH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjH_frs1) {
this->FloatFrs1Helper(kFsgnjH, TypeParam::OpcodeEnum::kFsgnjH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjH_frs2) {
this->FloatFrs2Helper(kFsgnjH, TypeParam::OpcodeEnum::kFsgnjH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjH_frd) {
this->FloatFrdHelper(kFsgnjH, TypeParam::OpcodeEnum::kFsgnjH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjnH) {
this->enc_->ParseInstruction(kFsgnjnH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsgnjnH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjnH_frs1) {
this->FloatFrs1Helper(kFsgnjnH, TypeParam::OpcodeEnum::kFsgnjnH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjnH_frs2) {
this->FloatFrs2Helper(kFsgnjnH, TypeParam::OpcodeEnum::kFsgnjnH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjnH_frd) {
this->FloatFrdHelper(kFsgnjnH, TypeParam::OpcodeEnum::kFsgnjnH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjxH) {
this->enc_->ParseInstruction(kFsgnjxH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsgnjxH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjxH_frs1) {
this->FloatFrs1Helper(kFsgnjxH, TypeParam::OpcodeEnum::kFsgnjxH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjxH_frs2) {
this->FloatFrs2Helper(kFsgnjxH, TypeParam::OpcodeEnum::kFsgnjxH);
}
TYPED_TEST(ZfhEncodingTest, FsgnjxH_frd) {
this->FloatFrdHelper(kFsgnjxH, TypeParam::OpcodeEnum::kFsgnjxH);
}
TYPED_TEST(ZfhEncodingTest, FsqrtH) {
this->enc_->ParseInstruction(kFsqrtH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFsqrtH);
}
TYPED_TEST(ZfhEncodingTest, FsqrtH_frs1) {
this->FloatFrs1Helper(kFsqrtH, TypeParam::OpcodeEnum::kFsqrtH);
}
TYPED_TEST(ZfhEncodingTest, FsqrtH_rm) {
this->FloatRmHelper(kFsqrtH, TypeParam::OpcodeEnum::kFsqrtH);
}
TYPED_TEST(ZfhEncodingTest, FsqrtH_frd) {
this->FloatFrdHelper(kFsqrtH, TypeParam::OpcodeEnum::kFsqrtH);
}
TYPED_TEST(ZfhEncodingTest, FcvtHw) {
this->enc_->ParseInstruction(kFcvtHw);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHw);
}
TYPED_TEST(ZfhEncodingTest, FcvtHw_frs1) {
this->FloatFrs1Helper(kFcvtHw, TypeParam::OpcodeEnum::kFcvtHw);
}
TYPED_TEST(ZfhEncodingTest, FcvtHw_rm) {
this->FloatRmHelper(kFcvtHw, TypeParam::OpcodeEnum::kFcvtHw);
}
TYPED_TEST(ZfhEncodingTest, FcvtHw_frd) {
this->FloatFrdHelper(kFcvtHw, TypeParam::OpcodeEnum::kFcvtHw);
}
TYPED_TEST(ZfhEncodingTest, FcvtWh) {
this->enc_->ParseInstruction(kFcvtWh);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtWh);
}
TYPED_TEST(ZfhEncodingTest, FcvtWh_frs1) {
this->FloatFrs1Helper(kFcvtWh, TypeParam::OpcodeEnum::kFcvtWh);
}
TYPED_TEST(ZfhEncodingTest, FcvtWh_rm) {
this->FloatRmHelper(kFcvtWh, TypeParam::OpcodeEnum::kFcvtWh);
}
TYPED_TEST(ZfhEncodingTest, FcvtWh_frd) {
this->FloatFrdHelper(kFcvtWh, TypeParam::OpcodeEnum::kFcvtWh);
}
TYPED_TEST(ZfhEncodingTest, FcvtHwu) {
this->enc_->ParseInstruction(kFcvtHwu);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtHwu);
}
TYPED_TEST(ZfhEncodingTest, FcvtHwu_frs1) {
this->FloatFrs1Helper(kFcvtHwu, TypeParam::OpcodeEnum::kFcvtHwu);
}
TYPED_TEST(ZfhEncodingTest, FcvtHwu_rm) {
this->FloatRmHelper(kFcvtHwu, TypeParam::OpcodeEnum::kFcvtHwu);
}
TYPED_TEST(ZfhEncodingTest, FcvtHwu_frd) {
this->FloatFrdHelper(kFcvtHwu, TypeParam::OpcodeEnum::kFcvtHwu);
}
TYPED_TEST(ZfhEncodingTest, FcvtWuh) {
this->enc_->ParseInstruction(kFcvtWuh);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcvtWuh);
}
TYPED_TEST(ZfhEncodingTest, FcvtWuh_frs1) {
this->FloatFrs1Helper(kFcvtWuh, TypeParam::OpcodeEnum::kFcvtWuh);
}
TYPED_TEST(ZfhEncodingTest, FcvtWuh_rm) {
this->FloatRmHelper(kFcvtWuh, TypeParam::OpcodeEnum::kFcvtWuh);
}
TYPED_TEST(ZfhEncodingTest, FcvtWuh_frd) {
this->FloatFrdHelper(kFcvtWuh, TypeParam::OpcodeEnum::kFcvtWuh);
}
TYPED_TEST(ZfhEncodingTest, FcmpeqH) {
this->enc_->ParseInstruction(kFcmpeqH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcmpeqH);
}
TYPED_TEST(ZfhEncodingTest, FcmpeqH_frs1) {
this->FloatFrs1Helper(kFcmpeqH, TypeParam::OpcodeEnum::kFcmpeqH);
}
TYPED_TEST(ZfhEncodingTest, FcmpeqH_frs2) {
this->FloatFrs2Helper(kFcmpeqH, TypeParam::OpcodeEnum::kFcmpeqH);
}
TYPED_TEST(ZfhEncodingTest, FcmpeqH_frd) {
this->FloatFrdHelper(kFcmpeqH, TypeParam::OpcodeEnum::kFcmpeqH);
}
TYPED_TEST(ZfhEncodingTest, FcmpltH) {
this->enc_->ParseInstruction(kFcmpltH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcmpltH);
}
TYPED_TEST(ZfhEncodingTest, FcmpltH_frs1) {
this->FloatFrs1Helper(kFcmpltH, TypeParam::OpcodeEnum::kFcmpltH);
}
TYPED_TEST(ZfhEncodingTest, FcmpltH_frs2) {
this->FloatFrs2Helper(kFcmpltH, TypeParam::OpcodeEnum::kFcmpltH);
}
TYPED_TEST(ZfhEncodingTest, FcmpltH_frd) {
this->FloatFrdHelper(kFcmpltH, TypeParam::OpcodeEnum::kFcmpltH);
}
TYPED_TEST(ZfhEncodingTest, FcmpleH) {
this->enc_->ParseInstruction(kFcmpleH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFcmpleH);
}
TYPED_TEST(ZfhEncodingTest, FcmpleH_frs1) {
this->FloatFrs1Helper(kFcmpleH, TypeParam::OpcodeEnum::kFcmpleH);
}
TYPED_TEST(ZfhEncodingTest, FcmpleH_frs2) {
this->FloatFrs2Helper(kFcmpleH, TypeParam::OpcodeEnum::kFcmpleH);
}
TYPED_TEST(ZfhEncodingTest, FcmpleH_frd) {
this->FloatFrdHelper(kFcmpleH, TypeParam::OpcodeEnum::kFcmpleH);
}
TYPED_TEST(ZfhEncodingTest, FclassH) {
this->enc_->ParseInstruction(kFclassH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFclassH);
}
TYPED_TEST(ZfhEncodingTest, FclassH_frs1) {
this->FloatFrs1Helper(kFclassH, TypeParam::OpcodeEnum::kFclassH);
}
TYPED_TEST(ZfhEncodingTest, FclassH_frd) {
this->FloatFrdHelper(kFclassH, TypeParam::OpcodeEnum::kFclassH);
}
TYPED_TEST(ZfhEncodingTest, FmaddH) {
this->enc_->ParseInstruction(kFmaddH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmaddH);
}
TYPED_TEST(ZfhEncodingTest, FmaddH_frs1) {
this->FloatFrs1Helper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH);
}
TYPED_TEST(ZfhEncodingTest, FmaddH_frs2) {
this->FloatFrs2Helper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH);
}
TYPED_TEST(ZfhEncodingTest, FmaddH_frs3) {
this->FloatFrs3Helper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH);
}
TYPED_TEST(ZfhEncodingTest, FmaddH_rm) {
this->FloatRmHelper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH);
}
TYPED_TEST(ZfhEncodingTest, FmaddH_frd) {
this->FloatFrdHelper(kFmaddH, TypeParam::OpcodeEnum::kFmaddH);
}
TYPED_TEST(ZfhEncodingTest, FmsubH) {
this->enc_->ParseInstruction(kFmsubH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFmsubH);
}
TYPED_TEST(ZfhEncodingTest, FmsubH_frs1) {
this->FloatFrs1Helper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH);
}
TYPED_TEST(ZfhEncodingTest, FmsubH_frs2) {
this->FloatFrs2Helper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH);
}
TYPED_TEST(ZfhEncodingTest, FmsubH_frs3) {
this->FloatFrs3Helper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH);
}
TYPED_TEST(ZfhEncodingTest, FmsubH_rm) {
this->FloatRmHelper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH);
}
TYPED_TEST(ZfhEncodingTest, FmsubH_frd) {
this->FloatFrdHelper(kFmsubH, TypeParam::OpcodeEnum::kFmsubH);
}
TYPED_TEST(ZfhEncodingTest, FnmaddH) {
this->enc_->ParseInstruction(kFnmaddH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFnmaddH);
}
TYPED_TEST(ZfhEncodingTest, FnmaddH_frs1) {
this->FloatFrs1Helper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH);
}
TYPED_TEST(ZfhEncodingTest, FnmaddH_frs2) {
this->FloatFrs2Helper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH);
}
TYPED_TEST(ZfhEncodingTest, FnmaddH_frs3) {
this->FloatFrs3Helper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH);
}
TYPED_TEST(ZfhEncodingTest, FnmaddH_rm) {
this->FloatRmHelper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH);
}
TYPED_TEST(ZfhEncodingTest, FnmaddH_frd) {
this->FloatFrdHelper(kFnmaddH, TypeParam::OpcodeEnum::kFnmaddH);
}
TYPED_TEST(ZfhEncodingTest, FnmsubH) {
this->enc_->ParseInstruction(kFnmsubH);
EXPECT_EQ(this->GetOpcode(), TypeParam::OpcodeEnum::kFnmsubH);
}
TYPED_TEST(ZfhEncodingTest, FnmsubH_frs1) {
this->FloatFrs1Helper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH);
}
TYPED_TEST(ZfhEncodingTest, FnmsubH_frs2) {
this->FloatFrs2Helper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH);
}
TYPED_TEST(ZfhEncodingTest, FnmsubH_frs3) {
this->FloatFrs3Helper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH);
}
TYPED_TEST(ZfhEncodingTest, FnmsubH_rm) {
this->FloatRmHelper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH);
}
TYPED_TEST(ZfhEncodingTest, FnmsubH_frd) {
this->FloatFrdHelper(kFnmsubH, TypeParam::OpcodeEnum::kFnmsubH);
}
} // namespace