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