// Copyright 2023 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_RISCV_RISCV_VECTOR_INSTRUCTION_HELPERS_H_
#define THIRD_PARTY_MPACT_RISCV_RISCV_RISCV_VECTOR_INSTRUCTION_HELPERS_H_

#include <algorithm>
#include <cstdint>
#include <functional>
#include <limits>
#include <optional>
#include <tuple>

#include "absl/log/log.h"
#include "absl/strings/str_cat.h"
#include "cheriot/cheriot_vector_state.h"
#include "mpact/sim/generic/instruction.h"
#include "mpact/sim/generic/type_helpers.h"
#include "riscv//riscv_fp_host.h"
#include "riscv//riscv_fp_info.h"
#include "riscv//riscv_register.h"
#include "riscv//riscv_state.h"

namespace mpact {
namespace sim {
namespace cheriot {

using ::mpact::sim::cheriot::CheriotVectorState;
using ::mpact::sim::generic::FPTypeInfo;
using ::mpact::sim::generic::GetInstructionSource;
using ::mpact::sim::generic::Instruction;
using ::mpact::sim::riscv::FPExceptions;
using ::mpact::sim::riscv::RV32VectorDestinationOperand;
using ::mpact::sim::riscv::RV32VectorSourceOperand;
using ::mpact::sim::riscv::ScopedFPStatus;
using ::mpact::sim::riscv::VectorLoadContext;

// This helper function handles the case of instructions that target a vector
// mask.
// It clears the masked bit and uses the mask value in the
// instruction, such as carry generation from add with carry.
// Note that this function will modify masked bits no matter what the mask
// value is.
template <typename Vs2, typename Vs1>
void RiscVSetMaskBinaryVectorMaskOp(CheriotVectorState* rv_vector,
                                    const Instruction* inst,
                                    std::function<bool(Vs2, Vs1, bool)> op) {
  if (rv_vector->vector_exception()) return;
  auto* dest_op =
      static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
  // Get the vector start element index and compute where to start
  // the operation.
  const int num_elements = rv_vector->vector_length();
  const int vector_index = rv_vector->vstart();
  // Allocate data buffer for the new register data.
  auto* dest_db = dest_op->CopyDataBuffer();
  auto dest_span = dest_db->Get<uint8_t>();
  // Determine if it's vector-vector or vector-scalar.
  const bool vector_scalar = inst->Source(1)->shape()[0] == 1;
  // Get the vector mask.
  auto* mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(2));
  bool vm_unmasked_bit = false;
  if (inst->SourcesSize() > 3) {
    vm_unmasked_bit = GetInstructionSource<bool>(inst, 3);
  }
  const bool mask_used = !vm_unmasked_bit;
  auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
  for (int i = vector_index; i < num_elements; i++) {
    const int mask_index = i >> 3;
    const int mask_offset = i & 0b111;
    const bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1) != 0;
    const Vs2 vs2 = GetInstructionSource<Vs2>(inst, 0, i);
    const Vs1 vs1 = GetInstructionSource<Vs1>(inst, 1, vector_scalar ? 0 : i);

    // Clear the masked register bit.
    dest_span[mask_index] &= ~(1 << mask_offset);

    // Mask value is used only when `vm_unmasked_bit` is 0.
    dest_span[mask_index] |=
        (op(vs2, vs1, mask_used & mask_value) << mask_offset);
  }
  // Submit the destination db .
  dest_db->Submit();
  rv_vector->clear_vstart();
}

// This helper function handles the case of instructions that target a vector
// mask and uses the mask value in the instruction, such as carry generation
// from add with carry.
template <typename Vs2, typename Vs1>
void RiscVMaskBinaryVectorMaskOp(CheriotVectorState* rv_vector,
                                 const Instruction* inst,
                                 std::function<bool(Vs2, Vs1, bool)> op) {
  if (rv_vector->vector_exception()) return;
  auto* dest_op =
      static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
  // Get the vector start element index and compute where to start
  // the operation.
  int num_elements = rv_vector->vector_length();
  int vector_index = rv_vector->vstart();
  // Allocate data buffer for the new register data.
  auto* dest_db = dest_op->CopyDataBuffer();
  auto dest_span = dest_db->Get<uint8_t>();
  // Determine if it's vector-vector or vector-scalar.
  bool vector_scalar = inst->Source(1)->shape()[0] == 1;
  // Get the vector mask.
  auto* mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(2));
  bool vm_unmasked_bit = false;
  if (inst->SourcesSize() > 3) {
    vm_unmasked_bit = GetInstructionSource<bool>(inst, 3);
  }
  const bool mask_used = !vm_unmasked_bit;
  auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
  for (int i = vector_index; i < num_elements; i++) {
    int mask_index = i >> 3;
    int mask_offset = i & 0b111;
    bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1) != 0;
    if (mask_used && !mask_value) {
      continue;
    }

