/*
 * Copyright (C) 2016 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.
 */

#ifndef ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_VIXL_H_
#define ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_VIXL_H_

#include <android-base/logging.h>

#include "base/macros.h"
#include "constants_arm.h"
#include "dwarf/register.h"
#include "offsets.h"
#include "utils/arm/managed_register_arm.h"
#include "utils/assembler.h"

// TODO(VIXL): Make VIXL compile with -Wshadow and remove pragmas.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow"
#include "aarch32/macro-assembler-aarch32.h"
#pragma GCC diagnostic pop

namespace vixl32 = vixl::aarch32;

namespace art HIDDEN {
namespace arm {

inline dwarf::Reg DWARFReg(vixl32::Register reg) {
  return dwarf::Reg::ArmCore(static_cast<int>(reg.GetCode()));
}

inline dwarf::Reg DWARFReg(vixl32::SRegister reg) {
  return dwarf::Reg::ArmFp(static_cast<int>(reg.GetCode()));
}

enum LoadOperandType {
  kLoadSignedByte,
  kLoadUnsignedByte,
  kLoadSignedHalfword,
  kLoadUnsignedHalfword,
  kLoadWord,
  kLoadWordPair,
  kLoadSWord,
  kLoadDWord
};

enum StoreOperandType {
  kStoreByte,
  kStoreHalfword,
  kStoreWord,
  kStoreWordPair,
  kStoreSWord,
  kStoreDWord
};

class ArmVIXLMacroAssembler final : public vixl32::MacroAssembler {
 public:
  // Most methods fit in a 1KB code buffer, which results in more optimal alloc/realloc and
  // fewer system calls than a larger default capacity.
  static constexpr size_t kDefaultCodeBufferCapacity = 1 * KB;

  ArmVIXLMacroAssembler()
      : vixl32::MacroAssembler(ArmVIXLMacroAssembler::kDefaultCodeBufferCapacity) {}

  // The following interfaces can generate CMP+Bcc or Cbz/Cbnz.
  // CMP+Bcc are generated by default.
  // If a hint is given (is_far_target = false) and rn and label can all fit into Cbz/Cbnz,
  // then Cbz/Cbnz is generated.
  // Prefer following interfaces to using vixl32::MacroAssembler::Cbz/Cbnz.
  // In T32, Cbz/Cbnz instructions have following limitations:
  // - Far targets, which are over 126 bytes away, are not supported.
  // - Only low registers can be encoded.
  // - Backward branches are not supported.
  void CompareAndBranchIfZero(vixl32::Register rn,
                              vixl32::Label* label,
                              bool is_far_target = true);
  void CompareAndBranchIfNonZero(vixl32::Register rn,
                                 vixl32::Label* label,
                                 bool is_far_target = true);

  // In T32 some of the instructions (add, mov, etc) outside an IT block
  // have only 32-bit encodings. But there are 16-bit flag setting
  // versions of these instructions (adds, movs, etc). In most of the
  // cases in ART we don't care if the instructions keep flags or not;
  // thus we can benefit from smaller code size.
  // VIXL will never generate flag setting versions (for example, adds
  // for Add macro instruction) unless vixl32::DontCare option is
  // explicitly specified. That's why we introduce wrappers to use
  // DontCare option by default.
#define WITH_FLAGS_DONT_CARE_RD_RN_OP(func_name) \
  void (func_name)(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) { \
    MacroAssembler::func_name(vixl32::DontCare, rd, rn, operand); \
  } \
  using MacroAssembler::func_name

  WITH_FLAGS_DONT_CARE_RD_RN_OP(Adc);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Sub);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Sbc);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Rsb);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Rsc);

  WITH_FLAGS_DONT_CARE_RD_RN_OP(Eor);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Orr);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Orn);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(And);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Bic);

  WITH_FLAGS_DONT_CARE_RD_RN_OP(Asr);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Lsr);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Lsl);
  WITH_FLAGS_DONT_CARE_RD_RN_OP(Ror);

#undef WITH_FLAGS_DONT_CARE_RD_RN_OP

