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

#include <cstdint>
#include <type_traits>

#include "mpact/sim/generic/instruction.h"
#include "riscv/riscv_instruction_helpers.h"
#include "riscv/riscv_register.h"
#include "riscv/riscv_state.h"

// This file implements the semantic functions for the Zcm* extensions.

namespace mpact::sim::riscv {

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

namespace RV32 {

namespace {

constexpr int kStackAdjBase[] = {
    0, 0, 0, 0, 16, 16, 16, 16, 32, 32, 32, 32, 48, 48, 48, 64,
};

}  // namespace

using RegType = ::mpact::sim::riscv::RV32Register;
using UIntReg = typename std::make_unsigned<typename RegType::ValueType>::type;
using IntReg = typename std::make_signed<UIntReg>::type;

// Zcmp instructions.
void RiscVZCmpPush(const Instruction *inst) {
  RiscVState *state = static_cast<RiscVState *>(inst->state());
  int num_regs = inst->SourcesSize() - 3;
  auto *db = state->db_factory()->Allocate<UIntReg>(num_regs);
  auto db_span = db->Get<UIntReg>();
  // Get the register values and put them in the data buffer.
  for (int i = 0; i < num_regs; ++i) {
    auto value = generic::GetInstructionSource<UIntReg>(inst, i + 3);
    db_span[i] = value;
  }
  // Store the data buffer to memory.
  auto sp = generic::GetInstructionSource<UIntReg>(inst, 0);
  state->StoreMemory(inst, sp - sizeof(UIntReg) * num_regs, db);
  db->DecRef();
  // Compute the stack adjustment.
  auto spimm6 = generic::GetInstructionSource<UIntReg>(inst, 1);
  auto rlist = generic::GetInstructionSource<UIntReg>(inst, 2);
  auto sp_adjustment = spimm6 + kStackAdjBase[rlist];
  // Compute the new stack pointer.
  sp -= sp_adjustment;
  RiscVWriteReg<RegType, UIntReg>(inst, 0, sp);
}

namespace {

// This helper pops the number of registers specified into the appropriate
// destination operands, and then adjusts the stack pointer.
void RiscVZCmpPopHelper(const Instruction *inst, int size) {
  RiscVState *state = static_cast<RiscVState *>(inst->state());
  // Compute the stack adjustment.
  auto spimm6 = generic::GetInstructionSource<UIntReg>(inst, 1);
  auto rlist = generic::GetInstructionSource<UIntReg>(inst, 2);
  auto sp_adjustment = spimm6 + kStackAdjBase[rlist];
  auto *db = state->db_factory()->Allocate<UIntReg>(size);
  // Load registers from the stack.
  auto sp = generic::GetInstructionSource<UIntReg>(inst, 0);
  // Start address = sp + sp_adjustment - sizeof(UIntReg) * size;
  uint64_t start_address = sp + sp_adjustment - sizeof(UIntReg) * size;
  state->LoadMemory(inst, start_address, db, nullptr, nullptr);
  auto db_span = db->Get<UIntReg>();
  for (int i = 0; i < size; ++i) {
    RiscVWriteReg<RegType, UIntReg>(inst, i, db_span[i]);
  }
  // Write to the stack pointer register.
  db->DecRef();
  RiscVWriteReg<RegType, UIntReg>(inst, size, sp + sp_adjustment);
}

}  // namespace

void RiscVZCmpPop(const Instruction *inst) {
  // Size is the number of registers to pop.
  int size = inst->DestinationsSize() - 1;
  RiscVZCmpPopHelper(inst, size);
}

void RiscVZCmpPopRet(const Instruction *inst) {
  // Size is the number of registers to pop.
  int size = inst->DestinationsSize() - 2;  // x2 and next_pc.
  RiscVZCmpPopHelper(inst, size);
  // Now perform the return.
  UIntReg target = generic::GetInstructionSource<UIntReg>(inst, 3);
  auto *db = inst->Destination(size + 1)->AllocateDataBuffer();
  db->SetSubmit<UIntReg>(0, target);
}

void RiscVZCmpPopRetz(const Instruction *inst) {
  // Size is the number of registers to pop.
  int size = inst->DestinationsSize() - 3;  // x2, x10, and next_pc.
  RiscVZCmpPopHelper(inst, size);
  // Now clear a0.
  RiscVWriteReg<RegType, UIntReg>(inst, size + 1, 0);
  // Now perform the return.
  UIntReg target = generic::GetInstructionSource<UIntReg>(inst, 3);
  auto *db = inst->Destination(size + 2)->AllocateDataBuffer();
  db->SetSubmit<UIntReg>(0, target);
}

void RiscVZCmpMvTwoRegs(const Instruction *inst) {
  RiscVWriteReg<RegType, UIntReg>(
      inst, 0, generic::GetInstructionSource<UIntReg>(inst, 0));
  RiscVWriteReg<RegType, UIntReg>(
      inst, 1, generic::GetInstructionSource<UIntReg>(inst, 1));
}

// Zcmt instructions.
namespace {

void RiscVZCmtJtHelper(const Instruction *inst, int dest_index) {
  int index = generic::GetInstructionSource<UIntReg>(inst, 0);
  auto *state = static_cast<RiscVState *>(inst->state());
  auto jvt_value = state->jvt()->AsUint64();
  auto mode = jvt_value & 0x3f;
  if (mode != 0) {
    state->Trap(/*is_interrupt=*/false, 0, *ExceptionCode::kIllegalInstruction,
                inst->address(), inst);
    return;
  }
  // Load target address from the jump table.
  UIntReg entry_address = (jvt_value & ~0x3f) + (index * sizeof(UIntReg));
  auto *db = state->db_factory()->Allocate<UIntReg>(1);
  state->LoadMemory(inst, entry_address, db, nullptr, nullptr);
  UIntReg target_address = db->Get<UIntReg>(0);
  db->DecRef();
  // Write the target address to the next pc operand.
  auto *target_db = inst->Destination(0)->AllocateDataBuffer();
  target_db->SetSubmit<UIntReg>(0, target_address);
}

}  // namespace

void RiscVZCmtJt(const Instruction *inst) { RiscVZCmtJtHelper(inst, 0); }

void RiscVZCmtJalt(const Instruction *inst) {
  RiscVZCmtJtHelper(inst, 1);
  // Write the return address to the x1 (ra) operand.
  RiscVWriteReg<RegType, UIntReg>(inst, 1, inst->address() + inst->size());
}

}  // namespace RV32

namespace RV64 {

namespace {

constexpr int kStackAdjBase[] = {
    0, 0, 0, 0, 16, 16, 32, 32, 48, 48, 64, 64, 80, 80, 96, 112,
};

}  // namespace

using RegType = ::mpact::sim::riscv::RV64Register;
using UIntReg = typename std::make_unsigned<typename RegType::ValueType>::type;
using IntReg = typename std::make_signed<UIntReg>::type;

// Zcmp instructions.
void RiscVZCmpPush(const Instruction *inst) {
  RiscVState *state = static_cast<RiscVState *>(inst->state());
  int num_regs = inst->SourcesSize() - 3;
  auto *db = state->db_factory()->Allocate<UIntReg>(num_regs);
  auto db_span = db->Get<UIntReg>();
  // Get the register values and put them in the data buffer.
  for (int i = 0; i < num_regs; ++i) {
    auto value = generic::GetInstructionSource<UIntReg>(inst, i + 3);
    db_span[i] = value;
  }
  // Store the data buffer to memory.
  auto sp = generic::GetInstructionSource<UIntReg>(inst, 0);
  state->StoreMemory(inst, sp - sizeof(UIntReg) * num_regs, db);
  db->DecRef();
  // Compute the stack adjustment.
  auto spimm6 = generic::GetInstructionSource<UIntReg>(inst, 1);
  auto rlist = generic::GetInstructionSource<UIntReg>(inst, 2);
  auto sp_adjustment = spimm6 + kStackAdjBase[rlist];
  // Compute the new stack pointer.
  sp -= sp_adjustment;
  RiscVWriteReg<RegType, UIntReg>(inst, 0, sp);
}

namespace {

// This helper pops the number of registers specified into the appropriate
// destination operands, and then adjusts the stack pointer.
void RiscVZCmpPopHelper(const Instruction *inst, int size) {
  RiscVState *state = static_cast<RiscVState *>(inst->state());
  // Compute the stack adjustment.
  auto spimm6 = generic::GetInstructionSource<UIntReg>(inst, 1);
  auto rlist = generic::GetInstructionSource<UIntReg>(inst, 2);
  auto sp_adjustment = spimm6 + kStackAdjBase[rlist];
  auto *db = state->db_factory()->Allocate<UIntReg>(size);
  // Load registers from the stack.
  auto sp = generic::GetInstructionSource<UIntReg>(inst, 0);
  // Start address = sp + sp_adjustment - sizeof(UIntReg) * size;
  uint64_t start_address = sp + sp_adjustment - sizeof(UIntReg) * size;
  state->LoadMemory(inst, start_address, db, nullptr, nullptr);
  auto db_span = db->Get<UIntReg>();
  for (int i = 0; i < size; ++i) {
    RiscVWriteReg<RegType, UIntReg>(inst, i, db_span[i]);
  }
  // Write to the stack pointer register.
  db->DecRef();
  RiscVWriteReg<RegType, UIntReg>(inst, size, sp + sp_adjustment);
}

}  // namespace

void RiscVZCmpPop(const Instruction *inst) {
  // Size is the number of registers to pop.
  int size = inst->DestinationsSize() - 1;
  RiscVZCmpPopHelper(inst, size);
}

void RiscVZCmpPopRet(const Instruction *inst) {
  // Size is the number of registers to pop.
  int size = inst->DestinationsSize() - 2;  // x2 and next_pc.
  RiscVZCmpPopHelper(inst, size);
  // Now perform the return.
  UIntReg target = generic::GetInstructionSource<UIntReg>(inst, 3);
  auto *db = inst->Destination(size + 1)->AllocateDataBuffer();
  db->SetSubmit<UIntReg>(0, target);
}

void RiscVZCmpPopRetz(const Instruction *inst) {
  // Size is the number of registers to pop.
  int size = inst->DestinationsSize() - 3;  // x2, x10, and next_pc.
  RiscVZCmpPopHelper(inst, size);
  // Now clear a0.
  RiscVWriteReg<RegType, UIntReg>(inst, size + 1, 0);
  // Now perform the return.
  UIntReg target = generic::GetInstructionSource<UIntReg>(inst, 3);
  auto *db = inst->Destination(size + 2)->AllocateDataBuffer();
  db->SetSubmit<UIntReg>(0, target);
}

void RiscVZCmpMvTwoRegs(const Instruction *inst) {
  RiscVWriteReg<RegType, UIntReg>(
      inst, 0, generic::GetInstructionSource<UIntReg>(inst, 0));
  RiscVWriteReg<RegType, UIntReg>(
      inst, 1, generic::GetInstructionSource<UIntReg>(inst, 1));
}

// Zcmt instructions.
namespace {

void RiscVZCmtJtHelper(const Instruction *inst, int dest_index) {
  int index = generic::GetInstructionSource<UIntReg>(inst, 0);
  auto *state = static_cast<RiscVState *>(inst->state());
  auto jvt_value = state->jvt()->AsUint64();
  auto mode = jvt_value & 0x3f;
  if (mode != 0) {
    state->Trap(/*is_interrupt=*/false, 0, *ExceptionCode::kIllegalInstruction,
                inst->address(), inst);
    return;
  }
  // Load target address from the jump table.
  UIntReg entry_address = (jvt_value & ~0x3f) + (index * sizeof(UIntReg));
  auto *db = state->db_factory()->Allocate<UIntReg>(1);
  state->LoadMemory(inst, entry_address, db, nullptr, nullptr);
  UIntReg target_address = db->Get<UIntReg>(0);
  db->DecRef();
  // Write the target address to the next pc operand.
  auto *target_db = inst->Destination(0)->AllocateDataBuffer();
  target_db->SetSubmit<UIntReg>(0, target_address);
}

}  // namespace

void RiscVZCmtJt(const Instruction *inst) { RiscVZCmtJtHelper(inst, 0); }

void RiscVZCmtJalt(const Instruction *inst) {
  RiscVZCmtJtHelper(inst, 1);
  // Write the return address to the x1 (ra) operand.
  RiscVWriteReg<RegType, UIntReg>(inst, 1, inst->address() + inst->size());
}

}  // namespace RV64

}  // namespace mpact::sim::riscv