    Vs2 vs2 = GetInstructionSource<Vs2>(inst, 0, i);
    Vs1 vs1 = GetInstructionSource<Vs1>(inst, 1, vector_scalar ? 0 : i);

    // Clear the masked register bit.
    dest_span[mask_index] &= ~(1 << mask_offset);

    // Mask value is used only when `vm_unmasked_bit` is 0.
    dest_span[mask_index] |=
        (op(vs2, vs1, mask_used & mask_value) << mask_offset);
  }
  // Submit the destination db .
  dest_db->Submit();
  rv_vector->clear_vstart();
}

// This helper function handles the case of vector mask
// operations.
template <typename Vs2, typename Vs1>
void RiscVBinaryVectorMaskOp(CheriotVectorState* rv_vector,
                             const Instruction* inst,
                             std::function<bool(Vs2, Vs1)> op) {
  RiscVMaskBinaryVectorMaskOp<Vs2, Vs1>(
      rv_vector, inst, [op](Vs2 vs2, Vs1 vs1, bool mask_value) -> bool {
        if (mask_value) {
          return op(vs2, vs1);
        }
        return false;
      });
}

// This helper function handles the case of nullary vector
// operations. It implements all the checking necessary for both widening and
// narrowing operations.
template <typename Vd>
void RiscVMaskNullaryVectorOp(CheriotVectorState* rv_vector,
                              const Instruction* inst,
                              std::function<Vd(bool)> op) {
  if (rv_vector->vector_exception()) return;
  int num_elements = rv_vector->vector_length();
  int elements_per_vector =
      rv_vector->vector_register_byte_length() / sizeof(Vd);
  int max_regs = (num_elements + elements_per_vector - 1) / elements_per_vector;
  auto* dest_op =
      static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
  // Verify that there are enough registers in the destination operand.
  if (dest_op->size() < max_regs) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << absl::StrCat(
        "Vector destination '", dest_op->AsString(), "' has fewer registers (",
        dest_op->size(), ") than required by the operation (", max_regs, ")");
    return;
  }
  // There 2 types of instruction with different number of source operands.
  // 1. inst vd, vs2, vmask (viota instruction)
  // 2. inst vd, vmask (vid instruction)
  RV32VectorSourceOperand* vs2_op = nullptr;
  RV32VectorSourceOperand* mask_op = nullptr;
  if (inst->SourcesSize() > 1) {
    vs2_op = static_cast<RV32VectorSourceOperand*>(inst->Source(0));
    mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(1));
  } else {
    mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(0));
  }
  auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
  // Get the vector start element index and compute where to start
  // the operation.
  int vector_index = rv_vector->vstart();
  int start_reg = vector_index / elements_per_vector;
  int item_index = vector_index % elements_per_vector;
  // Iterate over the number of registers to write.
  for (int reg = start_reg; (reg < max_regs) && (vector_index < num_elements);
       reg++) {
    // Allocate data buffer for the new register data.
    auto* dest_db = dest_op->CopyDataBuffer(reg);
    auto dest_span = dest_db->Get<Vd>();
    // Write data into register subject to masking.
    int element_count = std::min(elements_per_vector, num_elements);
    for (int i = item_index;
         (i < element_count) && (vector_index < num_elements); i++) {
      // Get the mask value.
      int mask_index = vector_index >> 3;
      int mask_offset = vector_index & 0b111;
      bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1) != 0;
      bool operation_mask = mask_value;
      // Instruction with rs2 operand checks vs2 bit value.
      if (vs2_op != nullptr) {
        const auto rs2_span =
            vs2_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
        const bool rs2_value = ((rs2_span[mask_index] >> mask_offset) & 0b1);
        // If rs2 is set, then the operation is performed.
        operation_mask &= rs2_value;
      }

      auto result = op(operation_mask);
      if (mask_value) {
        dest_span[i] = result;
      }
      vector_index++;
    }
    // Submit the destination db .
    dest_db->Submit();
    item_index = 0;
  }
  rv_vector->clear_vstart();
}

