/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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 <stdint.h>

#include <functional>

#include <unwindstack/Elf.h>
#include <unwindstack/MachineMips64.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Memory.h>
#include <unwindstack/RegsMips64.h>
#include <unwindstack/UcontextMips64.h>
#include <unwindstack/UserMips64.h>

namespace unwindstack {

RegsMips64::RegsMips64()
    : RegsImpl<uint64_t>(MIPS64_REG_LAST, MIPS64_REG_SP,
                         Location(LOCATION_REGISTER, MIPS64_REG_RA)) {}

ArchEnum RegsMips64::Arch() {
  return ARCH_MIPS64;
}

uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
  if (!elf->valid() || rel_pc < 8) {
    return 0;
  }
  // For now, just assume no compact branches
  return 8;
}

void RegsMips64::SetFromRaw() {
  set_pc(regs_[MIPS64_REG_PC]);
  set_sp(regs_[MIPS64_REG_SP]);
}

bool RegsMips64::SetPcFromReturnAddress(Memory*) {
  if (pc() == regs_[MIPS64_REG_RA]) {
    return false;
  }

  set_pc(regs_[MIPS64_REG_RA]);
  return true;
}

void RegsMips64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
  fn("r0", regs_[MIPS64_REG_R0]);
  fn("r1", regs_[MIPS64_REG_R1]);
  fn("r2", regs_[MIPS64_REG_R2]);
  fn("r3", regs_[MIPS64_REG_R3]);
  fn("r4", regs_[MIPS64_REG_R4]);
  fn("r5", regs_[MIPS64_REG_R5]);
  fn("r6", regs_[MIPS64_REG_R6]);
  fn("r7", regs_[MIPS64_REG_R7]);
  fn("r8", regs_[MIPS64_REG_R8]);
  fn("r9", regs_[MIPS64_REG_R9]);
  fn("r10", regs_[MIPS64_REG_R10]);
  fn("r11", regs_[MIPS64_REG_R11]);
  fn("r12", regs_[MIPS64_REG_R12]);
  fn("r13", regs_[MIPS64_REG_R13]);
  fn("r14", regs_[MIPS64_REG_R14]);
  fn("r15", regs_[MIPS64_REG_R15]);
  fn("r16", regs_[MIPS64_REG_R16]);
  fn("r17", regs_[MIPS64_REG_R17]);
  fn("r18", regs_[MIPS64_REG_R18]);
  fn("r19", regs_[MIPS64_REG_R19]);
  fn("r20", regs_[MIPS64_REG_R20]);
  fn("r21", regs_[MIPS64_REG_R21]);
  fn("r22", regs_[MIPS64_REG_R22]);
  fn("r23", regs_[MIPS64_REG_R23]);
  fn("r24", regs_[MIPS64_REG_R24]);
  fn("r25", regs_[MIPS64_REG_R25]);
  fn("r26", regs_[MIPS64_REG_R26]);
  fn("r27", regs_[MIPS64_REG_R27]);
  fn("r28", regs_[MIPS64_REG_R28]);
  fn("sp", regs_[MIPS64_REG_SP]);
  fn("r30", regs_[MIPS64_REG_R30]);
  fn("ra", regs_[MIPS64_REG_RA]);
  fn("pc", regs_[MIPS64_REG_PC]);
}

Regs* RegsMips64::Read(void* remote_data) {
  mips64_user_regs* user = reinterpret_cast<mips64_user_regs*>(remote_data);
  RegsMips64* regs = new RegsMips64();
  uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());

  memcpy(regs->RawData(), &user->regs[MIPS64_EF_R0], (MIPS64_REG_R31 + 1) * sizeof(uint64_t));

  reg_data[MIPS64_REG_PC] = user->regs[MIPS64_EF_CP0_EPC];
  regs->SetFromRaw();
  return regs;
}

Regs* RegsMips64::CreateFromUcontext(void* ucontext) {
  mips64_ucontext_t* mips64_ucontext = reinterpret_cast<mips64_ucontext_t*>(ucontext);

  RegsMips64* regs = new RegsMips64();
  // Copy 64 bit sc_regs over to 64 bit regs
  memcpy(regs->RawData(), &mips64_ucontext->uc_mcontext.sc_regs[0], 32 * sizeof(uint64_t));
  (*regs)[MIPS64_REG_PC] = mips64_ucontext->uc_mcontext.sc_pc;
  regs->SetFromRaw();
  return regs;
}

bool RegsMips64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
  uint64_t data;
  Memory* elf_memory = elf->memory();
  // Read from elf memory since it is usually more expensive to read from
  // process memory.
  if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
    return false;
  }

  // Look for the kernel sigreturn function.
  // __vdso_rt_sigreturn:
  // 0x2402145b     li  v0, 0x145b
  // 0x0000000c     syscall
  if (data != 0x0000000c2402145bULL) {
    return false;
  }

  // vdso_rt_sigreturn => read rt_sigframe
  // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset
  // read 64 bit sc_regs[32] from stack into 64 bit regs_
  if (!process_memory->Read(sp() + 24 + 128 + 40, regs_.data(),
                            sizeof(uint64_t) * (MIPS64_REG_LAST - 1))) {
    return false;
  }

  // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset
  // read 64 bit sc_pc from stack into 64 bit regs_[MIPS64_REG_PC]
  if (!process_memory->Read(sp() + 24 + 128 + 40 + 576, &regs_[MIPS64_REG_PC],
                            sizeof(uint64_t))) {
    return false;
  }

  SetFromRaw();
  return true;
}

}  // namespace unwindstack
