// 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
//
//     http://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 "cheriot/cheriot_rvv_fp_decoder.h"

#include <cstdint>
#include <string>

#include "cheriot/cheriot_state.h"
#include "cheriot/riscv_cheriot_rvv_fp_decoder.h"
#include "cheriot/riscv_cheriot_rvv_fp_encoding.h"
#include "cheriot/riscv_cheriot_rvv_fp_enums.h"
#include "mpact/sim/generic/instruction.h"
#include "mpact/sim/generic/type_helpers.h"
#include "mpact/sim/util/memory/memory_interface.h"
#include "riscv//riscv_state.h"

namespace mpact {
namespace sim {
namespace cheriot {

using RV_EC = ::mpact::sim::riscv::ExceptionCode;

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

CheriotRVVFPDecoder::CheriotRVVFPDecoder(CheriotState *state,
                                         util::MemoryInterface *memory)
    : state_(state), memory_(memory) {
  // Need a data buffer to load instructions from memory. Allocate a single
  // buffer that can be reused for each instruction word.
  inst_db_ = db_factory_.Allocate<uint32_t>(1);
  // Allocate the isa factory class, the top level isa decoder instance, and
  // the encoding parser.
  cheriot_rvv_fp_isa_factory_ = new CheriotRVVFPIsaFactory();
  cheriot_rvv_fp_isa_ = new isa32_rvv_fp::RiscVCheriotRVVFpInstructionSet(
      state, cheriot_rvv_fp_isa_factory_);
  cheriot_rvv_fp_encoding_ = new isa32_rvv_fp::RiscVCheriotRVVFPEncoding(state);
}

CheriotRVVFPDecoder::~CheriotRVVFPDecoder() {
  delete cheriot_rvv_fp_isa_;
  delete cheriot_rvv_fp_isa_factory_;
  delete cheriot_rvv_fp_encoding_;
  inst_db_->DecRef();
}

generic::Instruction *CheriotRVVFPDecoder::DecodeInstruction(uint64_t address) {
  // First check that the address is aligned properly. If not, create and return
  // an instruction object that will raise an exception.
  if (address & 0x1) {
    auto *inst = new generic::Instruction(0, state_);
    inst->set_size(1);
    inst->SetDisassemblyString("Misaligned instruction address");
    inst->set_opcode(*isa32_rvv_fp::OpcodeEnum::kNone);
    inst->set_address(address);
    inst->set_semantic_function([this](generic::Instruction *inst) {
      state_->Trap(/*is_interrupt*/ false, inst->address(),
                   *RV_EC::kInstructionAddressMisaligned, inst->address() ^ 0x1,
                   inst);
    });
    return inst;
  }

  // If the address is greater than the max address, return an instruction
  // that will raise an exception.
  if (address > state_->max_physical_address()) {
    auto *inst = new generic::Instruction(0, state_);
    inst->set_size(0);
    inst->SetDisassemblyString("Instruction access fault");
    inst->set_opcode(*isa32_rvv_fp::OpcodeEnum::kNone);
    inst->set_address(address);
    inst->set_semantic_function([this](generic::Instruction *inst) {
      state_->Trap(/*is_interrupt*/ false, inst->address(),
                   *RV_EC::kInstructionAccessFault, inst->address(), nullptr);
    });
    return inst;
  }

  // Read the instruction word from memory and parse it in the encoding parser.
  memory_->Load(address, inst_db_, nullptr, nullptr);
  uint32_t iword = inst_db_->Get<uint32_t>(0);
  cheriot_rvv_fp_encoding_->ParseInstruction(iword);

  // Call the isa decoder to obtain a new instruction object for the instruction
  // word that was parsed above.
  auto *instruction =
      cheriot_rvv_fp_isa_->Decode(address, cheriot_rvv_fp_encoding_);
  return instruction;
}

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