// This helper function handles the case of unary vector
// operations. It implements all the checking necessary for both widening and
// narrowing operations.
template <typename Vd, typename Vs2>
void RiscVUnaryVectorOp(CheriotVectorState* rv_vector, const Instruction* inst,
                        std::function<Vd(Vs2)> op) {
  if (rv_vector->vector_exception()) return;
  int num_elements = rv_vector->vector_length();
  int lmul = rv_vector->vector_length_multiplier();
  int sew = rv_vector->selected_element_width();
  int lmul_vd = lmul * sizeof(Vd) / sew;
  int lmul_vs2 = lmul * sizeof(Vs2) / sew;
  if (lmul_vd > 64 || lmul_vd == 0) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul value vd (" << lmul_vd << ")";
    return;
  }
  if (lmul_vs2 > 64 || lmul_vs2 == 0) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul_value vs2 (" << lmul_vs2 << ")";
    return;
  }
  int elements_per_vector =
      rv_vector->vector_register_byte_length() / sizeof(Vd);
  int max_regs = (num_elements + elements_per_vector - 1) / elements_per_vector;
  auto* dest_op =
      static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
  // Verify that there are enough registers in the destination operand.
  if (dest_op->size() < max_regs) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << absl::StrCat(
        "Vector destination '", dest_op->AsString(), "' has fewer registers (",
        dest_op->size(), ") than required by the operation (", max_regs, ")");
    return;
  }
  // Get the vector mask.
  auto* mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(1));
  auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
  // Get the vector start element index and compute where to start
  // the operation.
  int vector_index = rv_vector->vstart();
  int start_reg = vector_index / elements_per_vector;
  int item_index = vector_index % elements_per_vector;
  // Iterate over the number of registers to write.
  for (int reg = start_reg; (reg < max_regs) && (vector_index < num_elements);
       reg++) {
    // Allocate data buffer for the new register data.
    auto* dest_db = dest_op->CopyDataBuffer(reg);
    auto dest_span = dest_db->Get<Vd>();
    // Write data into register subject to masking.
    int element_count = std::min(elements_per_vector, num_elements);
    for (int i = item_index;
         (i < element_count) && (vector_index < num_elements); i++) {
      // Get the mask value.
      int mask_index = vector_index >> 3;
      int mask_offset = vector_index & 0b111;
      bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1) != 0;
      if (mask_value) {
        // Compute result.
        Vs2 vs2 = GetInstructionSource<Vs2>(inst, 0, vector_index);
        dest_span[i] = op(vs2);
      }
      vector_index++;
    }
    // Submit the destination db .
    dest_db->Submit();
    item_index = 0;
  }
  rv_vector->clear_vstart();
}

