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

// This file adds operand getters for the Zc* extensions.

#ifndef THIRD_PARTY_MPACT_RISCV_RISCV_ZC_GETTERS_H_
#define THIRD_PARTY_MPACT_RISCV_RISCV_ZC_GETTERS_H_

#include <cstdint>
#include <vector>

#include "absl/strings/str_cat.h"
#include "mpact/sim/generic/immediate_operand.h"
#include "mpact/sim/generic/literal_operand.h"
#include "mpact/sim/generic/operand_interface.h"
#include "mpact/sim/generic/resource_operand_interface.h"
#include "riscv/riscv_encoding_common.h"
#include "riscv/riscv_getter_helpers.h"
#include "riscv/riscv_register_aliases.h"
#include "riscv/riscv_state.h"

namespace mpact::sim::riscv {
using ::mpact::sim::generic::DestinationOperandInterface;
using ::mpact::sim::generic::ImmediateOperand;
using ::mpact::sim::generic::IntLiteralOperand;
using ::mpact::sim::generic::ResourceOperandInterface;
using ::mpact::sim::generic::SourceOperandInterface;

using SourceOpIf = SourceOperandInterface;

// The following function adds source operand getters to the given getter map.
// The function uses the template parameters to get the correct enum type
// for the instruction set being decoded. The Extractors parameter is used to
// get the correct instruction format extractor for the instruction set. The
// IntRegister and FpRegister parameters are used to get the correct register
// types for the instruction set.

// Getters for Zca source operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcaSourceGetters(SourceOpGetterMap& getter_map,
                              RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kC3rs1, [common]() {
    auto num = Extractors::CS::ExtractCsRs1(common->inst_word());
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kC3rs2, [common]() {
    auto num = Extractors::CS::ExtractCsRs2(common->inst_word());
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kCrd, [common]() {
    auto num = Extractors::CR::ExtractRd(common->inst_word());
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kCrs1, [common]() {
    auto num = Extractors::CR::ExtractRs1(common->inst_word());
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kCrs2, [common]() {
    auto num = Extractors::CR::ExtractRs2(common->inst_word());
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kICbImm8, [common]() {
    return new ImmediateOperand<int32_t>(
        Extractors::Inst16Format::ExtractBimm(common->inst_word()));
  });
  Insert(getter_map, *Enum::kICiImm6, [common]() {
    return new ImmediateOperand<int32_t>(
        Extractors::CI::ExtractImm6(common->inst_word()));
  });
  Insert(getter_map, *Enum::kICiImm6x16, [common]() {
    return new generic::ImmediateOperand<int32_t>(
        Extractors::Inst16Format::ExtractCiImm10(common->inst_word()));
  });
  Insert(getter_map, *Enum::kICiUimm6, [common]() {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractUimm6(common->inst_word()));
  });
  Insert(getter_map, *Enum::kICiUimm6x4, [common]() -> SourceOperandInterface* {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractCiImmW(common->inst_word()));
  });
  Insert(getter_map, *Enum::kICiwUimm8x4, [common]() {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractCiwImm10(common->inst_word()));
  });
  Insert(getter_map, *Enum::kICjImm11, [common]() {
    return new ImmediateOperand<int32_t>(
        Extractors::Inst16Format::ExtractJimm(common->inst_word()));
  });
  Insert(getter_map, *Enum::kIClUimm5x4, [common]() {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractClImmW(common->inst_word()));
  });
  Insert(getter_map, *Enum::kICssUimm6x4,
         [common]() -> SourceOperandInterface* {
           return new ImmediateOperand<uint32_t>(
               Extractors::Inst16Format::ExtractCssImmW(common->inst_word()));
         });
  Insert(getter_map, *Enum::kX0,
         []() { return new generic::IntLiteralOperand<0>({1}); });
  Insert(getter_map, *Enum::kX2, [common]() {
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, 2),
        kXRegisterAliases[2]);
  });
}

// Getters for Zca destination operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcaDestGetters(SourceOpGetterMap& getter_map,
                            RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kC3rd, [common](int latency) {
    int num = Extractors::CL::ExtractClRd(common->inst_word());
    return GetRegisterDestinationOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num), latency);
  });
}

// Getters for Zcb source operands (not covered in Zca).

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcbSourceGetters(SourceOpGetterMap& getter_map,
                              RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kUimm2b, [common]() {
    auto num = Extractors::CLB::ExtractUimm2(common->inst_word());
    return new ImmediateOperand<uint32_t>(num);
  });
  Insert(getter_map, *Enum::kUimm2h, [common](int latency) {
    auto num = Extractors::CLH::ExtractUimm2(common->inst_word());
    return new ImmediateOperand<uint32_t>(num);
  });
}

