// 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.

#ifndef THIRD_PARTY_MPACT_RISCV_TEST_RISCV_GETTERS_ZFH_H_
#define THIRD_PARTY_MPACT_RISCV_TEST_RISCV_GETTERS_ZFH_H_

#include <cstdint>
#include <string>

#include "absl/strings/str_cat.h"
#include "mpact/sim/generic/immediate_operand.h"
#include "mpact/sim/generic/literal_operand.h"
#include "mpact/sim/generic/type_helpers.h"
#include "riscv/riscv_encoding_common.h"
#include "riscv/riscv_getter_helpers.h"
#include "riscv/riscv_getters_vector.h"
#include "riscv/riscv_register.h"
#include "riscv/riscv_register_aliases.h"

namespace mpact {
namespace sim {
namespace riscv {

using ::mpact::sim::generic::operator*;  // NOLINT: is used below (clang error).

template <typename Enum, typename Extractors, typename IntegerRegister>
void AddRiscVZfhSourceScalarGetters(SourceOpGetterMap &getter_map,
                                    RiscVEncodingCommon *common) {
  // Source operand getters.
  Insert(getter_map, *Enum::kRs1, [common]() -> SourceOperandInterface * {
    int num = Extractors::Inst32Format::ExtractRs1(common->inst_word());
    if (num == 0) return new generic::IntLiteralOperand<0>({1});
    return GetRegisterSourceOp<IntegerRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  // I in IImm12 stands for IType instructions.
  Insert(getter_map, *Enum::kIImm12, [common]() -> SourceOperandInterface * {
    const auto num = Extractors::IType::ExtractImm12(common->inst_word());
    return new generic::ImmediateOperand<int32_t>(num);
  });
  // S in SImm12 stands for SType instructions.
  Insert(getter_map, *Enum::kSImm12, [common]() -> SourceOperandInterface * {
    const auto num = Extractors::SType::ExtractSImm(common->inst_word());
    return new generic::ImmediateOperand<int32_t>(num);
  });
  Insert(getter_map, *Enum::kRm, [common]() -> SourceOperandInterface * {
    const auto num =
        Extractors::Inst32Format::ExtractFunc3(common->inst_word());
    return new generic::ImmediateOperand<uint8_t>(num);
  });
}

template <typename Enum, typename Extractors, typename FloatRegister>
void AddRiscVZfhSourceFloatGetters(SourceOpGetterMap &getter_map,
                                   RiscVEncodingCommon *common) {
  // Source operand getters.
  Insert(getter_map, *Enum::kFrs1, [common]() -> SourceOperandInterface * {
    int num = Extractors::Inst32Format::ExtractRs1(common->inst_word());
    return GetRegisterSourceOp<FloatRegister>(
        common->state(), absl::StrCat(RiscVState::kFregPrefix, num),
        kFRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kFrs2, [common]() -> SourceOperandInterface * {
    int num = Extractors::Inst32Format::ExtractRs2(common->inst_word());
    return GetRegisterSourceOp<FloatRegister>(
        common->state(), absl::StrCat(RiscVState::kFregPrefix, num),
        kFRegisterAliases[num]);
  });
}

template <typename Enum, typename Extractors, typename IntegerRegister>
void AddRiscVZfhDestScalarGetters(DestOpGetterMap &getter_map,
                                  RiscVEncodingCommon *common) {
  // Destination operand getters.
  Insert(getter_map, *Enum::kRd,
         [common](int latency) -> DestinationOperandInterface * {
           auto num = Extractors::Inst32Format::ExtractRd(common->inst_word());
           std::string name = absl::StrCat(RiscVState::kXregPrefix, num);
           return mpact::sim::riscv::GetRegisterDestinationOp<IntegerRegister>(
               common->state(), name, latency);
         });
  Insert(getter_map, *Enum::kFflags,
         [common](int latency) -> DestinationOperandInterface * {
           return GetCSRSetBitsDestinationOp<uint32_t>(common->state(),
                                                       "fflags", latency, "");
         });
}

template <typename Enum, typename Extractors, typename FloatRegister>
void AddRiscVZfhDestFloatGetters(DestOpGetterMap &getter_map,
                                 RiscVEncodingCommon *common) {
  // Destination operand getters.
  Insert(getter_map, *Enum::kFrd,
         [common](int latency) -> DestinationOperandInterface * {
           auto num = Extractors::Inst32Format::ExtractRd(common->inst_word());
           std::string name = absl::StrCat(RiscVState::kFregPrefix, num);
           return mpact::sim::riscv::GetRegisterDestinationOp<FloatRegister>(
               common->state(), name, latency);
         });
}

// This function is used to add the simple resource getters to the given
// "getter map". The function is templated on the enum type that defines the
// simple resource types, the Extractors type that defines the bit
// extraction functions, and the IntRegister and FpRegister types that are used
// to construct the register operand.
template <typename Enum, typename Extractors>
void AddRiscVZfhSimpleResourceGetters(SimpleResourceGetterMap &getter_map,
                                      RiscVEncodingCommon *common) {
  // TODO(julianmb): Add resource getters when appropriate.
}

}  // namespace riscv
}  // namespace sim
}  // namespace mpact

#endif  // THIRD_PARTY_MPACT_RISCV_TEST_RISCV_GETTERS_ZFH_H_