// This helper function handles the case of unary vector operations that set
// fflags. It implements all the checking necessary for both widening and
// narrowing operations.
template <typename Vd, typename Vs2>
void RiscVUnaryVectorOpWithFflags(
    CheriotVectorState* rv_vector, const Instruction* inst,
    std::function<std::tuple<Vd, uint32_t>(Vs2)> op) {
  if (rv_vector->vector_exception()) return;
  int num_elements = rv_vector->vector_length();
  int lmul = rv_vector->vector_length_multiplier();
  int sew = rv_vector->selected_element_width();
  int lmul_vd = lmul * sizeof(Vd) / sew;
  int lmul_vs2 = lmul * sizeof(Vs2) / sew;
  if (lmul_vd > 64 || lmul_vd == 0) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul value vd (" << lmul_vd << ")";
    return;
  }
  if (lmul_vs2 > 64 || lmul_vs2 == 0) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul_value vs2 (" << lmul_vs2 << ")";
    return;
  }
  int elements_per_vector =
      rv_vector->vector_register_byte_length() / sizeof(Vd);
  int max_regs = (num_elements + elements_per_vector - 1) / elements_per_vector;
  auto* dest_op =
      static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
  // Verify that there are enough registers in the destination operand.
  if (dest_op->size() < max_regs) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << absl::StrCat(
        "Vector destination '", dest_op->AsString(), "' has fewer registers (",
        dest_op->size(), ") than required by the operation (", max_regs, ")");
    return;
  }
  // Get the vector mask.
  auto* mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(1));
  auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
  // Get the vector start element index and compute where to start
  // the operation.
  int vector_index = rv_vector->vstart();
  int start_reg = vector_index / elements_per_vector;
  int item_index = vector_index % elements_per_vector;
  // Iterate over the number of registers to write.
  uint32_t fflags = 0;
  for (int reg = start_reg; (reg < max_regs) && (vector_index < num_elements);
       reg++) {
    // Allocate data buffer for the new register data.
    auto* dest_db = dest_op->CopyDataBuffer(reg);
    auto dest_span = dest_db->Get<Vd>();
    // Write data into register subject to masking.
    int element_count = std::min(elements_per_vector, num_elements);
    for (int i = item_index;
         (i < element_count) && (vector_index < num_elements); i++) {
      // Get the mask value.
      int mask_index = vector_index >> 3;
      int mask_offset = vector_index & 0b111;
      bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1) != 0;
      if (mask_value) {
        // Compute result.
        Vs2 vs2 = GetInstructionSource<Vs2>(inst, 0, vector_index);
        auto [value, flag] = op(vs2);
        dest_span[i] = value;
        fflags |= flag;
      }
      vector_index++;
    }
    // Submit the destination db .
    dest_db->Submit();
    item_index = 0;
  }
  auto* flag_db = inst->Destination(1)->AllocateDataBuffer();
  flag_db->Set<uint32_t>(0, fflags);
  flag_db->Submit();
  rv_vector->clear_vstart();
}

// This helper function handles the case of mask + two source operand vector
// operations. It implements all the checking necessary for both widening and
// narrowing operations.
template <typename Vd, typename Vs2, typename Vs1>
void RiscVMaskBinaryVectorOp(
    CheriotVectorState* rv_vector, const Instruction* inst,
    std::function<std::optional<Vd>(Vs2, Vs1, bool)> op) {
  if (rv_vector->vector_exception()) return;
  int num_elements = rv_vector->vector_length();
  int lmul = rv_vector->vector_length_multiplier();
  int sew = rv_vector->selected_element_width();
  int lmul_vd = lmul * sizeof(Vd) / sew;
  int lmul_vs2 = lmul * sizeof(Vs2) / sew;
  int lmul_vs1 = lmul * sizeof(Vs1) / sew;
  if (lmul_vd > 64 || lmul_vs2 > 64 || lmul_vs1 > 64) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul value";
    return;
  }
  if (lmul_vd == 0 || lmul_vs2 == 0 || lmul_vs1 == 0) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul_value";
    return;
  }
  int elements_per_vector =
      rv_vector->vector_register_byte_length() / sizeof(Vd);
  int max_regs = (num_elements + elements_per_vector - 1) / elements_per_vector;
  auto* dest_op =
      static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
  // Verify that there are enough registers in the destination operand.
  if (dest_op->size() < max_regs) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << absl::StrCat(
        "Vector destination '", dest_op->AsString(), "' has fewer registers (",
        dest_op->size(), ") than required by the operation (", max_regs, ")");
    return;
  }
  // Get the vector mask.
  auto* mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(2));
  auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
  // Get the vector start element index and compute where to start
  // the operation.
  int vector_index = rv_vector->vstart();
  int start_reg = vector_index / elements_per_vector;
  int item_index = vector_index % elements_per_vector;
  // Determine if it's vector-vector or vector-scalar.
  bool vector_scalar = inst->Source(1)->shape()[0] == 1;
  // Iterate over the number of registers to write.
  bool exception = false;
  for (int reg = start_reg;
       !exception && (reg < max_regs) && (vector_index < num_elements); reg++) {
    // Allocate data buffer for the new register data.
    auto* dest_db = dest_op->CopyDataBuffer(reg);
    auto dest_span = dest_db->Get<Vd>();
    // Write data into register subject to masking.
    int element_count = std::min(elements_per_vector, num_elements);
    for (int i = item_index;
         (i < element_count) && (vector_index < num_elements); i++) {
      // Get the mask value.
      int mask_index = vector_index >> 3;
      int mask_offset = vector_index & 0b111;
      bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1) != 0;
      // Compute result.
      Vs2 vs2 = GetInstructionSource<Vs2>(inst, 0, vector_index);
      Vs1 vs1 = GetInstructionSource<Vs1>(inst, 1,
                                          (vector_scalar ? 0 : vector_index));
      auto value = op(vs2, vs1, mask_value);
      if (value.has_value()) {
        dest_span[i] = value.value();
      } else if (mask_value) {
        // If there is no value returned, but the mask_value is true, check
        // to see if there was an exception.
        if (rv_vector->vector_exception()) {
          rv_vector->set_vstart(vector_index);
          exception = true;
          break;
        }
      }
      vector_index++;
    }
    // Submit the destination db .
    dest_db->Submit();
    item_index = 0;
  }
  rv_vector->clear_vstart();
}

