// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_ARM64_CODE_STUBS_ARM64_H_
#define V8_ARM64_CODE_STUBS_ARM64_H_

namespace v8 {
namespace internal {


void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code);


class StringHelper : public AllStatic {
 public:
  // Compares two flat one-byte strings and returns result in x0.
  static void GenerateCompareFlatOneByteStrings(
      MacroAssembler* masm, Register left, Register right, Register scratch1,
      Register scratch2, Register scratch3, Register scratch4);

  // Compare two flat one-byte strings for equality and returns result in x0.
  static void GenerateFlatOneByteStringEquals(MacroAssembler* masm,
                                              Register left, Register right,
                                              Register scratch1,
                                              Register scratch2,
                                              Register scratch3);

 private:
  static void GenerateOneByteCharsCompareLoop(
      MacroAssembler* masm, Register left, Register right, Register length,
      Register scratch1, Register scratch2, Label* chars_not_equal);

  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
};


class StoreRegistersStateStub: public PlatformCodeStub {
 public:
  explicit StoreRegistersStateStub(Isolate* isolate)
      : PlatformCodeStub(isolate) {}

  static Register to_be_pushed_lr() { return ip0; }

  static void GenerateAheadOfTime(Isolate* isolate);

 private:
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
  DEFINE_PLATFORM_CODE_STUB(StoreRegistersState, PlatformCodeStub);
};


class RestoreRegistersStateStub: public PlatformCodeStub {
 public:
  explicit RestoreRegistersStateStub(Isolate* isolate)
      : PlatformCodeStub(isolate) {}

  static void GenerateAheadOfTime(Isolate* isolate);

 private:
  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
  DEFINE_PLATFORM_CODE_STUB(RestoreRegistersState, PlatformCodeStub);
};


class RecordWriteStub: public PlatformCodeStub {
 public:
  // Stub to record the write of 'value' at 'address' in 'object'.
  // Typically 'address' = 'object' + <some offset>.
  // See MacroAssembler::RecordWriteField() for example.
  RecordWriteStub(Isolate* isolate,
                  Register object,
                  Register value,
                  Register address,
                  RememberedSetAction remembered_set_action,
                  SaveFPRegsMode fp_mode)
      : PlatformCodeStub(isolate),
        regs_(object,   // An input reg.
              address,  // An input reg.
              value) {  // One scratch reg.
    DCHECK(object.Is64Bits());
    DCHECK(value.Is64Bits());
    DCHECK(address.Is64Bits());
    minor_key_ = ObjectBits::encode(object.code()) |
                 ValueBits::encode(value.code()) |
                 AddressBits::encode(address.code()) |
                 RememberedSetActionBits::encode(remembered_set_action) |
                 SaveFPRegsModeBits::encode(fp_mode);
  }

  RecordWriteStub(uint32_t key, Isolate* isolate)
      : PlatformCodeStub(key, isolate), regs_(object(), address(), value()) {}

  enum Mode {
    STORE_BUFFER_ONLY,
    INCREMENTAL,
    INCREMENTAL_COMPACTION
  };

  virtual bool SometimesSetsUpAFrame() { return false; }

  static Mode GetMode(Code* stub) {
    // Find the mode depending on the first two instructions.
    Instruction* instr1 =
      reinterpret_cast<Instruction*>(stub->instruction_start());
    Instruction* instr2 = instr1->following();

    if (instr1->IsUncondBranchImm()) {
      DCHECK(instr2->IsPCRelAddressing() && (instr2->Rd() == xzr.code()));
      return INCREMENTAL;
    }

    DCHECK(instr1->IsPCRelAddressing() && (instr1->Rd() == xzr.code()));

    if (instr2->IsUncondBranchImm()) {
      return INCREMENTAL_COMPACTION;
    }

    DCHECK(instr2->IsPCRelAddressing());

    return STORE_BUFFER_ONLY;
  }

