1f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
5fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#ifndef V8_ARM64_ASSEMBLER_ARM64_H_
6fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#define V8_ARM64_ASSEMBLER_ARM64_H_
7f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
8f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#include <list>
9f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#include <map>
10f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/cpu.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/globals.h"
13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/utils.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/assembler.h"
15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/serialize.h"
16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/instructions-arm64.h"
17f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
18f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
19f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace v8 {
20f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace internal {
21f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
22f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
23f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// -----------------------------------------------------------------------------
24f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Registers.
25f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define REGISTER_CODE_LIST(R)                                                  \
26f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgR(0)  R(1)  R(2)  R(3)  R(4)  R(5)  R(6)  R(7)                                 \
27f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgR(8)  R(9)  R(10) R(11) R(12) R(13) R(14) R(15)                                \
28f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgR(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23)                                \
29f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgR(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
30f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
31f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
32f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
33f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
34f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
35f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Some CPURegister methods can return Register and FPRegister types, so we
36f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// need to declare them in advance.
37f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstruct Register;
38f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstruct FPRegister;
39f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
40f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
41f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstruct CPURegister {
42f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  enum RegisterType {
43f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // The kInvalid value is used to detect uninitialized static instances,
44f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // which are always zero-initialized before any constructors are called.
45f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    kInvalid = 0,
46f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    kRegister,
47f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    kFPRegister,
48f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    kNoRegister
49f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  };
50f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
51f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static CPURegister Create(unsigned code, unsigned size, RegisterType type) {
52f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CPURegister r = {code, size, type};
53f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return r;
54f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
55f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
56f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned code() const;
57f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  RegisterType type() const;
58f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  RegList Bit() const;
59f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned SizeInBits() const;
60f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int SizeInBytes() const;
61f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool Is32Bits() const;
62f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool Is64Bits() const;
63f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsValid() const;
64f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsValidOrNone() const;
65f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsValidRegister() const;
66f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsValidFPRegister() const;
67f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsNone() const;
68f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool Is(const CPURegister& other) const;
69a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org  bool Aliases(const CPURegister& other) const;
70f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
71f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsZero() const;
72f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsSP() const;
73f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
74f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsRegister() const;
75f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsFPRegister() const;
76f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
77f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Register X() const;
78f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Register W() const;
79f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  FPRegister D() const;
80f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  FPRegister S() const;
81f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
82f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsSameSizeAndType(const CPURegister& other) const;
83f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
84f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // V8 compatibility.
85f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool is(const CPURegister& other) const { return Is(other); }
86f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool is_valid() const { return IsValid(); }
87f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
88f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned reg_code;
89f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned reg_size;
90f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  RegisterType reg_type;
91f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
92f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
93f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
94f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstruct Register : public CPURegister {
95f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Register Create(unsigned code, unsigned size) {
96a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    return Register(CPURegister::Create(code, size, CPURegister::kRegister));
97f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
99f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Register() {
100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_code = 0;
101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_size = 0;
102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_type = CPURegister::kNoRegister;
103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
105a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  explicit Register(const CPURegister& r) {
106a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    reg_code = r.reg_code;
107a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    reg_size = r.reg_size;
108a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    reg_type = r.reg_type;
109a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    ASSERT(IsValidOrNone());
110a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  }
111a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org
112a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  Register(const Register& r) {  // NOLINT(runtime/explicit)
113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_code = r.reg_code;
114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_size = r.reg_size;
115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_type = r.reg_type;
116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValidOrNone());
117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsValid() const {
120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsRegister() || IsNone());
121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return IsValidRegister();
122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Register XRegFromCode(unsigned code);
125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Register WRegFromCode(unsigned code);
126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Start of V8 compatibility section ---------------------
128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // These memebers are necessary for compilation.
129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // A few of them may be unused for now.
130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kNumRegisters = kNumberOfRegisters;
132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static int NumRegisters() { return kNumRegisters; }
133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // We allow crankshaft to use the following registers:
135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   - x0 to x15
136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   - x18 to x24
137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   - x27 (also context)
138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // TODO(all): Register x25 is currently free and could be available for
140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // crankshaft, but we don't use it as we might use it as a per function
141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // literal pool pointer in the future.
142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // TODO(all): Consider storing cp in x25 to have only two ranges.
144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // We split allocatable registers in three ranges called
145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   - "low range"
146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   - "high range"
147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   - "context"
148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const unsigned kAllocatableLowRangeBegin = 0;
149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const unsigned kAllocatableLowRangeEnd = 15;
150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const unsigned kAllocatableHighRangeBegin = 18;
151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const unsigned kAllocatableHighRangeEnd = 24;
152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const unsigned kAllocatableContext = 27;
153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Gap between low and high ranges.
155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kAllocatableRangeGapSize =
156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kMaxNumAllocatableRegisters =
159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1) + 1;  // cp
161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Return true if the register is one that crankshaft can allocate.
164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsAllocatable() const {
165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return ((reg_code == kAllocatableContext) ||
166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            (reg_code <= kAllocatableLowRangeEnd) ||
167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            ((reg_code >= kAllocatableHighRangeBegin) &&
168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             (reg_code <= kAllocatableHighRangeEnd)));
169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Register FromAllocationIndex(unsigned index) {
172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(index < static_cast<unsigned>(NumAllocatableRegisters()));
173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // cp is the last allocatable register.
174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (index == (static_cast<unsigned>(NumAllocatableRegisters() - 1))) {
175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      return from_code(kAllocatableContext);
176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Handle low and high ranges.
179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return (index <= kAllocatableLowRangeEnd)
180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        ? from_code(index)
181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        : from_code(index + kAllocatableRangeGapSize);
182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const char* AllocationIndexToString(int index) {
185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT((index >= 0) && (index < NumAllocatableRegisters()));
186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT((kAllocatableLowRangeBegin == 0) &&
187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           (kAllocatableLowRangeEnd == 15) &&
188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           (kAllocatableHighRangeBegin == 18) &&
189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           (kAllocatableHighRangeEnd == 24) &&
190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           (kAllocatableContext == 27));
191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    const char* const names[] = {
192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      "x0", "x1", "x2", "x3", "x4",
193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      "x5", "x6", "x7", "x8", "x9",
194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      "x10", "x11", "x12", "x13", "x14",
195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      "x15", "x18", "x19", "x20", "x21",
196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      "x22", "x23", "x24", "x27",
197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    };
198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return names[index];
199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static int ToAllocationIndex(Register reg) {
202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(reg.IsAllocatable());
203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    unsigned code = reg.code();
204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (code == kAllocatableContext) {
205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      return NumAllocatableRegisters() - 1;
206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return (code <= kAllocatableLowRangeEnd)
209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        ? code
210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        : code - kAllocatableRangeGapSize;
211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Register from_code(int code) {
214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Always return an X register.
21597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    return Register::Create(code, kXRegSizeInBits);
216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // End of V8 compatibility section -----------------------
219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstruct FPRegister : public CPURegister {
223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static FPRegister Create(unsigned code, unsigned size) {
224a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    return FPRegister(
225a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org        CPURegister::Create(code, size, CPURegister::kFPRegister));
226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  FPRegister() {
229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_code = 0;
230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_size = 0;
231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_type = CPURegister::kNoRegister;
232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
234a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  explicit FPRegister(const CPURegister& r) {
235a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    reg_code = r.reg_code;
236a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    reg_size = r.reg_size;
237a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    reg_type = r.reg_type;
238a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org    ASSERT(IsValidOrNone());
239a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  }
240a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org
241a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  FPRegister(const FPRegister& r) {  // NOLINT(runtime/explicit)
242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_code = r.reg_code;
243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_size = r.reg_size;
244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    reg_type = r.reg_type;
245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValidOrNone());
246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsValid() const {
249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsFPRegister() || IsNone());
250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return IsValidFPRegister();
251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static FPRegister SRegFromCode(unsigned code);
254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static FPRegister DRegFromCode(unsigned code);
255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Start of V8 compatibility section ---------------------
257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kMaxNumRegisters = kNumberOfFPRegisters;
258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Crankshaft can use all the FP registers except:
260486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  //   - d15 which is used to keep the 0 double value
261486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  //   - d30 which is used in crankshaft as a double scratch register
262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   - d31 which is used in the MacroAssembler as a double scratch register
263486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  static const unsigned kAllocatableLowRangeBegin = 0;
264486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  static const unsigned kAllocatableLowRangeEnd = 14;
265486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  static const unsigned kAllocatableHighRangeBegin = 16;
26663a7c9f848e755c52a37721debae242cf5d1682dmachenbach@chromium.org  static const unsigned kAllocatableHighRangeEnd = 28;
267486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org
26863a7c9f848e755c52a37721debae242cf5d1682dmachenbach@chromium.org  static const RegList kAllocatableFPRegisters = 0x1fff7fff;
269486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org
270486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  // Gap between low and high ranges.
271486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  static const int kAllocatableRangeGapSize =
272486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
273486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org
274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kMaxNumAllocatableRegisters =
275486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
276486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1);
277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
279486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  // Return true if the register is one that crankshaft can allocate.
280486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  bool IsAllocatable() const {
281486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    return (Bit() & kAllocatableFPRegisters) != 0;
282486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  }
283486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org
284486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org  static FPRegister FromAllocationIndex(unsigned int index) {
285486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    ASSERT(index < static_cast<unsigned>(NumAllocatableRegisters()));
286486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org
287486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    return (index <= kAllocatableLowRangeEnd)
288486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        ? from_code(index)
289486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        : from_code(index + kAllocatableRangeGapSize);
290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const char* AllocationIndexToString(int index) {
293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT((index >= 0) && (index < NumAllocatableRegisters()));
294486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    ASSERT((kAllocatableLowRangeBegin == 0) &&
295486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org           (kAllocatableLowRangeEnd == 14) &&
296486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org           (kAllocatableHighRangeBegin == 16) &&
29763a7c9f848e755c52a37721debae242cf5d1682dmachenbach@chromium.org           (kAllocatableHighRangeEnd == 28));
298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    const char* const names[] = {
299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
300486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org      "d8", "d9", "d10", "d11", "d12", "d13", "d14",
301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
30263a7c9f848e755c52a37721debae242cf5d1682dmachenbach@chromium.org      "d24", "d25", "d26", "d27", "d28"
303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    };
304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return names[index];
305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static int ToAllocationIndex(FPRegister reg) {
308486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    ASSERT(reg.IsAllocatable());
309486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    unsigned code = reg.code();
310486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org
311486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org    return (code <= kAllocatableLowRangeEnd)
312486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        ? code
313486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org        : code - kAllocatableRangeGapSize;
314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static FPRegister from_code(int code) {
317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Always return a D register.
31897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org    return FPRegister::Create(code, kDRegSizeInBits);
319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // End of V8 compatibility section -----------------------
321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSTATIC_ASSERT(sizeof(CPURegister) == sizeof(Register));
325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSTATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister));
326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
328fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#if defined(ARM64_DEFINE_REG_STATICS)
329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define INITIALIZE_REGISTER(register_class, name, code, size, type)      \
330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  const CPURegister init_##register_class##_##name = {code, size, type}; \
331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  const register_class& name = *reinterpret_cast<const register_class*>( \
332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                    &init_##register_class##_##name)
333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define ALIAS_REGISTER(register_class, alias, name)                       \
334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  const register_class& alias = *reinterpret_cast<const register_class*>( \
335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                     &init_##register_class##_##name)
336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#else
337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define INITIALIZE_REGISTER(register_class, name, code, size, type) \
338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  extern const register_class& name
339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define ALIAS_REGISTER(register_class, alias, name) \
340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  extern const register_class& alias
341fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#endif  // defined(ARM64_DEFINE_REG_STATICS)
342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// No*Reg is used to indicate an unused argument, or an error case. Note that
344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// these all compare equal (using the Is() method). The Register and FPRegister
345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// variants are provided for convenience.
346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgINITIALIZE_REGISTER(Register, NoReg, 0, 0, CPURegister::kNoRegister);
347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgINITIALIZE_REGISTER(FPRegister, NoFPReg, 0, 0, CPURegister::kNoRegister);
348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgINITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister);
349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// v8 compatibility.
351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgINITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister);
352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define DEFINE_REGISTERS(N)                                                  \
35497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  INITIALIZE_REGISTER(Register, w##N, N,                                     \
35597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                      kWRegSizeInBits, CPURegister::kRegister);              \
35697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  INITIALIZE_REGISTER(Register, x##N, N,                                     \
35797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                      kXRegSizeInBits, CPURegister::kRegister);
358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgREGISTER_CODE_LIST(DEFINE_REGISTERS)
359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#undef DEFINE_REGISTERS
360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
36197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.orgINITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits,
362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                    CPURegister::kRegister);
36397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.orgINITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits,
364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                    CPURegister::kRegister);
365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
36697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org#define DEFINE_FPREGISTERS(N)                                                  \
36797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  INITIALIZE_REGISTER(FPRegister, s##N, N,                                     \
36897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                      kSRegSizeInBits, CPURegister::kFPRegister);              \
36997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  INITIALIZE_REGISTER(FPRegister, d##N, N,                                     \
37097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                      kDRegSizeInBits, CPURegister::kFPRegister);
371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgREGISTER_CODE_LIST(DEFINE_FPREGISTERS)
372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#undef DEFINE_FPREGISTERS
373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#undef INITIALIZE_REGISTER
375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Registers aliases.
377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, ip0, x16);
378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, ip1, x17);
379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, wip0, w16);
380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, wip1, w17);
381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Root register.
382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, root, x26);
383f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, rr, x26);
384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Context pointer register.
385f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, cp, x27);
386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// We use a register as a JS stack pointer to overcome the restriction on the
387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// architectural SP alignment.
388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// We chose x28 because it is contiguous with the other specific purpose
389f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// registers.
390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSTATIC_ASSERT(kJSSPCode == 28);
391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, jssp, x28);
392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, wjssp, w28);
393f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, fp, x29);
394f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, lr, x30);
395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, xzr, x31);
396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgALIAS_REGISTER(Register, wzr, w31);
397f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Keeps the 0 double value.
399486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.orgALIAS_REGISTER(FPRegister, fp_zero, d15);
400486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org// Crankshaft double scratch register.
40163a7c9f848e755c52a37721debae242cf5d1682dmachenbach@chromium.orgALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d29);
40263a7c9f848e755c52a37721debae242cf5d1682dmachenbach@chromium.org// MacroAssembler double scratch registers.
40363a7c9f848e755c52a37721debae242cf5d1682dmachenbach@chromium.orgALIAS_REGISTER(FPRegister, fp_scratch, d30);
40463a7c9f848e755c52a37721debae242cf5d1682dmachenbach@chromium.orgALIAS_REGISTER(FPRegister, fp_scratch1, d30);
40563a7c9f848e755c52a37721debae242cf5d1682dmachenbach@chromium.orgALIAS_REGISTER(FPRegister, fp_scratch2, d31);
406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#undef ALIAS_REGISTER
408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgRegister GetAllocatableRegisterThatIsNotOneOf(Register reg1,
411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                              Register reg2 = NoReg,
412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                              Register reg3 = NoReg,
413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                              Register reg4 = NoReg);
414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// AreAliased returns true if any of the named registers overlap. Arguments set
417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// to NoReg are ignored. The system stack pointer may be specified.
418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgbool AreAliased(const CPURegister& reg1,
419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                const CPURegister& reg2,
420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                const CPURegister& reg3 = NoReg,
421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                const CPURegister& reg4 = NoReg,
422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                const CPURegister& reg5 = NoReg,
423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                const CPURegister& reg6 = NoReg,
424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                const CPURegister& reg7 = NoReg,
425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                const CPURegister& reg8 = NoReg);
426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// AreSameSizeAndType returns true if all of the specified registers have the
428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// same size, and are of the same type. The system stack pointer may be
429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// specified. Arguments set to NoReg are ignored, as are any subsequent
430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// arguments. At least one argument (reg1) must be valid (not NoCPUReg).
431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgbool AreSameSizeAndType(const CPURegister& reg1,
432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        const CPURegister& reg2,
433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        const CPURegister& reg3 = NoCPUReg,
434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        const CPURegister& reg4 = NoCPUReg,
435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        const CPURegister& reg5 = NoCPUReg,
436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        const CPURegister& reg6 = NoCPUReg,
437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        const CPURegister& reg7 = NoCPUReg,
438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        const CPURegister& reg8 = NoCPUReg);
439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtypedef FPRegister DoubleRegister;
442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
444f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// -----------------------------------------------------------------------------
445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Lists of registers.
446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass CPURegList {
447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  explicit CPURegList(CPURegister reg1,
449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                      CPURegister reg2 = NoCPUReg,
450f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                      CPURegister reg3 = NoCPUReg,
451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                      CPURegister reg4 = NoCPUReg)
452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()),
453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        size_(reg1.SizeInBits()), type_(reg1.type()) {
454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(AreSameSizeAndType(reg1, reg2, reg3, reg4));
455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValid());
456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
458f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CPURegList(CPURegister::RegisterType type, unsigned size, RegList list)
459f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      : list_(list), size_(size), type_(type) {
460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValid());
461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CPURegList(CPURegister::RegisterType type, unsigned size,
464f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             unsigned first_reg, unsigned last_reg)
465f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      : size_(size), type_(type) {
466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(((type == CPURegister::kRegister) &&
467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            (last_reg < kNumberOfRegisters)) ||
468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           ((type == CPURegister::kFPRegister) &&
469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            (last_reg < kNumberOfFPRegisters)));
470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(last_reg >= first_reg);
471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    list_ = (1UL << (last_reg + 1)) - 1;
472f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    list_ &= ~((1UL << first_reg) - 1);
473f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValid());
474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CPURegister::RegisterType type() const {
477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValid());
478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return type_;
479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  RegList list() const {
482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValid());
483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return list_;
484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
486bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  inline void set_list(RegList new_list) {
487bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    ASSERT(IsValid());
488bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    list_ = new_list;
489bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  }
490bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org
491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Combine another CPURegList into this one. Registers that already exist in
492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // this list are left unchanged. The type and size of the registers in the
493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // 'other' list must match those in this list.
494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Combine(const CPURegList& other);
495f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
496f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Remove every register in the other CPURegList from this one. Registers that
497202b1d8cd93e567672cc92f48fedc35989c47312machenbach@chromium.org  // do not exist in this list are ignored. The type of the registers in the
498202b1d8cd93e567672cc92f48fedc35989c47312machenbach@chromium.org  // 'other' list must match those in this list.
499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Remove(const CPURegList& other);
500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
501bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  // Variants of Combine and Remove which take CPURegisters.
502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Combine(const CPURegister& other);
503bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  void Remove(const CPURegister& other1,
504bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org              const CPURegister& other2 = NoCPUReg,
505bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org              const CPURegister& other3 = NoCPUReg,
506bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org              const CPURegister& other4 = NoCPUReg);
507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Variants of Combine and Remove which take a single register by its code;
509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the type and size of the register is inferred from this list.
510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Combine(int code);
511f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Remove(int code);
512f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
513f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Remove all callee-saved registers from the list. This can be useful when
514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // preparing registers for an AAPCS64 function call, for example.
515f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void RemoveCalleeSaved();
516f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
517f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CPURegister PopLowestIndex();
518f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CPURegister PopHighestIndex();
519f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
520f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // AAPCS64 callee-saved registers.
52197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static CPURegList GetCalleeSaved(unsigned size = kXRegSizeInBits);
52297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static CPURegList GetCalleeSavedFP(unsigned size = kDRegSizeInBits);
523f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // AAPCS64 caller-saved registers. Note that this includes lr.
52597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static CPURegList GetCallerSaved(unsigned size = kXRegSizeInBits);
52697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static CPURegList GetCallerSavedFP(unsigned size = kDRegSizeInBits);
527f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Registers saved as safepoints.
529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static CPURegList GetSafepointSavedRegisters();
530f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
531f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsEmpty() const {
532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValid());
533f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return list_ == 0;
534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
536bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org  bool IncludesAliasOf(const CPURegister& other1,
537bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org                       const CPURegister& other2 = NoCPUReg,
538bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org                       const CPURegister& other3 = NoCPUReg,
539bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org                       const CPURegister& other4 = NoCPUReg) const {
540f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValid());
541bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    RegList list = 0;
542bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    if (!other1.IsNone() && (other1.type() == type_)) list |= other1.Bit();
543bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    if (!other2.IsNone() && (other2.type() == type_)) list |= other2.Bit();
544bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    if (!other3.IsNone() && (other3.type() == type_)) list |= other3.Bit();
545bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    if (!other4.IsNone() && (other4.type() == type_)) list |= other4.Bit();
546bcc36723a2ace28fa3b0d7dd0d1de926d313fff9machenbach@chromium.org    return (list_ & list) != 0;
547f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
548f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
549f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int Count() const {
550f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValid());
551f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return CountSetBits(list_, kRegListSizeInBits);
552f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
553f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
554f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned RegisterSizeInBits() const {
555f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(IsValid());
556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return size_;
557f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
558f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned RegisterSizeInBytes() const {
560f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int size_in_bits = RegisterSizeInBits();
561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT((size_in_bits % kBitsPerByte) == 0);
562f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return size_in_bits / kBitsPerByte;
563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
564f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
565a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org  unsigned TotalSizeInBytes() const {
566a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org    ASSERT(IsValid());
567a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org    return RegisterSizeInBytes() * Count();
568a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org  }
569a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org
570f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org private:
571f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  RegList list_;
572f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned size_;
573f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  CPURegister::RegisterType type_;
574f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
575f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool IsValid() const {
576b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    const RegList kValidRegisters = 0x8000000ffffffff;
577b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    const RegList kValidFPRegisters = 0x0000000ffffffff;
578b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    switch (type_) {
579b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org      case CPURegister::kRegister:
580b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org        return (list_ & kValidRegisters) == list_;
581b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org      case CPURegister::kFPRegister:
582b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org        return (list_ & kValidFPRegisters) == list_;
583b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org      case CPURegister::kNoRegister:
584b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org        return list_ == 0;
585b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org      default:
586b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org        UNREACHABLE();
587b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org        return false;
588f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
589f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
590f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
591f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
592f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
593f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// AAPCS64 callee-saved registers.
594f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define kCalleeSaved CPURegList::GetCalleeSaved()
595f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define kCalleeSavedFP CPURegList::GetCalleeSavedFP()
596f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
597f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
598f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// AAPCS64 caller-saved registers. Note that this includes lr.
599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define kCallerSaved CPURegList::GetCallerSaved()
600f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define kCallerSavedFP CPURegList::GetCallerSavedFP()
601f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
602e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org// -----------------------------------------------------------------------------
603e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org// Immediates.
604e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.orgclass Immediate {
605e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org public:
606e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  template<typename T>
607e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  inline explicit Immediate(Handle<T> handle);
608e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
609e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // This is allowed to be an implicit constructor because Immediate is
610e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // a wrapper class that doesn't normally perform any type conversion.
611e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  template<typename T>
612e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  inline Immediate(T value);  // NOLINT(runtime/explicit)
613e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
614e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  template<typename T>
615e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  inline Immediate(T value, RelocInfo::Mode rmode);
616e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
617e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  int64_t value() const { return value_; }
618e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  RelocInfo::Mode rmode() const { return rmode_; }
619e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
620e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org private:
621e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  void InitializeHandle(Handle<Object> value);
622e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
623e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  int64_t value_;
624e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  RelocInfo::Mode rmode_;
625e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org};
626e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
627f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
628f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// -----------------------------------------------------------------------------
629f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Operands.
630f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst int kSmiShift = kSmiTagSize + kSmiShiftSize;
631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
632f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Represents an operand in a machine instruction.
634f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass Operand {
635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // TODO(all): If necessary, study more in details which methods
636f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // TODO(all): should be inlined or not.
637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
638f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // rm, {<shift> {#<shift_amount>}}
639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // where <shift> is one of {LSL, LSR, ASR, ROR}.
640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //       <shift_amount> is uint6_t.
641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This is allowed to be an implicit constructor because Operand is
642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // a wrapper class that doesn't normally perform any type conversion.
643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline Operand(Register reg,
644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 Shift shift = LSL,
645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 unsigned shift_amount = 0);  // NOLINT(runtime/explicit)
646f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
647f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // rm, <extend> {#<shift_amount>}
648f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}.
649f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //       <shift_amount> is uint2_t.
650f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline Operand(Register reg,
651f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 Extend extend,
652f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 unsigned shift_amount = 0);
653f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
654f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
655f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline explicit Operand(Handle<T> handle);
656f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
657f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Implicit constructor for all int types, ExternalReference, and Smi.
658f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  template<typename T>
659f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline Operand(T t);  // NOLINT(runtime/explicit)
660f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
661f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Implicit constructor for int types.
662e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  template<typename T>
663e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  inline Operand(T t, RelocInfo::Mode rmode);
664f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
665f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline bool IsImmediate() const;
666f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline bool IsShiftedRegister() const;
667f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline bool IsExtendedRegister() const;
668f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline bool IsZero() const;
669f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
670f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This returns an LSL shift (<= 4) operand as an equivalent extend operand,
671f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // which helps in the encoding of instructions that use the stack pointer.
672f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline Operand ToExtendedRegister() const;
673f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
674e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  inline Immediate immediate() const;
675e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  inline int64_t ImmediateValue() const;
676f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline Register reg() const;
677f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline Shift shift() const;
678f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline Extend extend() const;
679f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline unsigned shift_amount() const;
680f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
681f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Relocation information.
682874aad37f2a832804012c6f56739f4fc6c9283cdmachenbach@chromium.org  bool NeedsRelocation(const Assembler* assembler) const;
683f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
684f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Helpers
685f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Operand UntagSmi(Register smi);
686f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Operand UntagSmiAndScale(Register smi, int scale);
687f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
688f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org private:
689e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  Immediate immediate_;
690f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Register reg_;
691f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Shift shift_;
692f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Extend extend_;
693f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned shift_amount_;
694f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
695f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
697f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// MemOperand represents a memory operand in a load or store instruction.
698f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass MemOperand {
699f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
7005924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  inline explicit MemOperand();
701f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline explicit MemOperand(Register base,
702f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             ptrdiff_t offset = 0,
703f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             AddrMode addrmode = Offset);
704f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline explicit MemOperand(Register base,
705f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             Register regoffset,
706f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             Shift shift = LSL,
707f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             unsigned shift_amount = 0);
708f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline explicit MemOperand(Register base,
709f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             Register regoffset,
710f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             Extend extend,
711f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             unsigned shift_amount = 0);
712f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline explicit MemOperand(Register base,
713f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             const Operand& offset,
714f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             AddrMode addrmode = Offset);
715f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
716f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  const Register& base() const { return base_; }
717f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  const Register& regoffset() const { return regoffset_; }
718f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  ptrdiff_t offset() const { return offset_; }
719f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  AddrMode addrmode() const { return addrmode_; }
720f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Shift shift() const { return shift_; }
721f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Extend extend() const { return extend_; }
722f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned shift_amount() const { return shift_amount_; }
723f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline bool IsImmediateOffset() const;
724f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline bool IsRegisterOffset() const;
725f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline bool IsPreIndex() const;
726f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline bool IsPostIndex() const;
727f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // For offset modes, return the offset as an Operand. This helper cannot
729f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // handle indexed modes.
730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline Operand OffsetAsOperand() const;
731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
732f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org private:
733f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Register base_;
734f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Register regoffset_;
735f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  ptrdiff_t offset_;
736f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  AddrMode addrmode_;
737f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Shift shift_;
738f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Extend extend_;
739f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned shift_amount_;
740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
741f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
742f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
743f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// -----------------------------------------------------------------------------
744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Assembler.
745f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
746f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass Assembler : public AssemblerBase {
747f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
748f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Create an assembler. Instructions and relocation information are emitted
749f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // into a buffer, with the instructions starting from the beginning and the
750f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // relocation information starting from the end of the buffer. See CodeDesc
751f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // for a detailed comment on the layout (globals.h).
752f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
753f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // If the provided buffer is NULL, the assembler allocates and grows its own
754f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // buffer, and buffer_size determines the initial buffer size. The buffer is
755f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // owned by the assembler and deallocated upon destruction of the assembler.
756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
757f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // If the provided buffer is not NULL, the assembler uses the provided buffer
758f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // for code generation and assumes its size to be buffer_size. If the buffer
759f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // is too small, a fatal error occurs. No deallocation of the buffer is done
760f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // upon destruction of the assembler.
761f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Assembler(Isolate* arg_isolate, void* buffer, int buffer_size);
762f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
763f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  virtual ~Assembler();
764f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
76586b1631344aedfc4be5dcd5237e28d0b28e5974emachenbach@chromium.org  virtual void AbortedCodeGeneration() {
76686b1631344aedfc4be5dcd5237e28d0b28e5974emachenbach@chromium.org    num_pending_reloc_info_ = 0;
76786b1631344aedfc4be5dcd5237e28d0b28e5974emachenbach@chromium.org  }
76886b1631344aedfc4be5dcd5237e28d0b28e5974emachenbach@chromium.org
769f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // System functions ---------------------------------------------------------
770f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Start generating code from the beginning of the buffer, discarding any code
771f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // and data that has already been emitted into the buffer.
772f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
773f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // In order to avoid any accidental transfer of state, Reset ASSERTs that the
774f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // constant pool is not blocked.
775f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Reset();
776f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
777f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // GetCode emits any pending (non-emitted) code and fills the descriptor
778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // desc. GetCode() is idempotent; it returns the same result if no other
779f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Assembler functions are invoked in between GetCode() calls.
780f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
781f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The descriptor (desc) can be NULL. In that case, the code is finalized as
782f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // usual, but the descriptor is not populated.
783f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void GetCode(CodeDesc* desc);
784f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
785f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Insert the smallest number of nop instructions
786f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // possible to align the pc offset to a multiple
787f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // of m. m must be a power of 2 (>= 4).
788f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Align(int m);
789f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
790f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline void Unreachable();
791f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
792f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Label --------------------------------------------------------------------
793f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bind a label to the current pc. Note that labels can only be bound once,
794f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // and if labels are linked to other instructions, they _must_ be bound
795f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // before they go out of scope.
796f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bind(Label* label);
797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
798f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
799bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // RelocInfo and pools ------------------------------------------------------
800f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
801f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Record relocation information for current pc_.
802f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
803f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
804f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Return the address in the constant pool of the code target address used by
805f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the branch/call instruction at pc.
806f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Address target_pointer_address_at(Address pc);
807f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
808f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Read/Modify the code target address in the branch/call instruction at pc.
80997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  inline static Address target_address_at(Address pc,
81097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                          ConstantPoolArray* constant_pool);
81197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  inline static void set_target_address_at(Address pc,
81297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                           ConstantPoolArray* constant_pool,
8136a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           Address target,
8146a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           ICacheFlushMode icache_flush_mode =
8156a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                               FLUSH_ICACHE_IF_NEEDED);
81697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline Address target_address_at(Address pc, Code* code);
81797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  static inline void set_target_address_at(Address pc,
81897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org                                           Code* code,
8196a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           Address target,
8206a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                           ICacheFlushMode icache_flush_mode =
8216a4d394882dba70a85567fb90ffd4f428a9eb170machenbach@chromium.org                                               FLUSH_ICACHE_IF_NEEDED);
822f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Return the code target address at a call site from the return address of
824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // that call in the instruction stream.
825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Address target_address_from_return_address(Address pc);
826f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
827f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Given the address of the beginning of a call, return the address in the
828f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // instruction stream that call will return from.
829f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Address return_address_from_call_start(Address pc);
830f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
831f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This sets the branch destination (which is in the constant pool on ARM).
832f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This is for calls and branches within generated code.
833f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static void deserialization_set_special_target_at(
83497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org      Address constant_pool_entry, Code* code, Address target);
835f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
836f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // All addresses in the constant pool are the same size as pointers.
837f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kSpecialTargetSize = kPointerSize;
838f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
839f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The sizes of the call sequences emitted by MacroAssembler::Call.
840f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Wherever possible, use MacroAssembler::CallSize instead of these constants,
841f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // as it will choose the correct value for a given relocation mode.
842f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
843f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Without relocation:
844a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  //  movz  temp, #(target & 0x000000000000ffff)
845a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  //  movk  temp, #(target & 0x00000000ffff0000)
846a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  //  movk  temp, #(target & 0x0000ffff00000000)
847a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  //  blr   temp
848f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
849f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // With relocation:
850a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  //  ldr   temp, =target
851a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  //  blr   temp
852a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org  static const int kCallSizeWithoutRelocation = 4 * kInstructionSize;
853f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kCallSizeWithRelocation = 2 * kInstructionSize;
854f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
855f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Size of the generated code in bytes
856f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint64_t SizeOfGeneratedCode() const {
857f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_)));
858f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return pc_ - buffer_;
859f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
860f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
861f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Return the code size generated from label to the current position.
862f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  uint64_t SizeOfCodeGeneratedSince(const Label* label) {
863f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(label->is_bound());
864f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(pc_offset() >= label->pos());
865f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(pc_offset() < buffer_size_);
866f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return pc_offset() - label->pos();
867f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
868f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
869f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Check the size of the code generated since the given label. This function
870f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // is used primarily to work around comparisons between signed and unsigned
871f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // quantities, since V8 uses both.
872f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // TODO(jbramley): Work out what sign to use for these things and if possible,
873f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // change things to be consistent.
874f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void AssertSizeOfCodeGeneratedSince(const Label* label, ptrdiff_t size) {
875f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(size >= 0);
876f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(static_cast<uint64_t>(size) == SizeOfCodeGeneratedSince(label));
877f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
878f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
879f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Return the number of instructions generated from label to the
880f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // current position.
881f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int InstructionsGeneratedSince(const Label* label) {
882f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return SizeOfCodeGeneratedSince(label) / kInstructionSize;
883f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
884f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
885f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Number of instructions generated for the return sequence in
886f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FullCodeGenerator::EmitReturnSequence.
887f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kJSRetSequenceInstructions = 7;
888f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Distance between start of patched return sequence and the emitted address
889f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // to jump to.
890f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kPatchReturnSequenceAddressOffset =  0;
891f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kPatchDebugBreakSlotAddressOffset =  0;
892f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
893f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Number of instructions necessary to be able to later patch it to a call.
894d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  // See DebugCodegen::GenerateSlot() and
895d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  // BreakLocationIterator::SetDebugBreakAtSlot().
896f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kDebugBreakSlotInstructions = 4;
897f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kDebugBreakSlotLength =
898f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    kDebugBreakSlotInstructions * kInstructionSize;
899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
900f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstructionSize;
901f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
902f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Prevent contant pool emission until EndBlockConstPool is called.
903f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Call to this function can be nested but must be followed by an equal
904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // number of call to EndBlockConstpool.
905f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void StartBlockConstPool();
906f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
907f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Resume constant pool emission. Need to be called as many time as
908f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // StartBlockConstPool to have an effect.
909f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void EndBlockConstPool();
910f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  bool is_const_pool_blocked() const;
912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static bool IsConstantPoolAt(Instruction* instr);
913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static int ConstantPoolSizeAt(Instruction* instr);
914f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // See Assembler::CheckConstPool for more info.
915f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ConstantPoolMarker(uint32_t size);
91697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  void EmitPoolGuard();
917f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ConstantPoolGuard();
918f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
919bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // Prevent veneer pool emission until EndBlockVeneerPool is called.
920bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // Call to this function can be nested but must be followed by an equal
921bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // number of call to EndBlockConstpool.
922bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  void StartBlockVeneerPool();
923bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
924bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // Resume constant pool emission. Need to be called as many time as
925bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // StartBlockVeneerPool to have an effect.
926bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  void EndBlockVeneerPool();
927bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
928bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  bool is_veneer_pool_blocked() const {
929bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    return veneer_pool_blocked_nesting_ > 0;
930bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  }
931bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
932bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // Block/resume emission of constant pools and veneer pools.
933bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  void StartBlockPools() {
934bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    StartBlockConstPool();
935bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    StartBlockVeneerPool();
936bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  }
937bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  void EndBlockPools() {
938bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    EndBlockConstPool();
939bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    EndBlockVeneerPool();
940bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  }
941f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
942f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Debugging ----------------------------------------------------------------
943f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
944f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void RecordComment(const char* msg);
945f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int buffer_space() const;
946f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
947f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Mark address of the ExitJSFrame code.
948f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void RecordJSReturn();
949f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
950f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Mark address of a debug break slot.
951f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void RecordDebugBreakSlot();
952f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
953f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Record the emission of a constant pool.
954f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
95597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  // The emission of constant and veneer pools depends on the size of the code
95697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  // generated and the number of RelocInfo recorded.
957f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The Debug mechanism needs to map code offsets between two versions of a
958f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // function, compiled with and without debugger support (see for example
959f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Debug::PrepareForBreakPoints()).
960f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Compiling functions with debugger support generates additional code
961d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  // (DebugCodegen::GenerateSlot()). This may affect the emission of the pools
962d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  // and cause the version of the code with debugger support to have pools
963d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  // generated in different places.
96497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  // Recording the position and size of emitted pools allows to correctly
96597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  // compute the offset mappings between the different versions of a function in
96697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  // all situations.
967f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
96897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  // The parameter indicates the size of the pool (in bytes), including
969f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the marker and branch over the data.
970f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void RecordConstPool(int size);
971f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
972f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
973f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Instruction set functions ------------------------------------------------
974f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
975f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Branch / Jump instructions.
976f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // For branches offsets are scaled, i.e. they in instrcutions not in bytes.
977f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Branch to register.
978f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void br(const Register& xn);
979f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
980f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Branch-link to register.
981f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void blr(const Register& xn);
982f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
983f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Branch to register with return hint.
984f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ret(const Register& xn = lr);
985f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
986f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unconditional branch to label.
987f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void b(Label* label);
988f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
989f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional branch to label.
990f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void b(Label* label, Condition cond);
991f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
992f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unconditional branch to PC offset.
993f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void b(int imm26);
994f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
995f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional branch to PC offset.
996f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void b(int imm19, Condition cond);
997f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
998f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Branch-link to label / pc offset.
999f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bl(Label* label);
1000f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bl(int imm26);
1001f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1002f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Compare and branch to label / pc offset if zero.
1003f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cbz(const Register& rt, Label* label);
1004f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cbz(const Register& rt, int imm19);
1005f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1006f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Compare and branch to label / pc offset if not zero.
1007f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cbnz(const Register& rt, Label* label);
1008f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cbnz(const Register& rt, int imm19);
1009f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1010f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Test bit and branch to label / pc offset if zero.
1011f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void tbz(const Register& rt, unsigned bit_pos, Label* label);
1012f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void tbz(const Register& rt, unsigned bit_pos, int imm14);
1013f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1014f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Test bit and branch to label / pc offset if not zero.
1015f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void tbnz(const Register& rt, unsigned bit_pos, Label* label);
1016f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void tbnz(const Register& rt, unsigned bit_pos, int imm14);
1017f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1018f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Address calculation instructions.
1019f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Calculate a PC-relative address. Unlike for branches the offset in adr is
1020f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // unscaled (i.e. the result can be unaligned).
1021f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void adr(const Register& rd, Label* label);
1022f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void adr(const Register& rd, int imm21);
1023f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1024f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Data Processing instructions.
1025f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Add.
1026f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void add(const Register& rd,
1027f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Register& rn,
1028f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Operand& operand);
1029f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1030f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Add and update status flags.
1031f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void adds(const Register& rd,
1032f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1033f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand);
1034f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1035f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Compare negative.
1036f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cmn(const Register& rn, const Operand& operand);
1037f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1038f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Subtract.
1039f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sub(const Register& rd,
1040f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Register& rn,
1041f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Operand& operand);
1042f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1043f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Subtract and update status flags.
1044f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void subs(const Register& rd,
1045f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1046f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand);
1047f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1048f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Compare.
1049f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cmp(const Register& rn, const Operand& operand);
1050f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1051f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Negate.
1052f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void neg(const Register& rd,
1053f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Operand& operand);
1054f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1055f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Negate and update status flags.
1056f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void negs(const Register& rd,
1057f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand);
1058f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1059f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Add with carry bit.
1060f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void adc(const Register& rd,
1061f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Register& rn,
1062f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Operand& operand);
1063f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1064f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Add with carry bit and update status flags.
1065f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void adcs(const Register& rd,
1066f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1067f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand);
1068f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1069f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Subtract with carry bit.
1070f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sbc(const Register& rd,
1071f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Register& rn,
1072f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Operand& operand);
1073f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1074f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Subtract with carry bit and update status flags.
1075f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sbcs(const Register& rd,
1076f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1077f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand);
1078f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1079f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Negate with carry bit.
1080f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ngc(const Register& rd,
1081f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Operand& operand);
1082f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1083f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Negate with carry bit and update status flags.
1084f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ngcs(const Register& rd,
1085f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand);
1086f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1087f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Logical instructions.
1088f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitwise and (A & B).
1089f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void and_(const Register& rd,
1090f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1091f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand);
1092f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1093f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitwise and (A & B) and update status flags.
1094f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ands(const Register& rd,
1095f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1096f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand);
1097f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1098f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bit test, and set flags.
1099f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void tst(const Register& rn, const Operand& operand);
1100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bit clear (A & ~B).
1102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bic(const Register& rd,
1103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Register& rn,
1104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Operand& operand);
1105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bit clear (A & ~B) and update status flags.
1107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bics(const Register& rd,
1108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand);
1110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitwise or (A | B).
1112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void orr(const Register& rd, const Register& rn, const Operand& operand);
1113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitwise nor (A | ~B).
1115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void orn(const Register& rd, const Register& rn, const Operand& operand);
1116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitwise eor/xor (A ^ B).
1118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void eor(const Register& rd, const Register& rn, const Operand& operand);
1119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitwise enor/xnor (A ^ ~B).
1121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void eon(const Register& rd, const Register& rn, const Operand& operand);
1122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Logical shift left variable.
1124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void lslv(const Register& rd, const Register& rn, const Register& rm);
1125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Logical shift right variable.
1127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void lsrv(const Register& rd, const Register& rn, const Register& rm);
1128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Arithmetic shift right variable.
1130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void asrv(const Register& rd, const Register& rn, const Register& rm);
1131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Rotate right variable.
1133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void rorv(const Register& rd, const Register& rn, const Register& rm);
1134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitfield instructions.
1136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitfield move.
1137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bfm(const Register& rd,
1138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Register& rn,
1139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           unsigned immr,
1140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           unsigned imms);
1141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Signed bitfield move.
1143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sbfm(const Register& rd,
1144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            unsigned immr,
1146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            unsigned imms);
1147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unsigned bitfield move.
1149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ubfm(const Register& rd,
1150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            unsigned immr,
1152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            unsigned imms);
1153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bfm aliases.
1155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitfield insert.
1156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bfi(const Register& rd,
1157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const Register& rn,
1158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           unsigned lsb,
1159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           unsigned width) {
1160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(width >= 1);
1161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(lsb + width <= rn.SizeInBits());
1162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    bfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1);
1163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bitfield extract and insert low.
1166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void bfxil(const Register& rd,
1167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const Register& rn,
1168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             unsigned lsb,
1169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             unsigned width) {
1170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(width >= 1);
1171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(lsb + width <= rn.SizeInBits());
1172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    bfm(rd, rn, lsb, lsb + width - 1);
1173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Sbfm aliases.
1176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Arithmetic shift right.
1177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void asr(const Register& rd, const Register& rn, unsigned shift) {
1178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(shift < rd.SizeInBits());
1179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    sbfm(rd, rn, shift, rd.SizeInBits() - 1);
1180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Signed bitfield insert in zero.
1183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sbfiz(const Register& rd,
1184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const Register& rn,
1185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             unsigned lsb,
1186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             unsigned width) {
1187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(width >= 1);
1188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(lsb + width <= rn.SizeInBits());
1189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    sbfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1);
1190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Signed bitfield extract.
1193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sbfx(const Register& rd,
1194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            unsigned lsb,
1196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            unsigned width) {
1197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(width >= 1);
1198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(lsb + width <= rn.SizeInBits());
1199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    sbfm(rd, rn, lsb, lsb + width - 1);
1200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Signed extend byte.
1203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sxtb(const Register& rd, const Register& rn) {
1204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    sbfm(rd, rn, 0, 7);
1205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Signed extend halfword.
1208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sxth(const Register& rd, const Register& rn) {
1209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    sbfm(rd, rn, 0, 15);
1210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Signed extend word.
1213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sxtw(const Register& rd, const Register& rn) {
1214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    sbfm(rd, rn, 0, 31);
1215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Ubfm aliases.
1218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Logical shift left.
1219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void lsl(const Register& rd, const Register& rn, unsigned shift) {
1220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    unsigned reg_size = rd.SizeInBits();
1221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(shift < reg_size);
1222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1);
1223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Logical shift right.
1226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void lsr(const Register& rd, const Register& rn, unsigned shift) {
1227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(shift < rd.SizeInBits());
1228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ubfm(rd, rn, shift, rd.SizeInBits() - 1);
1229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unsigned bitfield insert in zero.
1232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ubfiz(const Register& rd,
1233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const Register& rn,
1234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             unsigned lsb,
1235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             unsigned width) {
1236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(width >= 1);
1237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(lsb + width <= rn.SizeInBits());
1238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ubfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1);
1239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unsigned bitfield extract.
1242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ubfx(const Register& rd,
1243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            unsigned lsb,
1245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            unsigned width) {
1246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(width >= 1);
1247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(lsb + width <= rn.SizeInBits());
1248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ubfm(rd, rn, lsb, lsb + width - 1);
1249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unsigned extend byte.
1252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void uxtb(const Register& rd, const Register& rn) {
1253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ubfm(rd, rn, 0, 7);
1254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unsigned extend halfword.
1257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void uxth(const Register& rd, const Register& rn) {
1258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ubfm(rd, rn, 0, 15);
1259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unsigned extend word.
1262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void uxtw(const Register& rd, const Register& rn) {
1263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ubfm(rd, rn, 0, 31);
1264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Extract.
1267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void extr(const Register& rd,
1268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rm,
1270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            unsigned lsb);
1271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional select: rd = cond ? rn : rm.
1273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void csel(const Register& rd,
1274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rm,
1276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            Condition cond);
1277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional select increment: rd = cond ? rn : rm + 1.
1279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void csinc(const Register& rd,
1280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const Register& rn,
1281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const Register& rm,
1282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             Condition cond);
1283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional select inversion: rd = cond ? rn : ~rm.
1285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void csinv(const Register& rd,
1286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const Register& rn,
1287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const Register& rm,
1288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             Condition cond);
1289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional select negation: rd = cond ? rn : -rm.
1291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void csneg(const Register& rd,
1292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const Register& rn,
1293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const Register& rm,
1294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             Condition cond);
1295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional set: rd = cond ? 1 : 0.
1297f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cset(const Register& rd, Condition cond);
1298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional set minus: rd = cond ? -1 : 0.
1300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void csetm(const Register& rd, Condition cond);
1301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional increment: rd = cond ? rn + 1 : rn.
1303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cinc(const Register& rd, const Register& rn, Condition cond);
1304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional invert: rd = cond ? ~rn : rn.
1306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cinv(const Register& rd, const Register& rn, Condition cond);
1307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional negate: rd = cond ? -rn : rn.
1309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cneg(const Register& rd, const Register& rn, Condition cond);
1310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Extr aliases.
1312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ror(const Register& rd, const Register& rs, unsigned shift) {
1313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    extr(rd, rs, rs, shift);
1314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional comparison.
1317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional compare negative.
1318f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ccmn(const Register& rn,
1319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand,
1320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            StatusFlags nzcv,
1321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            Condition cond);
1322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Conditional compare.
1324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ccmp(const Register& rn,
1325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Operand& operand,
1326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            StatusFlags nzcv,
1327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            Condition cond);
1328f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Multiplication.
1330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // 32 x 32 -> 32-bit and 64 x 64 -> 64-bit multiply.
1331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void mul(const Register& rd, const Register& rn, const Register& rm);
1332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // 32 + 32 x 32 -> 32-bit and 64 + 64 x 64 -> 64-bit multiply accumulate.
1334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void madd(const Register& rd,
1335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rm,
1337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& ra);
1338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // -(32 x 32) -> 32-bit and -(64 x 64) -> 64-bit multiply.
1340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void mneg(const Register& rd, const Register& rn, const Register& rm);
1341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // 32 - 32 x 32 -> 32-bit and 64 - 64 x 64 -> 64-bit multiply subtract.
1343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void msub(const Register& rd,
1344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rn,
1345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& rm,
1346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const Register& ra);
1347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // 32 x 32 -> 64-bit multiply.
1349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void smull(const Register& rd, const Register& rn, const Register& rm);
1350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Xd = bits<127:64> of Xn * Xm.
1352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void smulh(const Register& rd, const Register& rn, const Register& rm);
1353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Signed 32 x 32 -> 64-bit multiply and accumulate.
1355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void smaddl(const Register& rd,
1356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& rn,
1357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& rm,
1358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& ra);
1359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unsigned 32 x 32 -> 64-bit multiply and accumulate.
1361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void umaddl(const Register& rd,
1362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& rn,
1363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& rm,
1364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& ra);
1365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Signed 32 x 32 -> 64-bit multiply and subtract.
1367f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void smsubl(const Register& rd,
1368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& rn,
1369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& rm,
1370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& ra);
1371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unsigned 32 x 32 -> 64-bit multiply and subtract.
1373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void umsubl(const Register& rd,
1374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& rn,
1375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& rm,
1376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& ra);
1377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Signed integer divide.
1379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void sdiv(const Register& rd, const Register& rn, const Register& rm);
1380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Unsigned integer divide.
1382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void udiv(const Register& rd, const Register& rn, const Register& rm);
1383f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Bit count, bit reverse and endian reverse.
1385f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void rbit(const Register& rd, const Register& rn);
1386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void rev16(const Register& rd, const Register& rn);
1387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void rev32(const Register& rd, const Register& rn);
1388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void rev(const Register& rd, const Register& rn);
1389f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void clz(const Register& rd, const Register& rn);
1390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void cls(const Register& rd, const Register& rn);
1391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Memory instructions.
1393f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1394f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Load integer or FP register.
1395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ldr(const CPURegister& rt, const MemOperand& src);
1396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1397f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Store integer or FP register.
1398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void str(const CPURegister& rt, const MemOperand& dst);
1399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Load word with sign extension.
1401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ldrsw(const Register& rt, const MemOperand& src);
1402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Load byte.
1404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ldrb(const Register& rt, const MemOperand& src);
1405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Store byte.
1407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void strb(const Register& rt, const MemOperand& dst);
1408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Load byte with sign extension.
1410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ldrsb(const Register& rt, const MemOperand& src);
1411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Load half-word.
1413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ldrh(const Register& rt, const MemOperand& src);
1414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Store half-word.
1416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void strh(const Register& rt, const MemOperand& dst);
1417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Load half-word with sign extension.
1419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ldrsh(const Register& rt, const MemOperand& src);
1420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Load integer or FP register pair.
1422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ldp(const CPURegister& rt, const CPURegister& rt2,
1423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const MemOperand& src);
1424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Store integer or FP register pair.
1426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void stp(const CPURegister& rt, const CPURegister& rt2,
1427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org           const MemOperand& dst);
1428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Load word pair with sign extension.
1430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src);
1431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Load integer or FP register pair, non-temporal.
1433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ldnp(const CPURegister& rt, const CPURegister& rt2,
1434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const MemOperand& src);
1435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Store integer or FP register pair, non-temporal.
1437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void stnp(const CPURegister& rt, const CPURegister& rt2,
1438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org            const MemOperand& dst);
1439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1440e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // Load literal to register from a pc relative address.
1441e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  void ldr_pcrel(const CPURegister& rt, int imm19);
1442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1443e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  // Load literal to register.
1444e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  void ldr(const CPURegister& rt, const Immediate& imm);
1445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move instructions. The default shift of -1 indicates that the move
1447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // instruction will calculate an appropriate 16-bit immediate and left shift
1448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // that is equal to the 64-bit immediate argument. If an explicit left shift
1449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value.
1450f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
1451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // For movk, an explicit shift can be used to indicate which half word should
1452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant
1453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // half word with zero, whereas movk(x0, 0, 48) will overwrite the
1454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // most-significant.
1455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move and keep.
1457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void movk(const Register& rd, uint64_t imm, int shift = -1) {
1458f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    MoveWide(rd, imm, shift, MOVK);
1459f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move with non-zero.
1462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void movn(const Register& rd, uint64_t imm, int shift = -1) {
1463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    MoveWide(rd, imm, shift, MOVN);
1464f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1465f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move with zero.
1467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void movz(const Register& rd, uint64_t imm, int shift = -1) {
1468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    MoveWide(rd, imm, shift, MOVZ);
1469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Misc instructions.
1472f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Monitor debug-mode breakpoint.
1473f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void brk(int code);
1474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Halting debug-mode breakpoint.
1476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void hlt(int code);
1477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move register to register.
1479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void mov(const Register& rd, const Register& rn);
1480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move NOT(operand) to register.
1482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void mvn(const Register& rd, const Operand& operand);
1483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // System instructions.
1485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move to register from system register.
1486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void mrs(const Register& rt, SystemRegister sysreg);
1487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move from register to system register.
1489f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void msr(SystemRegister sysreg, const Register& rt);
1490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // System hint.
1492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void hint(SystemHint code);
1493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Data memory barrier
1495f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void dmb(BarrierDomain domain, BarrierType type);
1496f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Data synchronization barrier
1498f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void dsb(BarrierDomain domain, BarrierType type);
1499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Instruction synchronization barrier
1501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void isb();
1502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Alias for system instructions.
1504f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void nop() { hint(NOP); }
1505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Different nop operations are used by the code generator to detect certain
1507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // states of the generated code.
1508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  enum NopMarkerTypes {
1509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    DEBUG_BREAK_NOP,
1510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    INTERRUPT_CODE_NOP,
15119e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org    ADR_FAR_NOP,
1512f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    FIRST_NOP_MARKER = DEBUG_BREAK_NOP,
15139e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org    LAST_NOP_MARKER = ADR_FAR_NOP
1514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  };
1515f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1516f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void nop(NopMarkerTypes n) {
1517f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT((FIRST_NOP_MARKER <= n) && (n <= LAST_NOP_MARKER));
1518f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    mov(Register::XRegFromCode(n), Register::XRegFromCode(n));
1519f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1520f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1521f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP instructions.
1522f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move immediate to FP register.
1523f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmov(FPRegister fd, double imm);
1524381adef828187e237e8758ab730dee1c2834a0b3machenbach@chromium.org  void fmov(FPRegister fd, float imm);
1525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move FP register to register.
1527f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmov(Register rd, FPRegister fn);
1528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move register to FP register.
1530f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmov(FPRegister fd, Register rn);
1531f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move FP register to FP register.
1533f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmov(FPRegister fd, FPRegister fn);
1534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP add.
1536f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1538f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP subtract.
1539f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1540f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1541f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP multiply.
1542f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1543f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1544f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP fused multiply and add.
1545f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmadd(const FPRegister& fd,
1546f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const FPRegister& fn,
1547f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const FPRegister& fm,
1548f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const FPRegister& fa);
1549f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1550f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP fused multiply and subtract.
1551f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmsub(const FPRegister& fd,
1552f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const FPRegister& fn,
1553f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const FPRegister& fm,
1554f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const FPRegister& fa);
1555f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP fused multiply, add and negate.
1557f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fnmadd(const FPRegister& fd,
1558f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const FPRegister& fn,
1559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const FPRegister& fm,
1560f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const FPRegister& fa);
1561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1562f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP fused multiply, subtract and negate.
1563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fnmsub(const FPRegister& fd,
1564f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const FPRegister& fn,
1565f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const FPRegister& fm,
1566f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const FPRegister& fa);
1567f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1568f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP divide.
1569f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1570f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1571f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP maximum.
1572f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1573f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1574f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP minimum.
1575f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1576f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1577f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP maximum.
1578f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fmaxnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1579f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP minimum.
1581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fminnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1582f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1583f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP absolute.
1584f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fabs(const FPRegister& fd, const FPRegister& fn);
1585f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1586f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP negate.
1587f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fneg(const FPRegister& fd, const FPRegister& fn);
1588f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1589f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP square root.
1590f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fsqrt(const FPRegister& fd, const FPRegister& fn);
1591f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1592f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP round to integer (nearest with ties to away).
1593f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void frinta(const FPRegister& fd, const FPRegister& fn);
1594f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1595255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org  // FP round to integer (toward minus infinity).
1596255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org  void frintm(const FPRegister& fd, const FPRegister& fn);
1597255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org
1598f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP round to integer (nearest with ties to even).
1599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void frintn(const FPRegister& fd, const FPRegister& fn);
1600f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1601f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP round to integer (towards zero.)
1602f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void frintz(const FPRegister& fd, const FPRegister& fn);
1603f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1604f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP compare registers.
1605f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcmp(const FPRegister& fn, const FPRegister& fm);
1606f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1607f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP compare immediate.
1608f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcmp(const FPRegister& fn, double value);
1609f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1610f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP conditional compare.
1611f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fccmp(const FPRegister& fn,
1612f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const FPRegister& fm,
1613f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             StatusFlags nzcv,
1614f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             Condition cond);
1615f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1616f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP conditional select.
1617f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcsel(const FPRegister& fd,
1618f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const FPRegister& fn,
1619f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             const FPRegister& fm,
1620f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org             Condition cond);
1621f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1622f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Common FP Convert function
1623f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void FPConvertToInt(const Register& rd,
1624f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                      const FPRegister& fn,
1625f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                      FPIntegerConvertOp op);
1626f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1627f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP convert between single and double precision.
1628f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcvt(const FPRegister& fd, const FPRegister& fn);
1629f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1630f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert FP to unsigned integer (nearest with ties to away).
1631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcvtau(const Register& rd, const FPRegister& fn);
1632f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert FP to signed integer (nearest with ties to away).
1634f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcvtas(const Register& rd, const FPRegister& fn);
1635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1636f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert FP to unsigned integer (round towards -infinity).
1637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcvtmu(const Register& rd, const FPRegister& fn);
1638f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert FP to signed integer (round towards -infinity).
1640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcvtms(const Register& rd, const FPRegister& fn);
1641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert FP to unsigned integer (nearest with ties to even).
1643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcvtnu(const Register& rd, const FPRegister& fn);
1644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert FP to signed integer (nearest with ties to even).
1646f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcvtns(const Register& rd, const FPRegister& fn);
1647f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1648f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert FP to unsigned integer (round towards zero).
1649f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcvtzu(const Register& rd, const FPRegister& fn);
1650f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1651f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert FP to signed integer (rounf towards zero).
1652f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void fcvtzs(const Register& rd, const FPRegister& fn);
1653f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1654f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert signed integer or fixed point to FP.
1655f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
1656f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1657f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Convert unsigned integer or fixed point to FP.
1658f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
1659f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1660f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Instruction functions used only for test, debug, and patching.
1661f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Emit raw instructions in the instruction stream.
1662f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void dci(Instr raw_inst) { Emit(raw_inst); }
1663f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1664f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Emit 8 bits of data in the instruction stream.
1665f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void dc8(uint8_t data) { EmitData(&data, sizeof(data)); }
1666f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1667f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Emit 32 bits of data in the instruction stream.
1668f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void dc32(uint32_t data) { EmitData(&data, sizeof(data)); }
1669f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1670f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Emit 64 bits of data in the instruction stream.
1671f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void dc64(uint64_t data) { EmitData(&data, sizeof(data)); }
1672f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1673f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Copy a string into the instruction stream, including the terminating NULL
1674f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // character. The instruction pointer (pc_) is then aligned correctly for
1675f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // subsequent instructions.
1676f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void EmitStringData(const char * string) {
1677f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    size_t len = strlen(string) + 1;
1678f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(RoundUp(len, kInstructionSize) <= static_cast<size_t>(kGap));
1679f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    EmitData(string, len);
1680f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Pad with NULL characters until pc_ is aligned.
1681f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    const char pad[] = {'\0', '\0', '\0', '\0'};
1682f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    STATIC_ASSERT(sizeof(pad) == kInstructionSize);
1683f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    byte* next_pc = AlignUp(pc_, kInstructionSize);
1684f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    EmitData(&pad, next_pc - pc_);
1685f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1686f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1687f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Pseudo-instructions ------------------------------------------------------
1688f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1689fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Parameters are described in arm64/instructions-arm64.h.
1690f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void debug(const char* message, uint32_t code, Instr params = BREAK);
1691f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1692f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Required by V8.
1693f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void dd(uint32_t data) { dc32(data); }
1694f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void db(uint8_t data) { dc8(data); }
1695f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Code generation helpers --------------------------------------------------
1697f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1698f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  unsigned num_pending_reloc_info() const { return num_pending_reloc_info_; }
1699f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1700f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Instruction* InstructionAt(int offset) const {
1701f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return reinterpret_cast<Instruction*>(buffer_ + offset);
1702f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1703f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1704c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  ptrdiff_t InstructionOffset(Instruction* instr) const {
1705c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org    return reinterpret_cast<byte*>(instr) - buffer_;
1706c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  }
1707c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org
1708f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Register encoding.
1709f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr Rd(CPURegister rd) {
1710f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(rd.code() != kSPRegInternalCode);
1711f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return rd.code() << Rd_offset;
1712f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1713f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1714f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr Rn(CPURegister rn) {
1715f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(rn.code() != kSPRegInternalCode);
1716f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return rn.code() << Rn_offset;
1717f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1718f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1719f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr Rm(CPURegister rm) {
1720f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(rm.code() != kSPRegInternalCode);
1721f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return rm.code() << Rm_offset;
1722f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1723f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1724f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr Ra(CPURegister ra) {
1725f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(ra.code() != kSPRegInternalCode);
1726f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return ra.code() << Ra_offset;
1727f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1729f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr Rt(CPURegister rt) {
1730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(rt.code() != kSPRegInternalCode);
1731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return rt.code() << Rt_offset;
1732f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1733f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1734f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr Rt2(CPURegister rt2) {
1735f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(rt2.code() != kSPRegInternalCode);
1736f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return rt2.code() << Rt2_offset;
1737f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1738f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1739f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // These encoding functions allow the stack pointer to be encoded, and
1740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // disallow the zero register.
1741f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr RdSP(Register rd) {
1742f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(!rd.IsZero());
1743f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return (rd.code() & kRegCodeMask) << Rd_offset;
1744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1745f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1746f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr RnSP(Register rn) {
1747f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(!rn.IsZero());
1748f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    return (rn.code() & kRegCodeMask) << Rn_offset;
1749f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
1750f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1751f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Flags encoding.
1752f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr Flags(FlagsUpdate S);
1753f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr Cond(Condition cond);
1754f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1755f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // PC-relative address encoding.
1756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmPCRelAddress(int imm21);
1757f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1758f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Branch encoding.
1759f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmUncondBranch(int imm26);
1760f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmCondBranch(int imm19);
1761f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmCmpBranch(int imm19);
1762f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmTestBranch(int imm14);
1763f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmTestBranchBit(unsigned bit_pos);
1764f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1765f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Data Processing encoding.
1766f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr SF(Register rd);
1767f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmAddSub(int64_t imm);
1768f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmS(unsigned imms, unsigned reg_size);
1769f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmR(unsigned immr, unsigned reg_size);
1770f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmSetBits(unsigned imms, unsigned reg_size);
1771f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmRotate(unsigned immr, unsigned reg_size);
1772f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmLLiteral(int imm19);
1773f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr BitN(unsigned bitn, unsigned reg_size);
1774f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ShiftDP(Shift shift);
1775f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmDPShift(unsigned amount);
1776f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ExtendMode(Extend extend);
1777f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmExtendShift(unsigned left_shift);
1778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmCondCmp(unsigned imm);
1779f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr Nzcv(StatusFlags nzcv);
1780f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
17815924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  static bool IsImmAddSub(int64_t immediate);
17825924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org  static bool IsImmLogical(uint64_t value,
17835924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org                           unsigned width,
17845924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org                           unsigned* n,
17855924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org                           unsigned* imm_s,
17865924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org                           unsigned* imm_r);
17875924917d324a643d00a8aefee030bd4acea0de0bmachenbach@chromium.org
1788f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // MemOperand offset encoding.
1789f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmLSUnsigned(int imm12);
1790f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmLS(int imm9);
1791f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmLSPair(int imm7, LSDataSize size);
1792f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmShiftLS(unsigned shift_amount);
1793f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmException(int imm16);
1794f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmSystemRegister(int imm15);
1795f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmHint(int imm7);
1796f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmBarrierDomain(int imm2);
1797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmBarrierType(int imm2);
1798f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static LSDataSize CalcLSDataSize(LoadStoreOp op);
1799f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1800f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Move immediates encoding.
1801f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ImmMoveWide(uint64_t imm);
1802f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr ShiftMoveWide(int64_t shift);
1803f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1804f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP Immediates.
1805f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr ImmFP32(float imm);
1806f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static Instr ImmFP64(double imm);
1807f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr FPScale(unsigned scale);
1808f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1809f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // FP register type.
1810f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline static Instr FPType(FPRegister fd);
1811f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1812f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Class for scoping postponing the constant pool generation.
1813f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  class BlockConstPoolScope {
1814f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org   public:
1815f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1816f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      assem_->StartBlockConstPool();
1817f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
1818f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ~BlockConstPoolScope() {
1819f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      assem_->EndBlockConstPool();
1820f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
1821f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1822f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org   private:
1823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Assembler* assem_;
1824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1826f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  };
1827f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1828f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Check if is time to emit a constant pool.
1829f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CheckConstPool(bool force_emit, bool require_jump);
1830f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1831763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  // Allocate a constant pool of the correct size for the generated code.
18329fa619507474a4c1c21c6935b3209070bc13a218machenbach@chromium.org  Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
1833763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org
1834763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  // Generate the constant pool for the generated code.
1835763da4c1a1bd42dfafe0844b4c18f4882cc66352machenbach@chromium.org  void PopulateConstantPool(ConstantPoolArray* constant_pool);
1836bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
1837bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // Returns true if we should emit a veneer as soon as possible for a branch
1838bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // which can at most reach to specified pc.
1839bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  bool ShouldEmitVeneer(int max_reachable_pc,
1840bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org                        int margin = kVeneerDistanceMargin);
1841bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  bool ShouldEmitVeneers(int margin = kVeneerDistanceMargin) {
1842bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    return ShouldEmitVeneer(unresolved_branches_first_limit(), margin);
1843bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  }
1844bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
1845bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // The maximum code size generated for a veneer. Currently one branch
1846bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // instruction. This is for code size checking purposes, and can be extended
1847bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // in the future for example if we decide to add nops between the veneers.
1848bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  static const int kMaxVeneerCodeSize = 1 * kInstructionSize;
1849bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
185097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  void RecordVeneerPool(int location_offset, int size);
1851bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // Emits veneers for branches that are approaching their maximum range.
1852bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // If need_protection is true, the veneers are protected by a branch jumping
1853bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // over the code.
18549801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org  void EmitVeneers(bool force_emit, bool need_protection,
18559801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org                   int margin = kVeneerDistanceMargin);
185697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org  void EmitVeneersGuard() { EmitPoolGuard(); }
1857bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // Checks whether veneers need to be emitted at this point.
18589801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org  // If force_emit is set, a veneer is generated for *all* unresolved branches.
18599801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org  void CheckVeneerPool(bool force_emit, bool require_jump,
18609801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org                       int margin = kVeneerDistanceMargin);
1861bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
1862bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  class BlockPoolsScope {
1863bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org   public:
1864bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    explicit BlockPoolsScope(Assembler* assem) : assem_(assem) {
1865bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org      assem_->StartBlockPools();
1866bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    }
1867bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    ~BlockPoolsScope() {
1868bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org      assem_->EndBlockPools();
1869bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    }
1870bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
1871bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org   private:
1872bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    Assembler* assem_;
1873bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
1874bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope);
1875bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  };
1876bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
1877f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org protected:
1878f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const;
1879f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1880f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LoadStore(const CPURegister& rt,
1881f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 const MemOperand& addr,
1882f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 LoadStoreOp op);
1883f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static bool IsImmLSUnscaled(ptrdiff_t offset);
1884f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static bool IsImmLSScaled(ptrdiff_t offset, LSDataSize size);
1885f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1886f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Logical(const Register& rd,
1887f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org               const Register& rn,
1888f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org               const Operand& operand,
1889f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org               LogicalOp op);
1890f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LogicalImmediate(const Register& rd,
1891f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        const Register& rn,
1892f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        unsigned n,
1893f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        unsigned imm_s,
1894f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        unsigned imm_r,
1895f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                        LogicalOp op);
1896f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1897f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ConditionalCompare(const Register& rn,
1898f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                          const Operand& operand,
1899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                          StatusFlags nzcv,
1900f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                          Condition cond,
1901f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                          ConditionalCompareOp op);
1902f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static bool IsImmConditionalCompare(int64_t immediate);
1903f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void AddSubWithCarry(const Register& rd,
1905f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                       const Register& rn,
1906f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                       const Operand& operand,
1907f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                       FlagsUpdate S,
1908f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                       AddSubWithCarryOp op);
1909f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1910f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Functions for emulating operands not directly supported by the instruction
1911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // set.
1912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void EmitShift(const Register& rd,
1913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 const Register& rn,
1914f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 Shift shift,
1915f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                 unsigned amount);
1916f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void EmitExtendShift(const Register& rd,
1917f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                       const Register& rn,
1918f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                       Extend extend,
1919f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                       unsigned left_shift);
1920f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1921f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void AddSub(const Register& rd,
1922f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Register& rn,
1923f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              const Operand& operand,
1924f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              FlagsUpdate S,
1925f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org              AddSubOp op);
1926f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1927f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static bool IsImmFP32(float imm);
1928f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static bool IsImmFP64(double imm);
1929f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1930f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified
1931f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // registers. Only simple loads are supported; sign- and zero-extension (such
1932f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // as in LDPSW_x or LDRB_w) are not supported.
1933f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline LoadStoreOp LoadOpFor(const CPURegister& rt);
1934f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline LoadStorePairOp LoadPairOpFor(const CPURegister& rt,
1935f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                              const CPURegister& rt2);
1936f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline LoadStoreOp StoreOpFor(const CPURegister& rt);
1937f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline LoadStorePairOp StorePairOpFor(const CPURegister& rt,
1938f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                               const CPURegister& rt2);
1939f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline LoadStorePairNonTemporalOp LoadPairNonTemporalOpFor(
1940f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    const CPURegister& rt, const CPURegister& rt2);
1941f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static inline LoadStorePairNonTemporalOp StorePairNonTemporalOpFor(
1942f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    const CPURegister& rt, const CPURegister& rt2);
1943e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt);
1944f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1945f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Remove the specified branch from the unbound label link chain.
1946f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // If available, a veneer for this label can be used for other branches in the
1947f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // chain if the link chain cannot be fixed up without this branch.
1948f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void RemoveBranchFromLabelLinkChain(Instruction* branch,
1949f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                      Label* label,
1950f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                      Instruction* label_veneer = NULL);
1951f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
1952f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org private:
1953f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Instruction helpers.
1954f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void MoveWide(const Register& rd,
1955f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                uint64_t imm,
1956f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                int shift,
1957f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                MoveWideImmediateOp mov_op);
1958f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void DataProcShiftedRegister(const Register& rd,
1959f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               const Register& rn,
1960f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               const Operand& operand,
1961f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               FlagsUpdate S,
1962f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               Instr op);
1963f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void DataProcExtendedRegister(const Register& rd,
1964f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                const Register& rn,
1965f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                const Operand& operand,
1966f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                FlagsUpdate S,
1967f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                Instr op);
1968f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LoadStorePair(const CPURegister& rt,
1969f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     const CPURegister& rt2,
1970f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     const MemOperand& addr,
1971f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     LoadStorePairOp op);
1972f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void LoadStorePairNonTemporal(const CPURegister& rt,
1973f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                const CPURegister& rt2,
1974f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                const MemOperand& addr,
1975f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                LoadStorePairNonTemporalOp op);
1976f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void ConditionalSelect(const Register& rd,
1977f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                         const Register& rn,
1978f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                         const Register& rm,
1979f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                         Condition cond,
1980f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                         ConditionalSelectOp op);
1981f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void DataProcessing1Source(const Register& rd,
1982f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             const Register& rn,
1983f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             DataProcessing1SourceOp op);
1984f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void DataProcessing3Source(const Register& rd,
1985f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             const Register& rn,
1986f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             const Register& rm,
1987f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             const Register& ra,
1988f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                             DataProcessing3SourceOp op);
1989f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void FPDataProcessing1Source(const FPRegister& fd,
1990f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               const FPRegister& fn,
1991f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               FPDataProcessing1SourceOp op);
1992f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void FPDataProcessing2Source(const FPRegister& fd,
1993f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               const FPRegister& fn,
1994f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               const FPRegister& fm,
1995f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               FPDataProcessing2SourceOp op);
1996f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void FPDataProcessing3Source(const FPRegister& fd,
1997f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               const FPRegister& fn,
1998f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               const FPRegister& fm,
1999f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               const FPRegister& fa,
2000f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                               FPDataProcessing3SourceOp op);
2001f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2002f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Label helpers.
2003f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2004f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Return an offset for a label-referencing instruction, typically a branch.
2005f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int LinkAndGetByteOffsetTo(Label* label);
2006f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2007f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // This is the same as LinkAndGetByteOffsetTo, but return an offset
2008f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // suitable for fields that take instruction offsets.
2009f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline int LinkAndGetInstructionOffsetTo(Label* label);
2010f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2011f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kStartOfLabelLinkChain = 0;
2012f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2013f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Verify that a label's link chain is intact.
2014f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CheckLabelLinkChain(Label const * label);
2015f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2016f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void RecordLiteral(int64_t imm, unsigned size);
2017f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2018f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Postpone the generation of the constant pool for the specified number of
2019f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // instructions.
2020f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void BlockConstPoolFor(int instructions);
2021f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2022f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Emit the instruction at pc_.
2023f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void Emit(Instr instruction) {
2024f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    STATIC_ASSERT(sizeof(*pc_) == 1);
2025f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    STATIC_ASSERT(sizeof(instruction) == kInstructionSize);
2026f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_));
2027f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2028f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    memcpy(pc_, &instruction, sizeof(instruction));
2029f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    pc_ += sizeof(instruction);
2030f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CheckBuffer();
2031f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
2032f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2033f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Emit data inline in the instruction stream.
2034f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void EmitData(void const * data, unsigned size) {
2035f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(sizeof(*pc_) == 1);
2036f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT((pc_ + size) <= (buffer_ + buffer_size_));
2037f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2038f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // TODO(all): Somehow register we have some data here. Then we can
2039f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // disassemble it correctly.
2040f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    memcpy(pc_, data, size);
2041f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    pc_ += size;
2042f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CheckBuffer();
2043f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
2044f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2045f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void GrowBuffer();
2046c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  void CheckBufferSpace();
2047f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void CheckBuffer();
2048f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2049bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // Pc offset of the next constant pool check.
2050bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  int next_constant_pool_check_;
2051f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2052f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Constant pool generation
2053f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Pools are emitted in the instruction stream, preferably after unconditional
2054f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // jumps or after returns from functions (in dead code locations).
2055f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // If a long code sequence does not contain unconditional jumps, it is
2056f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // necessary to emit the constant pool before the pool gets too far from the
2057f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // location it is accessed from. In this case, we emit a jump over the emitted
2058f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // constant pool.
2059f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Constants in the pool may be addresses of functions that gets relocated;
2060f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // if so, a relocation info entry is associated to the constant pool entry.
2061f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2062f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Repeated checking whether the constant pool should be emitted is rather
2063f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // expensive. By default we only check again once a number of instructions
2064f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // has been generated. That also means that the sizing of the buffers is not
2065f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // an exact science, and that we rely on some slop to not overrun buffers.
2066bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  static const int kCheckConstPoolIntervalInst = 128;
2067bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  static const int kCheckConstPoolInterval =
2068bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    kCheckConstPoolIntervalInst * kInstructionSize;
2069f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2070f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Constants in pools are accessed via pc relative addressing, which can
2071f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // reach +/-4KB thereby defining a maximum distance between the instruction
2072f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // and the accessed constant.
2073bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  static const int kMaxDistToConstPool = 4 * KB;
2074bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  static const int kMaxNumPendingRelocInfo =
2075bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    kMaxDistToConstPool / kInstructionSize;
2076f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2077f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2078f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Average distance beetween a constant pool and the first instruction
2079f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // accessing the constant pool. Longer distance should result in less I-cache
2080f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // pollution.
2081f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // In practice the distance will be smaller since constant pool emission is
2082f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // forced after function return and sometimes after unconditional branches.
2083bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  static const int kAvgDistToConstPool =
2084bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    kMaxDistToConstPool - kCheckConstPoolInterval;
2085f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2086f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Emission of the constant pool may be blocked in some code sequences.
2087f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int const_pool_blocked_nesting_;  // Block emission if this is not zero.
2088f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int no_const_pool_before_;  // Block emission before this pc offset.
2089f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2090f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Keep track of the first instruction requiring a constant pool entry
2091f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // since the previous constant pool was emitted.
2092f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int first_const_pool_use_;
2093f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2094bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // Emission of the veneer pools may be blocked in some code sequences.
2095bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  int veneer_pool_blocked_nesting_;  // Block emission if this is not zero.
2096bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
2097f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Relocation info generation
2098f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Each relocation is encoded as a variable size value
2099f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
2100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  RelocInfoWriter reloc_info_writer;
2101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Relocation info records are also used during code generation as temporary
2103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // containers for constants and code target addresses until they are emitted
2104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // to the constant pool. These pending relocation info records are temporarily
2105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // stored in a separate buffer until a constant pool is emitted.
2106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // If every instruction in a long sequence is accessing the pool, we need one
2107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // pending relocation entry per instruction.
2108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the buffer of pending relocation info
2110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo];
2111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // number of pending reloc info entries in the buffer
2112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  int num_pending_reloc_info_;
2113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Relocation for a type-recording IC has the AST id added to it.  This
2115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // member variable is a way to pass the information from the call site to
2116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the relocation info.
2117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  TypeFeedbackId recorded_ast_id_;
2118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline TypeFeedbackId RecordedAstId();
2120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  inline void ClearRecordedAstId();
2121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org protected:
2123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Record the AST id of the CallIC being compiled, so that it can be placed
2124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // in the relocation information.
2125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void SetRecordedAstId(TypeFeedbackId ast_id) {
2126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(recorded_ast_id_.IsNone());
2127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    recorded_ast_id_ = ast_id;
2128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
2129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Code generation
2131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The relocation writer's position is at least kGap bytes below the end of
2132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the generated instructions. This is so that multi-instruction sequences do
2133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // not have to check for overflow. The same is true for writes of large
2134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // relocation info entries, and debug strings encoded in the instruction
2135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // stream.
2136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  static const int kGap = 128;
2137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
2139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  class FarBranchInfo {
2140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org   public:
2141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    FarBranchInfo(int offset, Label* label)
2142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        : pc_offset_(offset), label_(label) {}
2143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Offset of the branch in the code generation buffer.
2144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int pc_offset_;
2145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // The label branched to.
2146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    Label* label_;
2147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  };
2148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org protected:
2150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Information about unresolved (forward) branches.
2151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The Assembler is only allowed to delete out-of-date information from here
2152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // after a label is bound. The MacroAssembler uses this information to
2153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // generate veneers.
2154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //
2155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The second member gives information about the unresolved branch. The first
2156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // member of the pair is the maximum offset that the branch can reach in the
2157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // buffer. The map is sorted according to this reachable offset, allowing to
2158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // easily check when veneers need to be emitted.
2159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Note that the maximum reachable offset (first member of the pairs) should
2160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // always be positive but has the same type as the return value for
2161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // pc_offset() for convenience.
2162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  std::multimap<int, FarBranchInfo> unresolved_branches_;
2163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2164bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // We generate a veneer for a branch if we reach within this distance of the
2165bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // limit of the range.
2166bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  static const int kVeneerDistanceMargin = 1 * KB;
2167bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // The factor of 2 is a finger in the air guess. With a default margin of
2168bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // 1KB, that leaves us an addional 256 instructions to avoid generating a
2169bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // protective branch.
2170bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  static const int kVeneerNoProtectionFactor = 2;
2171bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  static const int kVeneerDistanceCheckMargin =
2172bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    kVeneerNoProtectionFactor * kVeneerDistanceMargin;
2173bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  int unresolved_branches_first_limit() const {
2174bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    ASSERT(!unresolved_branches_.empty());
2175bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org    return unresolved_branches_.begin()->first;
2176bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  }
2177bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // This is similar to next_constant_pool_check_ and helps reduce the overhead
2178bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // of checking for veneer pools.
2179bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // It is maintained to the closest unresolved branch limit minus the maximum
2180bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  // veneer margin (or kMaxInt if there are no unresolved branches).
2181bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org  int next_veneer_pool_check_;
2182bc176057ae476990672de915df235c9aeadc8521titzer@chromium.org
2183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org private:
2184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // If a veneer is emitted for a branch instruction, that instruction must be
2185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // removed from the associated label's link chain so that the assembler does
2186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // not later attempt (likely unsuccessfully) to patch it to branch directly to
2187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the label.
2188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  void DeleteUnresolvedBranchInfoForLabel(Label* label);
2189c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  // This function deletes the information related to the label by traversing
2190c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  // the label chain, and for each PC-relative instruction in the chain checking
2191c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  // if pending unresolved information exists. Its complexity is proportional to
2192c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  // the length of the label chain.
2193c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org  void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label);
2194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org private:
2196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  PositionsRecorder positions_recorder_;
2197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  friend class PositionsRecorder;
2198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  friend class EnsureSpace;
2199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
2200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass PatchingAssembler : public Assembler {
2202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
2203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Create an Assembler with a buffer starting at 'start'.
2204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The buffer size is
2205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   size of instructions to patch + kGap
2206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Where kGap is the distance from which the Assembler tries to grow the
2207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // buffer.
2208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // If more or fewer instructions than expected are generated or if some
2209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // relocation information takes space in the buffer, the PatchingAssembler
2210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // will crash trying to grow the buffer.
2211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  PatchingAssembler(Instruction* start, unsigned count)
2212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    : Assembler(NULL,
2213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                reinterpret_cast<byte*>(start),
2214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                count * kInstructionSize + kGap) {
22156b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org    StartBlockPools();
2216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
2217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  PatchingAssembler(byte* start, unsigned count)
2219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    : Assembler(NULL, start, count * kInstructionSize + kGap) {
2220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Block constant pool emission.
22216b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org    StartBlockPools();
2222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
2223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  ~PatchingAssembler() {
2225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Const pool should still be blocked.
2226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(is_const_pool_blocked());
22276b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org    EndBlockPools();
2228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Verify we have generated the number of instruction we expected.
2229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT((pc_offset() + kGap) == buffer_size_);
2230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Verify no relocation information has been emitted.
2231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    ASSERT(num_pending_reloc_info() == 0);
2232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Flush the Instruction cache.
2233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    size_t length = buffer_size_ - kGap;
2234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CPU::FlushICache(buffer_, length);
2235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
22369e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org
22379e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  static const int kMovInt64NInstrs = 4;
22389e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  void MovInt64(const Register& rd, int64_t imm);
22399e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org
22409e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  // See definition of PatchAdrFar() for details.
22419e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  static const int kAdrFarPatchableNNops = kMovInt64NInstrs - 1;
22429e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 3;
22439e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  void PatchAdrFar(Instruction* target);
2244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
2245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass EnsureSpace BASE_EMBEDDED {
2248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public:
2249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  explicit EnsureSpace(Assembler* assembler) {
2250c2e08d7d6b03e672e13fc3bf274a292009decce6machenbach@chromium.org    assembler->CheckBufferSpace();
2251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
2252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org};
2253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} }  // namespace v8::internal
2255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
2256fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#endif  // V8_ARM64_ASSEMBLER_ARM64_H_
2257