// This helper function handles the case of two source operand vector
// operations. It implements all the checking necessary for both widening and
// narrowing operations.
template <typename Vd, typename Vs2, typename Vs1>
void RiscVBinaryVectorOp(CheriotVectorState* rv_vector, const Instruction* inst,
                         std::function<Vd(Vs2, Vs1)> op) {
  RiscVMaskBinaryVectorOp<Vd, Vs2, Vs1>(
      rv_vector, inst,
      [op](Vs2 vs2, Vs1 vs1, bool mask_value) -> std::optional<Vd> {
        if (mask_value) {
          return op(vs2, vs1);
        }
        return std::nullopt;
      });
}

template <typename Vd, typename Vs2, typename Vs1>
void RiscVBinaryVectorOpWithFflags(
    CheriotVectorState* rv_vector, const Instruction* inst,
    std::function<std::tuple<Vd, uint32_t>(Vs2, Vs1)> op) {
  if (rv_vector->vector_exception()) return;
  int num_elements = rv_vector->vector_length();
  int lmul = rv_vector->vector_length_multiplier();
  int sew = rv_vector->selected_element_width();
  int lmul_vd = lmul * sizeof(Vd) / sew;
  int lmul_vs2 = lmul * sizeof(Vs2) / sew;
  int lmul_vs1 = lmul * sizeof(Vs1) / sew;
  if (lmul_vd > 64 || lmul_vs2 > 64 || lmul_vs1 > 64) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul value";
    return;
  }
  if (lmul_vd == 0 || lmul_vs2 == 0 || lmul_vs1 == 0) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul_value";
    return;
  }
  int elements_per_vector =
      rv_vector->vector_register_byte_length() / sizeof(Vd);
  int max_regs = (num_elements + elements_per_vector - 1) / elements_per_vector;
  auto* dest_op =
      static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
  // Verify that there are enough registers in the destination operand.
  if (dest_op->size() < max_regs) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << absl::StrCat(
        "Vector destination '", dest_op->AsString(), "' has fewer registers (",
        dest_op->size(), ") than required by the operation (", max_regs, ")");
    return;
  }
  // Get the vector mask.
  auto* mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(2));
  auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
  // Get the vector start element index and compute where to start
  // the operation.
  int vector_index = rv_vector->vstart();
  int start_reg = vector_index / elements_per_vector;
  int item_index = vector_index % elements_per_vector;
  // Determine if it's vector-vector or vector-scalar.
  bool vector_scalar = inst->Source(1)->shape()[0] == 1;
  // Iterate over the number of registers to write.
  bool exception = false;
  uint32_t fflags = 0;
  for (int reg = start_reg;
       !exception && (reg < max_regs) && (vector_index < num_elements); reg++) {
    // Allocate data buffer for the new register data.
    auto* dest_db = dest_op->CopyDataBuffer(reg);
    auto dest_span = dest_db->Get<Vd>();
    // Write data into register subject to masking.
    int element_count = std::min(elements_per_vector, num_elements);
    for (int i = item_index;
         (i < element_count) && (vector_index < num_elements); i++) {
      // Get the mask value.
      int mask_index = vector_index >> 3;
      int mask_offset = vector_index & 0b111;
      bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1) != 0;
      // Compute result.
      Vs2 vs2 = GetInstructionSource<Vs2>(inst, 0, vector_index);
      Vs1 vs1 = GetInstructionSource<Vs1>(inst, 1,
                                          (vector_scalar ? 0 : vector_index));
      if (mask_value) {
        auto [value, flag] = op(vs2, vs1);
        dest_span[i] = value;
        fflags |= flag;
        if (rv_vector->vector_exception()) {
          rv_vector->set_vstart(vector_index);
          exception = true;
          break;
        }
      }
      vector_index++;
    }
    // Submit the destination dbs.
    dest_db->Submit();
    item_index = 0;
  }
  auto* flag_db = inst->Destination(1)->AllocateDataBuffer();
  flag_db->Set<uint32_t>(0, fflags);
  flag_db->Submit();
  rv_vector->clear_vstart();
}