  // We patch the two first instructions of the stub back and forth between an
  // adr and branch when we start and stop incremental heap marking.
  // The branch is
  //   b label
  // The adr is
  //   adr xzr label
  // so effectively a nop.
  static void Patch(Code* stub, Mode mode) {
    // We are going to patch the two first instructions of the stub.
    PatchingAssembler patcher(
        reinterpret_cast<Instruction*>(stub->instruction_start()), 2);
    Instruction* instr1 = patcher.InstructionAt(0);
    Instruction* instr2 = patcher.InstructionAt(kInstructionSize);
    // Instructions must be either 'adr' or 'b'.
    DCHECK(instr1->IsPCRelAddressing() || instr1->IsUncondBranchImm());
    DCHECK(instr2->IsPCRelAddressing() || instr2->IsUncondBranchImm());
    // Retrieve the offsets to the labels.
    int32_t offset_to_incremental_noncompacting = instr1->ImmPCOffset();
    int32_t offset_to_incremental_compacting = instr2->ImmPCOffset();

    switch (mode) {
      case STORE_BUFFER_ONLY:
        DCHECK(GetMode(stub) == INCREMENTAL ||
               GetMode(stub) == INCREMENTAL_COMPACTION);
        patcher.adr(xzr, offset_to_incremental_noncompacting);
        patcher.adr(xzr, offset_to_incremental_compacting);
        break;
      case INCREMENTAL:
        DCHECK(GetMode(stub) == STORE_BUFFER_ONLY);
        patcher.b(offset_to_incremental_noncompacting >> kInstructionSizeLog2);
        patcher.adr(xzr, offset_to_incremental_compacting);
        break;
      case INCREMENTAL_COMPACTION:
        DCHECK(GetMode(stub) == STORE_BUFFER_ONLY);
        patcher.adr(xzr, offset_to_incremental_noncompacting);
        patcher.b(offset_to_incremental_compacting >> kInstructionSizeLog2);
        break;
    }
    DCHECK(GetMode(stub) == mode);
  }

  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();

 private:
  // This is a helper class to manage the registers associated with the stub.
  // The 'object' and 'address' registers must be preserved.
  class RegisterAllocation {
   public:
    RegisterAllocation(Register object,
                       Register address,
                       Register scratch)
        : object_(object),
          address_(address),
          scratch0_(scratch),
          saved_regs_(kCallerSaved),
          saved_fp_regs_(kCallerSavedFP) {
      DCHECK(!AreAliased(scratch, object, address));

      // The SaveCallerSaveRegisters method needs to save caller-saved
      // registers, but we don't bother saving MacroAssembler scratch registers.
      saved_regs_.Remove(MacroAssembler::DefaultTmpList());
      saved_fp_regs_.Remove(MacroAssembler::DefaultFPTmpList());

      // We would like to require more scratch registers for this stub,
      // but the number of registers comes down to the ones used in
      // FullCodeGen::SetVar(), which is architecture independent.
      // We allocate 2 extra scratch registers that we'll save on the stack.
      CPURegList pool_available = GetValidRegistersForAllocation();
      CPURegList used_regs(object, address, scratch);
      pool_available.Remove(used_regs);
      scratch1_ = Register(pool_available.PopLowestIndex());
      scratch2_ = Register(pool_available.PopLowestIndex());

      // The scratch registers will be restored by other means so we don't need
      // to save them with the other caller saved registers.
      saved_regs_.Remove(scratch0_);
      saved_regs_.Remove(scratch1_);
      saved_regs_.Remove(scratch2_);
    }

    void Save(MacroAssembler* masm) {
      // We don't have to save scratch0_ because it was given to us as
      // a scratch register.
      masm->Push(scratch1_, scratch2_);
    }

    void Restore(MacroAssembler* masm) {
      masm->Pop(scratch2_, scratch1_);
    }

    // If we have to call into C then we need to save and restore all caller-
    // saved registers that were not already preserved.
    void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
      // TODO(all): This can be very expensive, and it is likely that not every
      // register will need to be preserved. Can we improve this?
      masm->PushCPURegList(saved_regs_);
      if (mode == kSaveFPRegs) {
        masm->PushCPURegList(saved_fp_regs_);
      }
    }

    void RestoreCallerSaveRegisters(MacroAssembler*masm, SaveFPRegsMode mode) {
      // TODO(all): This can be very expensive, and it is likely that not every
      // register will need to be preserved. Can we improve this?
      if (mode == kSaveFPRegs) {
        masm->PopCPURegList(saved_fp_regs_);
      }
      masm->PopCPURegList(saved_regs_);
    }

    Register object() { return object_; }
    Register address() { return address_; }
    Register scratch0() { return scratch0_; }
    Register scratch1() { return scratch1_; }
    Register scratch2() { return scratch2_; }

   private:
    Register object_;
    Register address_;
    Register scratch0_;
    Register scratch1_;
    Register scratch2_;
    CPURegList saved_regs_;
    CPURegList saved_fp_regs_;

