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

#include <cstdint>

#include "absl/log/log.h"
#include "absl/status/status.h"
#include "mpact/sim/generic/data_buffer.h"
#include "mpact/sim/generic/decoder_interface.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_csr.h"
#include "riscv/riscv_state.h"

#ifndef THIRD_PARTY_MPACT_RISCV_RISCV_GENERIC_DECODER_H_
#define THIRD_PARTY_MPACT_RISCV_RISCV_GENERIC_DECODER_H_

namespace mpact::sim::riscv {

using ::mpact::sim::generic::operator*;  // NOLINT: clang-tidy false positive.

using ::mpact::sim::generic::Instruction;

template <typename State, typename OpcodeEnum, typename Encoding, typename Isa>
class RiscVGenericDecoder {
 public:
  RiscVGenericDecoder(State* state, util::MemoryInterface* memory,
                      Encoding* encoding, Isa* isa)
      : state_(state), memory_(memory), encoding_(encoding), isa_(isa) {
    auto res =
        state_->csr_set()->GetCsr(static_cast<uint64_t>(RiscVCsrEnum::kMIsa));
    if (res.ok()) {
      isa_csr_ = res.value();
    } else {
      isa_csr_ = nullptr;
      LOG(FATAL) << "Failed to get misa CSR: " << res.status();
    }

    // Need a data buffer to load instructions from memory. Allocate a single
    // buffer that can be reused for each instruction word.
    inst_db_ = state_->db_factory()->Allocate<uint32_t>(1);
  }

  ~RiscVGenericDecoder() { inst_db_->DecRef(); }

  Instruction* DecodeInstruction(uint64_t address) {
    Instruction* instruction = nullptr;
    auto status = CheckAddress(address, instruction);
    if (!status.ok()) {
      LOG(FATAL) << "Decoder error check failed.";
      return nullptr;
    }
    if (instruction != nullptr) return instruction;

    // 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);
    encoding_->ParseInstruction(iword);

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

 private:
  // Check that the address is valid. If not, return an instruction object that
  // will raise an exception.
  absl::Status CheckAddress(uint64_t address, Instruction*& inst) {
    if (isa_csr_ == nullptr) {
      return absl::InvalidArgumentError("MISA CSR is null");
    }
    if (inst != nullptr) {
      return absl::InvalidArgumentError("Instruction is not null");
    }
    // First check that the address is aligned properly. If not, create and
    // return an instruction object that will raise an exception.
    if (address & 0x1) {
      inst = new generic::Instruction(0, state_);
      inst->set_size(1);
      inst->SetDisassemblyString("Misaligned instruction address");
      inst->set_opcode(*OpcodeEnum::kNone);
      inst->set_address(address);
      inst->set_semantic_function([this](generic::Instruction* inst) {
        state_->Trap(/*is_interrupt*/ false, inst->address(),
                     *ExceptionCode::kInstructionAddressMisaligned,
                     inst->address() ^ 0x1, inst);
      });
      return absl::OkStatus();
    }

    // If the C extension is not supported and the address is not 4 byte
    // aligned, return an instruction that will raise an exception.
    if (((isa_csr_->GetUint64() &
          static_cast<uint64_t>(IsaExtensions::kCompressed)) == 0) &&
        (address & 0x3)) {
      inst = new generic::Instruction(0, state_);
      inst->set_size(1);
      inst->SetDisassemblyString("Misaligned instruction address");
      inst->set_opcode(*OpcodeEnum::kNone);
      inst->set_address(address);
      inst->set_semantic_function([this](generic::Instruction* inst) {
        state_->Trap(/*is_interrupt*/ false, inst->address(),
                     *ExceptionCode::kInstructionAddressMisaligned,
                     inst->address() & ~0x3, inst);
      });
      return absl::OkStatus();
    }

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

    return absl::OkStatus();
  }

  RiscVState* state_;
  util::MemoryInterface* memory_;
  Encoding* encoding_;
  Isa* isa_;
  generic::DataBuffer* inst_db_;
  RiscVCsrInterface* isa_csr_;
};

}  // namespace mpact::sim::riscv

#endif  // THIRD_PARTY_MPACT_RISCV_RISCV_GENERIC_DECODER_H_