// This helper function handles three source operand vector operations. It
// implements all the checking necessary for both widening and narrowing
// operations.
template <typename Vd, typename Vs2, typename Vs1>
void RiscVTernaryVectorOp(CheriotVectorState* rv_vector,
                          const Instruction* inst,
                          std::function<Vd(Vs2, Vs1, Vd)> op) {
  if (rv_vector->vector_exception()) return;
  int num_elements = rv_vector->vector_length();
  int lmul = rv_vector->vector_length_multiplier();
  int sew = rv_vector->selected_element_width();
  int lmul_vd = lmul * sizeof(Vd) / sew;
  int lmul_vs2 = lmul * sizeof(Vs2) / sew;
  int lmul_vs1 = lmul * sizeof(Vs1) / sew;
  if (lmul_vd > 64 || lmul_vs2 > 64 || lmul_vs1 > 64) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul value";
    return;
  }
  if (lmul_vd == 0 || lmul_vs2 == 0 || lmul_vs1 == 0) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul_value";
    return;
  }
  int elements_per_vector =
      rv_vector->vector_register_byte_length() / sizeof(Vd);
  int max_regs = (num_elements + elements_per_vector - 1) / elements_per_vector;
  auto* dest_op =
      static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
  // Verify that there are enough registers in the destination operand.
  if (dest_op->size() < max_regs) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << absl::StrCat(
        "Vector destination '", dest_op->AsString(), "' has fewer registers (",
        dest_op->size(), ") than required by the operation (", max_regs, ")");
    return;
  }
  // Get the vector mask.
  auto* mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(3));
  auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
  // Get the vector start element index and compute where to start
  // the operation.
  int vector_index = rv_vector->vstart();
  int start_reg = vector_index / elements_per_vector;
  int item_index = vector_index % elements_per_vector;
  // Determine if it's vector-vector or vector-scalar.
  bool vector_scalar = inst->Source(1)->shape()[0] == 1;
  // Iterate over the number of registers to write.
  for (int reg = start_reg; (reg < max_regs) && (vector_index < num_elements);
       reg++) {
    // Allocate data buffer for the new register data.
    auto* dest_db = dest_op->CopyDataBuffer(reg);
    auto dest_span = dest_db->Get<Vd>();
    // Write data into register subject to masking.
    int element_count = std::min(elements_per_vector, num_elements);
    for (int i = item_index;
         (i < element_count) && (vector_index < num_elements); i++) {
      // Get the mask value.
      int mask_index = vector_index >> 3;
      int mask_offset = vector_index & 0b111;
      bool mask_value = ((mask_span[mask_index] >> mask_offset) & 0b1) != 0;
      // Compute result.
      Vs2 vs2 = GetInstructionSource<Vs2>(inst, 0, vector_index);
      Vs1 vs1 = GetInstructionSource<Vs1>(inst, 1,
                                          (vector_scalar ? 0 : vector_index));
      Vd vd = GetInstructionSource<Vd>(inst, 2, vector_index);
      if (mask_value) {
        dest_span[i] = op(vs2, vs1, vd);
      }
      vector_index++;
    }
    // Submit the destination db .
    dest_db->Submit();
    item_index = 0;
  }
  rv_vector->clear_vstart();
}

