// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Classes that describe assembly patterns as used by inline caches.

#ifndef RUNTIME_VM_INSTRUCTIONS_X64_H_
#define RUNTIME_VM_INSTRUCTIONS_X64_H_

#ifndef RUNTIME_VM_INSTRUCTIONS_H_
#error "Do not include instructions_x64.h directly; use instructions.h instead."
#endif

#include <limits>

#include "platform/unaligned.h"
#include "vm/allocation.h"

namespace dart {

intptr_t IndexFromPPLoadDisp8(uword start);
intptr_t IndexFromPPLoadDisp32(uword start);

// Template class for all instruction pattern classes.
// P has to specify a static pattern and a pattern length method.
template <class P>
class InstructionPattern : public ValueObject {
 public:
  explicit InstructionPattern(uword pc) : start_(pc) { ASSERT(pc != 0); }

  // Call to check if the instruction pattern at 'pc' match the instruction.
  // 'P::pattern()' returns the expected byte pattern in form of an integer
  // array with length of 'P::pattern_length_in_bytes()'. A '-1' element means
  // 'any byte'.
  bool IsValid() const {
    return TestBytesWith(P::pattern(), P::pattern_length_in_bytes());
  }

 protected:
  uword start() const { return start_; }

 private:
  // Returns true if the 'num_bytes' bytes at 'start_' correspond to
  // array of integers 'data'. 'data' elements are either a byte or -1, which
  // represents any byte.
  bool TestBytesWith(const int* data, int num_bytes) const {
    ASSERT(data != nullptr);
    const uint8_t* byte_array = reinterpret_cast<const uint8_t*>(start_);
    for (int i = 0; i < num_bytes; i++) {
      // Skip comparison for data[i] < 0.
      if ((data[i] >= 0) && (byte_array[i] != (0xFF & data[i]))) {
        return false;
      }
    }
    return true;
  }

  const uword start_;

  DISALLOW_COPY_AND_ASSIGN(InstructionPattern);
};

class ReturnPattern : public InstructionPattern<ReturnPattern> {
 public:
  explicit ReturnPattern(uword pc) : InstructionPattern(pc) {}

  static const int* pattern() {
    static const int kReturnPattern[kLengthInBytes] = {0xC3};
    return kReturnPattern;
  }

  static int pattern_length_in_bytes() { return kLengthInBytes; }

 private:
  static constexpr int kLengthInBytes = 1;
};

// push rbp
// mov rbp, rsp
class ProloguePattern : public InstructionPattern<ProloguePattern> {
 public:
  explicit ProloguePattern(uword pc) : InstructionPattern(pc) {}

  static const int* pattern() {
    static const int kProloguePattern[kLengthInBytes] = {0x55, 0x48, 0x89,
                                                         0xe5};
    return kProloguePattern;
  }

  static int pattern_length_in_bytes() { return kLengthInBytes; }

 private:
  static constexpr int kLengthInBytes = 4;
};

// mov rbp, rsp
class SetFramePointerPattern
    : public InstructionPattern<SetFramePointerPattern> {
 public:
  explicit SetFramePointerPattern(uword pc) : InstructionPattern(pc) {}

  static const int* pattern() {
    static const int kFramePointerPattern[kLengthInBytes] = {0x48, 0x89, 0xe5};
    return kFramePointerPattern;
  }

  static int pattern_length_in_bytes() { return kLengthInBytes; }

 private:
  static constexpr int kLengthInBytes = 3;
};

// callq *[rip+offset]
class PcRelativeCallPattern : public InstructionPattern<PcRelativeCallPattern> {
 public:
  static constexpr int kLengthInBytes = 5;

  // Theoretically we can encode offsets 5 bytes more than INT_MAX since the
  // instruction encoding uses the PC after current instruction.
  // Though in order to use int32_t as type on all architectures for distances,
  // we make the upper limit not have `+ kLengthInBytes`.
  static constexpr int32_t kLowerCallingRange =
      std::numeric_limits<int32_t>::min() + kLengthInBytes;
  static constexpr int32_t kUpperCallingRange =
      std::numeric_limits<int32_t>::max();

  explicit PcRelativeCallPattern(uword pc) : InstructionPattern(pc) {}

  int32_t distance() {
    return LoadUnaligned(reinterpret_cast<int32_t*>(start() + 1)) +
           kLengthInBytes;
  }

  void set_distance(int32_t distance) {
    // [distance] is relative to the start of the instruction, x64 considers the
    // offset relative to next PC.
    StoreUnaligned(reinterpret_cast<int32_t*>(start() + 1),
                   distance - kLengthInBytes);
  }

  static const int* pattern() {
    static const int kPattern[kLengthInBytes] = {0xe8, -1, -1, -1, -1};
    return kPattern;
  }

  static int pattern_length_in_bytes() { return kLengthInBytes; }
};

// Instruction pattern for a tail call to a signed 32-bit PC-relative offset
//
// The AOT compiler can emit PC-relative calls. If the destination of such a
// call is not in range for the "bl.<cond> <offset>" instruction, the AOT
// compiler will emit a trampoline which is in range. That trampoline will
// then tail-call to the final destination (also via PC-relative offset, but it
// supports a full signed 32-bit offset).
//
// The pattern of the trampoline looks like:
//
//     jmp $rip + <offset>
//
// (Strictly speaking the pc-relative call distance on X64 is big enough, but
// for making AOT relocation code (i.e. relocation.cc) platform independent and
// allow testing of trampolines on X64 we have it nonetheless)
class PcRelativeTrampolineJumpPattern : public ValueObject {
 public:
  static constexpr int kLengthInBytes = 5;

  explicit PcRelativeTrampolineJumpPattern(uword pattern_start)
      : pattern_start_(pattern_start) {}

  void Initialize() {
    uint8_t* pattern = reinterpret_cast<uint8_t*>(pattern_start_);
    pattern[0] = 0xe9;
  }

  int32_t distance() {
    return LoadUnaligned(reinterpret_cast<int32_t*>(pattern_start_ + 1)) +
           kLengthInBytes;
  }

  void set_distance(intptr_t distance) {
    // [distance] is relative to the start of the instruction, x64 considers the
    // offset relative to next PC.
    StoreUnaligned(reinterpret_cast<int32_t*>(pattern_start_ + 1),
                   static_cast<int32_t>(distance - kLengthInBytes));
  }

  bool IsValid() const {
    uint8_t* pattern = reinterpret_cast<uint8_t*>(pattern_start_);
    return pattern[0] == 0xe9;
  }

 private:
  uword pattern_start_;
};

class PcRelativeTailCallPattern : public PcRelativeTrampolineJumpPattern {
 public:
  static constexpr int32_t kLowerCallingRange =
      PcRelativeCallPattern::kLowerCallingRange;
  static constexpr int32_t kUpperCallingRange =
      PcRelativeCallPattern::kUpperCallingRange;

  explicit PcRelativeTailCallPattern(uword pc)
      : PcRelativeTrampolineJumpPattern(pc) {}
};

}  // namespace dart

#endif  // RUNTIME_VM_INSTRUCTIONS_X64_H_
