/*
 * Copyright (C) 2014 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 "disassembler_arm64.h"

#include <inttypes.h>

#include <regex>

#include <sstream>

#include "android-base/logging.h"
#include "android-base/stringprintf.h"

using android::base::StringPrintf;

using namespace vixl::aarch64;  // NOLINT(build/namespaces)

namespace art {
namespace arm64 {

// This enumeration should mirror the declarations in
// runtime/arch/arm64/registers_arm64.h. We do not include that file to
// avoid a dependency on libart.
enum {
  TR  = 19,
  IP0 = 16,
  IP1 = 17,
  FP  = 29,
  LR  = 30
};

void CustomDisassembler::AppendRegisterNameToOutput(const Instruction* instr,
                                                    const CPURegister& reg) {
  USE(instr);
  if (reg.IsRegister() && reg.Is64Bits()) {
    if (reg.GetCode() == TR) {
      AppendToOutput("tr");
      return;
    } else if (reg.GetCode() == LR) {
      AppendToOutput("lr");
      return;
    }
    // Fall through.
  }
  // Print other register names as usual.
  Disassembler::AppendRegisterNameToOutput(instr, reg);
}

void CustomDisassembler::Visit(vixl::aarch64::Metadata* metadata, const Instruction* instr) {
  vixl::aarch64::Disassembler::Visit(metadata, instr);
  const std::string& form = (*metadata)["form"];

  // These regexs are long, but it is an attempt to match the mapping entry keys in the
  // #define DEFAULT_FORM_TO_VISITOR_MAP(VISITORCLASS) in the file
  // external/vixl/src/aarch64/decoder-visitor-map-aarch64.h
  // for the ::VisitLoadLiteralInstr, ::VisitLoadStoreUnsignedOffset or ::VisitUnconditionalBranch
  // function addresess key values.
  // N.B. the mapping are many to one.
  if (std::regex_match(form, std::regex("(ldrsw|ldr|prfm)_(32|64|d|b|h|q|s)_loadlit"))) {
    VisitLoadLiteralInstr(instr);
    return;
  }

  if (std::regex_match(form, std::regex(
      "(ldrb|ldrh|ldrsb|ldrsh|ldrsw|ldr|prfm|strb|strh|str)_(32|64|d|b|h|q|s)_ldst_pos"))) {
    VisitLoadStoreUnsignedOffsetInstr(instr);
    return;
  }

  if (std::regex_match(form, std::regex("(bl|b)_only_branch_imm"))) {
    VisitUnconditionalBranchInstr(instr);
    return;
  }
}

void CustomDisassembler::VisitLoadLiteralInstr(const Instruction* instr) {
  if (!read_literals_) {
    return;
  }

  // Get address of literal. Bail if not within expected buffer range to
  // avoid trying to fetch invalid literals (we can encounter this when
  // interpreting raw data as instructions).
  void* data_address = instr->GetLiteralAddress<void*>();

  if (data_address < base_address_ || data_address >= end_address_) {
    AppendToOutput(" (?)");
    return;
  }

  // Output information on literal.
  Instr op = instr->Mask(LoadLiteralMask);
  switch (op) {
    case LDR_w_lit:
    case LDR_x_lit:
    case LDRSW_x_lit: {
      int64_t data = op == LDR_x_lit ? *reinterpret_cast<int64_t*>(data_address)
                                     : *reinterpret_cast<int32_t*>(data_address);
      AppendToOutput(" (0x%" PRIx64 " / %" PRId64 ")", data, data);
      break;
    }
    case LDR_s_lit:
    case LDR_d_lit: {
      double data = (op == LDR_s_lit) ? *reinterpret_cast<float*>(data_address)
                                      : *reinterpret_cast<double*>(data_address);
      AppendToOutput(" (%g)", data);
      break;
    }
    default:
      break;
  }
}

void CustomDisassembler::VisitLoadStoreUnsignedOffsetInstr(const Instruction* instr) {
  if (instr->GetRn() == TR) {
    AppendThreadOfsetName(instr);
  }
}

void CustomDisassembler::VisitUnconditionalBranchInstr(const Instruction* instr) {
  if (instr->Mask(UnconditionalBranchMask) == BL) {
    const Instruction* target = instr->GetImmPCOffsetTarget();
    if (target >= base_address_ &&
        target < end_address_ &&
        target->Mask(LoadStoreMask) == LDR_x &&
        target->GetRn() == TR &&
        target->GetRt() == IP0 &&
        target->GetNextInstruction() < end_address_ &&
        target->GetNextInstruction()->Mask(UnconditionalBranchToRegisterMask) == BR &&
        target->GetNextInstruction()->GetRn() == IP0) {
      AppendThreadOfsetName(target);
    }
  }
}

void CustomDisassembler::AppendThreadOfsetName(const vixl::aarch64::Instruction* instr) {
  int64_t offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
  std::ostringstream tmp_stream;
  options_->thread_offset_name_function_(tmp_stream, static_cast<uint32_t>(offset));
  AppendToOutput(" ; %s", tmp_stream.str().c_str());
}

size_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) {
  const Instruction* instr = reinterpret_cast<const Instruction*>(begin);
  decoder.Decode(instr);
    os << FormatInstructionPointer(begin)
     << StringPrintf(": %08x\t%s\n", instr->GetInstructionBits(), disasm.GetOutput());
  return kInstructionSize;
}

void DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) {
  for (const uint8_t* cur = begin; cur < end; cur += kInstructionSize) {
    Dump(os, cur);
  }
}

}  // namespace arm64
}  // namespace art
