// 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/riscv_cheriot_a_instructions.h"

#include <cstdint>

#include "absl/status/status.h"
#include "cheriot/cheriot_state.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 ::mpact::sim::generic::operator*;  // NOLINT: is used below (clang error).

// This file contains the definitions of the semantic functions for the A, or
// atomic, subset of the RiscV architecture. Each semantic function calls the
// helper function which does all the heavy lifting.

using Operation = util::AtomicMemoryOpInterface::Operation;
using RV_EC = ::mpact::sim::riscv::ExceptionCode;

// Helper function for the atomic memory operation semantic functions.
template <typename T>
static inline void AInstructionHelper(Instruction* inst, Operation op,
                                      bool has_store_value) {
  auto* state = static_cast<CheriotState*>(inst->state());
  auto* atomic = state->atomic_tagged_memory();
  // If the atomic memory operation interface is nullptr, this is an illegal
  // instruction.
  if (atomic == nullptr) {
    state->Trap(/*is_interrupt*/ false, /*trap_value*/ 0,
                *RV_EC::kIllegalInstruction, inst->address(), inst);
    return;
  }
  // Submit the memory operation.
  auto address = generic::GetInstructionSource<uint64_t>(inst, 0);
  auto* db = inst->state()->db_factory()->Allocate<T>(1);
  db->set_latency(0);
  // Only access the operand if there is a value to be read.
  if (has_store_value) {
    db->template Set<T>(0, generic::GetInstructionSource<T>(inst, 1));
  }
  // This transfers ownership of db to context. Don't DecRef.
  auto* context = new riscv::LoadContext(db);
  auto status = state->atomic_tagged_memory()->PerformMemoryOp(
      address, op, db, inst->child(), context);
  // If the operation is unimplemented, this is an illegal instruction.
  if (absl::IsUnimplemented(status)) {
    state->Trap(/*is_interrupt*/ false, /*trap_value*/ 0,
                *RV_EC::kIllegalInstruction, inst->address(), inst);
    return;
  }
  context->DecRef();
}

void ALrw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kLoadLinked,
                               /*has_store_value*/ false);
}

void AScw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kStoreConditional,
                               /*has_store_value*/ true);
}

void AAmoswapw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kAtomicSwap,
                               /*has_store_value*/ true);
}

void AAmoaddw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kAtomicAdd,
                               /*has_store_value*/ true);
}

void AAmoandw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kAtomicAnd,
                               /*has_store_value*/ true);
}

void AAmoorw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kAtomicOr,
                               /*has_store_value*/ true);
}

void AAmoxorw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kAtomicXor,
                               /*has_store_value*/ true);
}

void AAmomaxw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kAtomicMax,
                               /*has_store_value*/ true);
}

void AAmomaxuw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kAtomicMaxu,
                               /*has_store_value*/ true);
}

void AAmominw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kAtomicMin,
                               /*has_store_value*/ true);
}

void AAmominuw(Instruction* instruction) {
  AInstructionHelper<uint32_t>(instruction, Operation::kAtomicMinu,
                               /*has_store_value*/ true);
}

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