#define WITH_FLAGS_DONT_CARE_RD_OP(func_name) \
  void (func_name)(vixl32::Register rd, const vixl32::Operand& operand) { \
    MacroAssembler::func_name(vixl32::DontCare, rd, operand); \
  } \
  using MacroAssembler::func_name

  WITH_FLAGS_DONT_CARE_RD_OP(Mvn);
  WITH_FLAGS_DONT_CARE_RD_OP(Mov);

#undef WITH_FLAGS_DONT_CARE_RD_OP

  // The following two functions don't fall into above categories. Overload them separately.
  void Rrx(vixl32::Register rd, vixl32::Register rn) {
    MacroAssembler::Rrx(vixl32::DontCare, rd, rn);
  }
  using MacroAssembler::Rrx;

  void Mul(vixl32::Register rd, vixl32::Register rn, vixl32::Register rm) {
    MacroAssembler::Mul(vixl32::DontCare, rd, rn, rm);
  }
  using MacroAssembler::Mul;

  // TODO: Remove when MacroAssembler::Add(FlagsUpdate, Condition, Register, Register, Operand)
  // makes the right decision about 16-bit encodings.
  void Add(vixl32::Register rd, vixl32::Register rn, const vixl32::Operand& operand) {
    if (rd.Is(rn) && operand.IsPlainRegister()) {
      MacroAssembler::Add(rd, rn, operand);
    } else {
      MacroAssembler::Add(vixl32::DontCare, rd, rn, operand);
    }
  }
  using MacroAssembler::Add;

  // These interfaces try to use 16-bit T2 encoding of B instruction.
  void B(vixl32::Label* label);
  // For B(label), we always try to use Narrow encoding, because 16-bit T2 encoding supports
  // jumping within 2KB range. For B(cond, label), because the supported branch range is 256
  // bytes; we use the far_target hint to try to use 16-bit T1 encoding for short range jumps.
  void B(vixl32::Condition cond, vixl32::Label* label, bool is_far_target = true);

  // Use literal for generating double constant if it doesn't fit VMOV encoding.
  void Vmov(vixl32::DRegister rd, double imm) {
    if (vixl::VFP::IsImmFP64(imm)) {
      MacroAssembler::Vmov(rd, imm);
    } else {
      MacroAssembler::Vldr(rd, imm);
    }
  }
  using MacroAssembler::Vmov;

  // TODO(b/281982421): Move the implementation of Mrrc to vixl and remove this implementation.
  void Mrrc(vixl32::Register r1, vixl32::Register r2, int coproc, int opc1, int crm) {
    // See ARM A-profile A32/T32 Instruction set architecture
    // https://developer.arm.com/documentation/ddi0597/2022-09/Base-Instructions/MRRC--Move-to-two-general-purpose-registers-from-System-register-
    CHECK(coproc == 15 || coproc == 14);
    if (IsUsingT32()) {
      uint32_t inst = (0b111011000101 << 20) |
                      (r2.GetCode() << 16) |
                      (r1.GetCode() << 12) |
                      (coproc << 8) |
                      (opc1 << 4) |
                      crm;
      EmitT32_32(inst);
    } else {
      uint32_t inst = (0b000011000101 << 20) |
                      (r2.GetCode() << 16) |
                      (r1.GetCode() << 12) |
                      (coproc << 8) |
                      (opc1 << 4) |
                      crm;
      EmitA32(inst);
    }
  }
};

class ArmVIXLAssembler final : public Assembler {
 private:
  class ArmException;
 public:
  explicit ArmVIXLAssembler(ArenaAllocator* allocator)
      : Assembler(allocator) {
    // Use Thumb2 instruction set.
    vixl_masm_.UseT32();
  }

  virtual ~ArmVIXLAssembler() {}
  ArmVIXLMacroAssembler* GetVIXLAssembler() { return &vixl_masm_; }
  void FinalizeCode() override;

  // Size of generated code.
  size_t CodeSize() const override;
  const uint8_t* CodeBufferBaseAddress() const override;

  // Copy instructions out of assembly buffer into the given region of memory.
  void CopyInstructions(const MemoryRegion& region) override;