// Getters for Zcb destination operands (not covered in Zca).

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcbDestGetters(DestOpGetterMap& getter_map,
                            RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kC3rs2, [common](int latency) {
    int num = Extractors::CLB::ExtractClRd(common->inst_word());
    return GetRegisterDestinationOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num), latency);
  });
}

// Getters for Zcf source operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcfSourceGetters(SourceOpGetterMap& getter_map,
                              RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kC3frs2, [common]() {
    auto num = Extractors::CS::ExtractCsRs2(common->inst_word());
    return GetRegisterSourceOp<FpRegister>(
        common->state(), absl::StrCat(RiscVState::kFregPrefix, num),
        kFRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kC3rs1, [common]() {
    auto num = Extractors::CS::ExtractCsRs1(common->inst_word());
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kCfrs2, [common]() {
    auto num = Extractors::CR::ExtractRs2(common->inst_word());
    return GetRegisterSourceOp<FpRegister>(
        common->state(), absl::StrCat(RiscVState::kFregPrefix, num),
        kFRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kICiUimm6x4, [common]() -> SourceOperandInterface* {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractCiImmW(common->inst_word()));
  });
  Insert(getter_map, *Enum::kIClUimm5x4, [common]() {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractClImmW(common->inst_word()));
  });
  Insert(getter_map, *Enum::kICssUimm6x4, [common]() {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractCssImmW(common->inst_word()));
  });
  Insert(getter_map, *Enum::kX2, [common]() {
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, 2),
        kXRegisterAliases[2]);
  });
}

// Getters for Zcf destination operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcfDestGetters(DestOpGetterMap& getter_map,
                            RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kC3frd, [common](int latency) {
    int num = Extractors::CL::ExtractClRd(common->inst_word());
    return GetRegisterDestinationOp<FpRegister>(
        common->state(), absl::StrCat(RiscVState::kFregPrefix, num), latency);
  });
}

// Getters for Zcd source operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcdSourceGetters(SourceOpGetterMap& getter_map,
                              RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kC3drs2, [common]() {
    auto num = Extractors::CS::ExtractCsRs2(common->inst_word());
    return GetRegisterSourceOp<FpRegister>(
        common->state(), absl::StrCat(RiscVState::kFregPrefix, num),
        kFRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kC3rs1, [common]() {
    auto num = Extractors::CS::ExtractCsRs1(common->inst_word());
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kCdrs2, [common]() {
    auto num = Extractors::CR::ExtractRs2(common->inst_word());
    return GetRegisterSourceOp<FpRegister>(
        common->state(), absl::StrCat(RiscVState::kFregPrefix, num),
        kFRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kICiUimm6x8, [common]() -> SourceOperandInterface* {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractCiImmW(common->inst_word()));
  });
  Insert(getter_map, *Enum::kIClUimm5x8, [common]() {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractClImmW(common->inst_word()));
  });
  Insert(getter_map, *Enum::kICssUimm6x8, [common]() {
    return new ImmediateOperand<uint32_t>(
        Extractors::Inst16Format::ExtractCssImmW(common->inst_word()));
  });
  Insert(getter_map, *Enum::kX2, [common]() {
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, 2),
        kXRegisterAliases[2]);
  });
}

// Getters for Zcd destination operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcdDestGetters(DestOpGetterMap& getter_map,
                            RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kC3drd, [common](int latency) {
    int num = Extractors::CL::ExtractClRd(common->inst_word());
    return GetRegisterDestinationOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kFregPrefix, num), latency);
  });
}

// The following table maps Zcmp Sreg alias register numbers to Xreg numbers.
constexpr int kSRegToXRegMap[8] = {8, 9, 18, 19, 20, 21, 22, 23};

// Getters for Zcmp source operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcmpSourceGetters(SourceOpGetterMap& getter_map,
                               RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kRlist, [common]() {
    return new ImmediateOperand<uint32_t>(
        Extractors::CMMP::ExtractRlist(common->inst_word()));
  });
  Insert(getter_map, *Enum::kSpimm, [common]() {
    return new ImmediateOperand<uint32_t>(
        Extractors::CMMP::ExtractSpimm(common->inst_word()));
  });
  Insert(getter_map, *Enum::kSreg1, [common]() {
    int num =
        kSRegToXRegMap[Extractors::CMMV::ExtractRs1p(common->inst_word())];
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kSreg2, [common]() {
    int num =
        kSRegToXRegMap[Extractors::CMMV::ExtractRs2p(common->inst_word())];
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num),
        kXRegisterAliases[num]);
  });
  Insert(getter_map, *Enum::kX2, [common]() {
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, 2),
        kXRegisterAliases[2]);
  });
  Insert(getter_map, *Enum::kX10, [common]() {
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, 10),
        kXRegisterAliases[10]);
  });
  Insert(getter_map, *Enum::kX11, [common]() {
    return GetRegisterSourceOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, 11),
        kXRegisterAliases[11]);
  });
}

