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