// The reduction instructions take Vs1[0], and all the elements (subject to
// masking) from Vs2 and apply the reduction operation to produce a single
// element that is written to Vd[0].
template <typename Vd, typename Vs2, typename Vs1>
void RiscVBinaryReductionVectorOp(CheriotVectorState* rv_vector,
                                  const Instruction* inst,
                                  std::function<Vd(Vd, Vs2)> op) {
  if (rv_vector->vector_exception()) return;
  if (rv_vector->vstart()) {
    rv_vector->vector_exception();
    return;
  }
  int sew = rv_vector->selected_element_width();
  int lmul = rv_vector->vector_length_multiplier();
  int lmul_vd = lmul * sizeof(Vd) / sew;
  int lmul_vs2 = lmul * sizeof(Vs2) / sew;
  int lmul_vs1 = lmul * sizeof(Vs1) / sew;
  if (lmul_vd > 64 || lmul_vs2 > 64 || lmul_vs1 > 64) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul value";
    return;
  }
  if (lmul_vd == 0 || lmul_vs2 == 0 || lmul_vs1 == 0) {
    rv_vector->set_vector_exception();
    LOG(ERROR) << "Illegal lmul_value";
    return;
  }
  int num_elements = rv_vector->vector_length();
  // Get the vector mask.
  auto* mask_op = static_cast<RV32VectorSourceOperand*>(inst->Source(2));
  auto mask_span = mask_op->GetRegister(0)->data_buffer()->Get<uint8_t>();
  Vd accumulator =
      static_cast<Vd>(generic::GetInstructionSource<Vs1>(inst, 1, 0));
  for (int i = 0; i < num_elements; i++) {
    int mask_index = i >> 3;
    int mask_offset = i & 0b111;
    bool mask_value = (mask_span[mask_index] >> mask_offset) & 0b1;
    if (mask_value) {
      accumulator =
          op(accumulator, generic::GetInstructionSource<Vs2>(inst, 0, i));
    }
  }
  auto* dest_op =
      static_cast<RV32VectorDestinationOperand*>(inst->Destination(0));
  auto dest_db = dest_op->CopyDataBuffer();
  dest_db->Set<Vd>(0, accumulator);
  dest_db->Submit();
  rv_vector->clear_vstart();
}

template <typename T>
T GetRoundingBit(int rounding_mode, T rounding_bits, int size) {
  switch (rounding_mode) {
    case 0:  // Round-to-nearest-up (add +0.5 lsb)
      if (size < 2) return 0;
      return (rounding_bits >> (size - 2)) & 0b1;
    case 1: {  // Round-to-nearest-event
      T v_d_minus_1 = (size < 2) ? 0 : (rounding_bits >> (size - 2)) & 0b1;
      T v_d = (size == 0) ? 0 : (rounding_bits >> (size - 1)) & 0b1;
      T v_d_minus_2_0 = (size < 3)
                            ? 0
                            : (rounding_bits & ~(std::numeric_limits<T>::max()
                                                 << (size - 2))) != 0;
      return v_d_minus_1 & (v_d_minus_2_0 | v_d);
    }
    case 2:  // Round-down (truncate).
      return 0;
    case 3: {  // Round-to-odd.
      T v_d_minus_1_0 = (size < 2)
                            ? 0
                            : (rounding_bits & ~(std::numeric_limits<T>::max()
                                                 << (size - 1))) != 0;
      T v_d = (rounding_bits >> (size - 1)) & 0b1;
      return (!v_d) & v_d_minus_1_0;
    }
    default:
      LOG(ERROR) << "GetRoundingBit: Invalid value for rounding mode";
      break;
  }
  return 0;
}

template <typename T>
T RoundOff(CheriotVectorState* rv_vector, T value, int size) {
  auto rm = rv_vector->vxrm();
  auto ret = (value >> size) + GetRoundingBit<T>(rm, value, size + 1);
  return ret;
}

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

#endif  // THIRD_PARTY_MPACT_RISCV_RISCV_RISCV_VECTOR_INSTRUCTION_HELPERS_H_
