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

#ifndef MPACT_CHERIOT_CHERIOT_RVV_GETTERS_H_
#define MPACT_CHERIOT_CHERIOT_RVV_GETTERS_H_

#include <cstdint>

#include "absl/container/flat_hash_map.h"
#include "absl/functional/any_invocable.h"
#include "cheriot/cheriot_getter_helpers.h"
#include "cheriot/cheriot_state.h"
#include "cheriot/cheriot_vector_true_operand.h"
#include "cheriot/riscv_cheriot_encoding_common.h"
#include "mpact/sim/generic/immediate_operand.h"
#include "mpact/sim/generic/literal_operand.h"
#include "mpact/sim/generic/operand_interface.h"
#include "riscv//riscv_register.h"

namespace mpact {
namespace sim {
namespace cheriot {

using ::mpact::sim::cheriot::RiscVCheriotEncodingCommon;
using ::mpact::sim::generic::DestinationOperandInterface;
using ::mpact::sim::generic::ImmediateOperand;
using ::mpact::sim::generic::IntLiteralOperand;
using ::mpact::sim::generic::SourceOperandInterface;
using ::mpact::sim::riscv::RV32VectorTrueOperand;
using ::mpact::sim::riscv::RVVectorRegister;

using SourceOpGetterMap =
    absl::flat_hash_map<int, absl::AnyInvocable<SourceOperandInterface*()>>;
using DestOpGetterMap =
    absl::flat_hash_map<int,
                        absl::AnyInvocable<DestinationOperandInterface*(int)>>;

template <typename Enum, typename Extractors>
void AddCheriotRVVSourceGetters(SourceOpGetterMap& getter_map,
                                RiscVCheriotEncodingCommon* common) {
  Insert(getter_map, *Enum::kConst1, []() -> SourceOperandInterface* {
    return new IntLiteralOperand<1>();
  });
  Insert(getter_map, *Enum::kConst2, []() -> SourceOperandInterface* {
    return new IntLiteralOperand<2>();
  });
  Insert(getter_map, *Enum::kConst4, []() -> SourceOperandInterface* {
    return new IntLiteralOperand<4>();
  });
  Insert(getter_map, *Enum::kConst8, []() -> SourceOperandInterface* {
    return new IntLiteralOperand<8>();
  });
  Insert(getter_map, *Enum::kNf, [common]() -> SourceOperandInterface* {
    auto imm = Extractors::VMem::ExtractNf(common->inst_word());
    return new ImmediateOperand<uint32_t>(imm);
  });
  Insert(getter_map, *Enum::kSimm5, [common]() -> SourceOperandInterface* {
    auto imm = Extractors::VArith::ExtractSimm5(common->inst_word());
    return new ImmediateOperand<uint32_t>(imm);
  });
  Insert(getter_map, *Enum::kUimm5, [common]() -> SourceOperandInterface* {
    auto imm = Extractors::VArith::ExtractUimm5(common->inst_word());
    return new ImmediateOperand<int32_t>(imm);
  });
  Insert(getter_map, *Enum::kVd, [common]() -> SourceOperandInterface* {
    auto num = Extractors::VArith::ExtractVd(common->inst_word());
    return GetVectorRegisterSourceOp<RVVectorRegister>(common->state(), num);
  });
  Insert(getter_map, *Enum::kVm, [common]() -> SourceOperandInterface* {
    auto vm = Extractors::VArith::ExtractVm(common->inst_word());
    return new ImmediateOperand<uint32_t>(vm);
  });
  Insert(getter_map, *Enum::kVmask, [common]() -> SourceOperandInterface* {
    auto vm = Extractors::VArith::ExtractVm(common->inst_word());
    if (vm == 1) {
      // Unmasked, return the True mask.
      return new CheriotVectorTrueOperand(common->state());
    }
    // Masked. Return the mask register.
    return GetVectorMaskRegisterSourceOp<RVVectorRegister>(common->state(), 0);
  });
  Insert(getter_map, *Enum::kVmaskTrue, [common]() -> SourceOperandInterface* {
    return new CheriotVectorTrueOperand(common->state());
  });
  Insert(getter_map, *Enum::kVs1, [common]() -> SourceOperandInterface* {
    auto num = Extractors::VArith::ExtractVs1(common->inst_word());
    return GetVectorRegisterSourceOp<RVVectorRegister>(common->state(), num);
  });
  Insert(getter_map, *Enum::kVs2, [common]() -> SourceOperandInterface* {
    auto num = Extractors::VArith::ExtractVs2(common->inst_word());
    return GetVectorRegisterSourceOp<RVVectorRegister>(common->state(), num);
  });
  Insert(getter_map, *Enum::kVs3, [common]() -> SourceOperandInterface* {
    auto num = Extractors::VMem::ExtractVs3(common->inst_word());
    return GetVectorRegisterSourceOp<RVVectorRegister>(common->state(), num);
  });
  Insert(getter_map, *Enum::kZimm10, [common]() -> SourceOperandInterface* {
    auto imm = Extractors::VConfig::ExtractZimm10(common->inst_word());
    return new ImmediateOperand<uint32_t>(imm);
  });
  Insert(getter_map, *Enum::kZimm11, [common]() -> SourceOperandInterface* {
    auto imm = Extractors::VConfig::ExtractZimm11(common->inst_word());
    return new ImmediateOperand<uint32_t>(imm);
  });
}

template <typename Enum, typename Extractors>
void AddCheriotRVVDestGetters(DestOpGetterMap& getter_map,
                              RiscVCheriotEncodingCommon* common) {
  Insert(getter_map, Enum::kVd,
         [common](int latency) -> DestinationOperandInterface* {
           auto num = Extractors::VArith::ExtractVd(common->inst_word());
           return GetVectorRegisterDestinationOp<RVVectorRegister>(
               common->state(), latency, num);
         });
}

}  // namespace cheriot
}  // namespace sim
}  // namespace mpact

#endif  // MPACT_CHERIOT_CHERIOT_RVV_GETTERS_H_