// Getters for Zcmp destination operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcmpDestGetters(DestOpGetterMap& getter_map,
                             RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kSreg1, [common](int latency) {
    int num =
        kSRegToXRegMap[Extractors::CMMV::ExtractRs1p(common->inst_word())];
    return GetRegisterDestinationOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num), latency);
  });
  Insert(getter_map, *Enum::kSreg2, [common](int latency) {
    int num =
        kSRegToXRegMap[Extractors::CMMV::ExtractRs2p(common->inst_word())];
    return GetRegisterDestinationOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, num), latency);
  });
  Insert(getter_map, *Enum::kX2, [common](int latency) {
    return GetRegisterDestinationOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, 2), latency);
  });
  Insert(getter_map, *Enum::kX10, [common](int latency) {
    return GetRegisterDestinationOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, 10), latency);
  });
  Insert(getter_map, *Enum::kX11, [common](int latency) {
    return GetRegisterDestinationOp<IntRegister>(
        common->state(), absl::StrCat(RiscVState::kXregPrefix, 11), latency);
  });
}

// Getters for Zcmp list source operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcmpListSourceGetters(ListSourceOpGetterMap& getter_map,
                                   RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kRlist, [common]() {
    std::vector<SourceOperandInterface*> result;
    int rlist = Extractors::CMMP::ExtractRlist(common->inst_word());
    // Get the value of 'rlist', and add source operands accordingly.
    if (rlist < 4) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x1"));
    if (rlist == 4) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x8"));
    if (rlist == 5) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x9"));
    if (rlist == 6) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x18"));
    if (rlist == 7) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x19"));
    if (rlist == 8) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x20"));
    if (rlist == 9) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x21"));
    if (rlist == 10) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x22"));
    if (rlist == 11) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x23"));
    if (rlist == 12) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x24"));
    if (rlist == 13) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x25"));
    if (rlist == 14) return result;
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x26"));
    result.push_back(GetRegisterSourceOp<IntRegister>(common->state(), "x27"));
    return result;
  });
}

// Getters for Zcmp list destination operands.

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcmpListDestGetters(ListDestOpGetterMap& getter_map,
                                 RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kRlist, [common](std::vector<int> latency) {
    std::vector<DestinationOperandInterface*> result;
    int rlist = Extractors::CMMP::ExtractRlist(common->inst_word());
    // Get the value of 'rlist', and add destination operands accordingly.
    int size = latency.size();
    if (rlist < 4) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x1", latency[result.size() % size]));
    if (rlist == 4) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x8", latency[result.size() % size]));
    if (rlist == 5) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x9", latency[result.size() % size]));
    if (rlist == 6) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x18", latency[result.size() % size]));
    if (rlist == 7) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x19", latency[result.size() % size]));
    if (rlist == 8) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x20", latency[result.size() % size]));
    if (rlist == 9) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x21", latency[result.size() % size]));
    if (rlist == 10) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x22", latency[result.size() % size]));
    if (rlist == 11) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x23", latency[result.size() % size]));
    if (rlist == 12) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x24", latency[result.size() % size]));
    if (rlist == 13) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x25", latency[result.size() % size]));
    if (rlist == 14) return result;
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x26", latency[result.size() % size]));
    result.push_back(GetRegisterDestinationOp<IntRegister>(
        common->state(), "x27", latency[result.size() % size]));
    return result;
  });
}

template <typename Enum, typename Extractors, typename IntRegister,
          typename FpRegister>
void AddRiscVZcmtSourceGetters(SourceOpGetterMap& getter_map,
                               RiscVEncodingCommon* common) {
  Insert(getter_map, *Enum::kJtIndex, [common](int latency) {
    int num = Extractors::CMJT::ExtractIndex(common->inst_word());
    return new ImmediateOperand<uint32_t>(num);
  });
}

}  // namespace mpact::sim::riscv

#endif  // THIRD_PARTY_MPACT_RISCV_RISCV_ZC_GETTERS_H_