  void Bind([[maybe_unused]] Label* label) override {
    UNIMPLEMENTED(FATAL) << "Do not use Bind(Label*) for ARM";
  }
  void Jump([[maybe_unused]] Label* label) override {
    UNIMPLEMENTED(FATAL) << "Do not use Jump(Label*) for ARM";
  }

  void Bind(vixl::aarch32::Label* label) {
    vixl_masm_.Bind(label);
  }
  void Jump(vixl::aarch32::Label* label) {
    vixl_masm_.B(label);
  }

  //
  // Heap poisoning.
  //

  // Poison a heap reference contained in `reg`.
  void PoisonHeapReference(vixl32::Register reg);
  // Unpoison a heap reference contained in `reg`.
  void UnpoisonHeapReference(vixl32::Register reg);
  // Poison a heap reference contained in `reg` if heap poisoning is enabled.
  void MaybePoisonHeapReference(vixl32::Register reg);
  // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
  void MaybeUnpoisonHeapReference(vixl32::Register reg);

  // Emit code checking the status of the Marking Register, and aborting
  // the program if MR does not match the value stored in the art::Thread
  // object.
  //
  // Argument `temp` is used as a temporary register to generate code.
  // Argument `code` is used to identify the different occurrences of
  // MaybeGenerateMarkingRegisterCheck and is passed to the BKPT instruction.
  void GenerateMarkingRegisterCheck(vixl32::Register temp, int code = 0);

  void StoreToOffset(StoreOperandType type,
                     vixl32::Register reg,
                     vixl32::Register base,
                     int32_t offset);
  void StoreSToOffset(vixl32::SRegister source, vixl32::Register base, int32_t offset);
  void StoreDToOffset(vixl32::DRegister source, vixl32::Register base, int32_t offset);

  void LoadImmediate(vixl32::Register dest, int32_t value);
  void LoadFromOffset(LoadOperandType type,
                      vixl32::Register reg,
                      vixl32::Register base,
                      int32_t offset);
  void LoadSFromOffset(vixl32::SRegister reg, vixl32::Register base, int32_t offset);
  void LoadDFromOffset(vixl32::DRegister reg, vixl32::Register base, int32_t offset);

  void LoadRegisterList(RegList regs, size_t stack_offset);
  void StoreRegisterList(RegList regs, size_t stack_offset);

  bool ShifterOperandCanAlwaysHold(uint32_t immediate);
  bool ShifterOperandCanHold(Opcode opcode,
                             uint32_t immediate,
                             vixl::aarch32::FlagsUpdate update_flags = vixl::aarch32::DontCare);
  bool CanSplitLoadStoreOffset(int32_t allowed_offset_bits,
                               int32_t offset,
                               /*out*/ int32_t* add_to_base,
                               /*out*/ int32_t* offset_for_load_store);
  int32_t AdjustLoadStoreOffset(int32_t allowed_offset_bits,
                                vixl32::Register temp,
                                vixl32::Register base,
                                int32_t offset);
  int32_t GetAllowedLoadOffsetBits(LoadOperandType type);
  int32_t GetAllowedStoreOffsetBits(StoreOperandType type);

  void AddConstant(vixl32::Register rd, int32_t value);
  void AddConstant(vixl32::Register rd, vixl32::Register rn, int32_t value);
  void AddConstantInIt(vixl32::Register rd,
                       vixl32::Register rn,
                       int32_t value,
                       vixl32::Condition cond = vixl32::al);

  template <typename T>
  vixl::aarch32::Literal<T>* CreateLiteralDestroyedWithPool(T value) {
    vixl::aarch32::Literal<T>* literal =
        new vixl::aarch32::Literal<T>(value,
                                      vixl32::RawLiteral::kPlacedWhenUsed,
                                      vixl32::RawLiteral::kDeletedOnPoolDestruction);
    return literal;
  }

 private:
  // VIXL assembler.
  ArmVIXLMacroAssembler vixl_masm_;
};

// Thread register declaration.
extern const vixl32::Register tr;
// Marking register declaration.
extern const vixl32::Register mr;

}  // namespace arm
}  // namespace art

#endif  // ART_COMPILER_UTILS_ARM_ASSEMBLER_ARM_VIXL_H_