    // TODO(all): We should consider moving this somewhere else.
    static CPURegList GetValidRegistersForAllocation() {
      // The list of valid registers for allocation is defined as all the
      // registers without those with a special meaning.
      //
      // The default list excludes registers x26 to x31 because they are
      // reserved for the following purpose:
      //  - x26 root register
      //  - x27 context pointer register
      //  - x28 jssp
      //  - x29 frame pointer
      //  - x30 link register(lr)
      //  - x31 xzr/stack pointer
      CPURegList list(CPURegister::kRegister, kXRegSizeInBits, 0, 25);

      // We also remove MacroAssembler's scratch registers.
      list.Remove(MacroAssembler::DefaultTmpList());

      return list;
    }

    friend class RecordWriteStub;
  };

  enum OnNoNeedToInformIncrementalMarker {
    kReturnOnNoNeedToInformIncrementalMarker,
    kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
  };

  virtual inline Major MajorKey() const FINAL OVERRIDE { return RecordWrite; }

  virtual void Generate(MacroAssembler* masm) OVERRIDE;
  void GenerateIncremental(MacroAssembler* masm, Mode mode);
  void CheckNeedsToInformIncrementalMarker(
      MacroAssembler* masm,
      OnNoNeedToInformIncrementalMarker on_no_need,
      Mode mode);
  void InformIncrementalMarker(MacroAssembler* masm);

  void Activate(Code* code) {
    code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
  }

  Register object() const {
    return Register::from_code(ObjectBits::decode(minor_key_));
  }

  Register value() const {
    return Register::from_code(ValueBits::decode(minor_key_));
  }

  Register address() const {
    return Register::from_code(AddressBits::decode(minor_key_));
  }

  RememberedSetAction remembered_set_action() const {
    return RememberedSetActionBits::decode(minor_key_);
  }

  SaveFPRegsMode save_fp_regs_mode() const {
    return SaveFPRegsModeBits::decode(minor_key_);
  }

  class ObjectBits: public BitField<int, 0, 5> {};
  class ValueBits: public BitField<int, 5, 5> {};
  class AddressBits: public BitField<int, 10, 5> {};
  class RememberedSetActionBits: public BitField<RememberedSetAction, 15, 1> {};
  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 16, 1> {};

  Label slow_;
  RegisterAllocation regs_;
};


// Helper to call C++ functions from generated code. The caller must prepare
// the exit frame before doing the call with GenerateCall.
class DirectCEntryStub: public PlatformCodeStub {
 public:
  explicit DirectCEntryStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
  void GenerateCall(MacroAssembler* masm, Register target);

 private:
  bool NeedsImmovableCode() { return true; }

  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
  DEFINE_PLATFORM_CODE_STUB(DirectCEntry, PlatformCodeStub);
};


class NameDictionaryLookupStub: public PlatformCodeStub {
 public:
  enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };

  NameDictionaryLookupStub(Isolate* isolate, LookupMode mode)
      : PlatformCodeStub(isolate) {
    minor_key_ = LookupModeBits::encode(mode);
  }

  static void GenerateNegativeLookup(MacroAssembler* masm,
                                     Label* miss,
                                     Label* done,
                                     Register receiver,
                                     Register properties,
                                     Handle<Name> name,
                                     Register scratch0);

  static void GeneratePositiveLookup(MacroAssembler* masm,
                                     Label* miss,
                                     Label* done,
                                     Register elements,
                                     Register name,
                                     Register scratch1,
                                     Register scratch2);

  virtual bool SometimesSetsUpAFrame() { return false; }

 private:
  static const int kInlinedProbes = 4;
  static const int kTotalProbes = 20;

  static const int kCapacityOffset =
      NameDictionary::kHeaderSize +
      NameDictionary::kCapacityIndex * kPointerSize;

  static const int kElementsStartOffset =
      NameDictionary::kHeaderSize +
      NameDictionary::kElementsStartIndex * kPointerSize;

  LookupMode mode() const { return LookupModeBits::decode(minor_key_); }

  class LookupModeBits: public BitField<LookupMode, 0, 1> {};

  DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
  DEFINE_PLATFORM_CODE_STUB(NameDictionaryLookup, PlatformCodeStub);
};

} }  // namespace v8::internal

#endif  // V8_ARM64_CODE_STUBS_ARM64_H_
