1b78f13911bfe6eda303e91ef215c87a165aae8aeAlexandre Rames// Copyright 2015, VIXL authors
2ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// All rights reserved.
3ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
4ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// Redistribution and use in source and binary forms, with or without
5ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// modification, are permitted provided that the following conditions are met:
6ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
7ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions of source code must retain the above copyright notice,
8ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer.
9ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Redistributions in binary form must reproduce the above copyright notice,
10ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     this list of conditions and the following disclaimer in the documentation
11ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     and/or other materials provided with the distribution.
12ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//   * Neither the name of ARM Limited nor the names of its contributors may be
13ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     used to endorse or promote products derived from this software without
14ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//     specific prior written permission.
15ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl//
16ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2778973f258039f6e96eba85f1b5ecdb14b3c51dbbPierre Langlois#include <cctype>
28684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl
29b49bdb7996e603555eba4c8b56c7325e3e737ab6Alexandre Rames#include "macro-assembler-aarch64.h"
305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
31ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlnamespace vixl {
3288c46b84df005638546de5e4e965bdcc31352f48Pierre Langloisnamespace aarch64 {
33ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
34c68cb64496485710cdb5b8480f8fee287058c93farmvixl
355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid Pool::Release() {
365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (--monitor_ == 0) {
375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // Ensure the pool has not been blocked for too long.
3888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(masm_->GetCursorOffset() < checkpoint_);
395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid Pool::SetNextCheckpoint(ptrdiff_t checkpoint) {
445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  masm_->checkpoint_ = std::min(masm_->checkpoint_, checkpoint);
455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  checkpoint_ = checkpoint;
465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
496e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlLiteralPool::LiteralPool(MacroAssembler* masm)
500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    : Pool(masm),
510f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      size_(0),
520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      first_use_(-1),
530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      recommended_checkpoint_(kNoCheckpointRequired) {}
54c68cb64496485710cdb5b8480f8fee287058c93farmvixl
55c68cb64496485710cdb5b8480f8fee287058c93farmvixl
56c68cb64496485710cdb5b8480f8fee287058c93farmvixlLiteralPool::~LiteralPool() {
57c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(IsEmpty());
58c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!IsBlocked());
59db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  for (std::vector<RawLiteral*>::iterator it = deleted_on_destruction_.begin();
60db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl       it != deleted_on_destruction_.end();
61db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl       it++) {
62db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    delete *it;
63db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  }
64c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
65c68cb64496485710cdb5b8480f8fee287058c93farmvixl
66c68cb64496485710cdb5b8480f8fee287058c93farmvixl
67c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid LiteralPool::Reset() {
681bce007699e07bd855b7d194ca93fa5504a73edaPierre Langlois  std::vector<RawLiteral *>::iterator it, end;
69c68cb64496485710cdb5b8480f8fee287058c93farmvixl  for (it = entries_.begin(), end = entries_.end(); it != end; ++it) {
70db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    RawLiteral* literal = *it;
71db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    if (literal->deletion_policy_ == RawLiteral::kDeletedOnPlacementByPool) {
72db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      delete literal;
73db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    }
74c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
75c68cb64496485710cdb5b8480f8fee287058c93farmvixl  entries_.clear();
765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  size_ = 0;
77c68cb64496485710cdb5b8480f8fee287058c93farmvixl  first_use_ = -1;
785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Pool::Reset();
795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  recommended_checkpoint_ = kNoCheckpointRequired;
80c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
81c68cb64496485710cdb5b8480f8fee287058c93farmvixl
82c68cb64496485710cdb5b8480f8fee287058c93farmvixl
83c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid LiteralPool::CheckEmitFor(size_t amount, EmitOption option) {
84c68cb64496485710cdb5b8480f8fee287058c93farmvixl  if (IsEmpty() || IsBlocked()) return;
85c68cb64496485710cdb5b8480f8fee287058c93farmvixl
8688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ptrdiff_t distance = masm_->GetCursorOffset() + amount - first_use_;
87c68cb64496485710cdb5b8480f8fee287058c93farmvixl  if (distance >= kRecommendedLiteralPoolRange) {
88c68cb64496485710cdb5b8480f8fee287058c93farmvixl    Emit(option);
89c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
90c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
91c68cb64496485710cdb5b8480f8fee287058c93farmvixl
92c68cb64496485710cdb5b8480f8fee287058c93farmvixl
93896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouvelivoid LiteralPool::CheckEmitForBranch(size_t range) {
94896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  if (IsEmpty() || IsBlocked()) return;
95896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  if (GetMaxSize() >= range) Emit();
96896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli}
97896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli
9807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames// We use a subclass to access the protected `ExactAssemblyScope` constructor
9907d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames// giving us control over the pools. This allows us to use this scope within
10007d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames// code emitting pools without creating a circular dependency.
10107d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames// We keep the constructor private to restrict usage of this helper class.
10207d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Ramesclass ExactAssemblyScopeWithoutPoolsCheck : public ExactAssemblyScope {
10307d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames private:
10407d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  ExactAssemblyScopeWithoutPoolsCheck(MacroAssembler* masm, size_t size)
10507d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames      : ExactAssemblyScope(masm,
10607d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames                           size,
10707d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames                           ExactAssemblyScope::kExactSize,
10807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames                           ExactAssemblyScope::kIgnorePools) {}
10907d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames
11007d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  friend void LiteralPool::Emit(LiteralPool::EmitOption);
11107d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  friend void VeneerPool::Emit(VeneerPool::EmitOption, size_t);
11207d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames};
11307d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames
11407d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames
115c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid LiteralPool::Emit(EmitOption option) {
116c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // There is an issue if we are asked to emit a blocked or empty pool.
117c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!IsBlocked());
118c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!IsEmpty());
119c68cb64496485710cdb5b8480f8fee287058c93farmvixl
12088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  size_t pool_size = GetSize();
121c68cb64496485710cdb5b8480f8fee287058c93farmvixl  size_t emit_size = pool_size;
122c68cb64496485710cdb5b8480f8fee287058c93farmvixl  if (option == kBranchRequired) emit_size += kInstructionSize;
123c68cb64496485710cdb5b8480f8fee287058c93farmvixl  Label end_of_pool;
124c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(emit_size % kInstructionSize == 0);
126de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  {
127de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    CodeBufferCheckScope guard(masm_,
128de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                               emit_size,
129de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                               CodeBufferCheckScope::kCheck,
130de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                               CodeBufferCheckScope::kExactSize);
131de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames#ifdef VIXL_DEBUG
132de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    // Also explicitly disallow usage of the `MacroAssembler` here.
133de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    masm_->SetAllowMacroInstructions(false);
134de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames#endif
135de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    if (option == kBranchRequired) {
13607d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames      ExactAssemblyScopeWithoutPoolsCheck guard(masm_, kInstructionSize);
137de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      masm_->b(&end_of_pool);
138de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    }
139c68cb64496485710cdb5b8480f8fee287058c93farmvixl
140de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    {
141de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      // Marker indicating the size of the literal pool in 32-bit words.
142de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      VIXL_ASSERT((pool_size % kWRegSizeInBytes) == 0);
14307d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames      ExactAssemblyScopeWithoutPoolsCheck guard(masm_, kInstructionSize);
144de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      masm_->ldr(xzr, static_cast<int>(pool_size / kWRegSizeInBytes));
145de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    }
146c68cb64496485710cdb5b8480f8fee287058c93farmvixl
147de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    // Now populate the literal pool.
1481bce007699e07bd855b7d194ca93fa5504a73edaPierre Langlois    std::vector<RawLiteral *>::iterator it, end;
149de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    for (it = entries_.begin(), end = entries_.end(); it != end; ++it) {
150de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      VIXL_ASSERT((*it)->IsUsed());
151de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      masm_->place(*it);
152de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    }
153c68cb64496485710cdb5b8480f8fee287058c93farmvixl
154de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    if (option == kBranchRequired) masm_->bind(&end_of_pool);
155de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames#ifdef VIXL_DEBUG
156de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    masm_->SetAllowMacroInstructions(true);
157de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames#endif
158de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  }
159c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Reset();
1615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
164db6443499376478f5281607a3923e6ffc4c8d8ecarmvixlvoid LiteralPool::AddEntry(RawLiteral* literal) {
165db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  // A literal must be registered immediately before its first use. Here we
166db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  // cannot control that it is its first use, but we check no code has been
167db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  // emitted since its last use.
16888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(masm_->GetCursorOffset() == literal->GetLastUse());
1695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
17088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  UpdateFirstUse(masm_->GetCursorOffset());
17188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(masm_->GetCursorOffset() >= first_use_);
1725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  entries_.push_back(literal);
17388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  size_ += literal->GetSize();
174db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl}
175db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl
1765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
177db6443499376478f5281607a3923e6ffc4c8d8ecarmvixlvoid LiteralPool::UpdateFirstUse(ptrdiff_t use_position) {
178db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  first_use_ = std::min(first_use_, use_position);
179db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  if (first_use_ == -1) {
180db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    first_use_ = use_position;
18188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    SetNextRecommendedCheckpoint(GetNextRecommendedCheckpoint());
182db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    SetNextCheckpoint(first_use_ + Instruction::kLoadLiteralRange);
183db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  } else {
184db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    VIXL_ASSERT(use_position > first_use_);
185db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  }
1865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::Reset() {
1905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Pool::Reset();
1915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unresolved_branches_.Reset();
1925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::Release() {
1965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (--monitor_ == 0) {
1975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(IsEmpty() ||
19888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                masm_->GetCursorOffset() <
19988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    unresolved_branches_.GetFirstLimit());
2005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
201c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
202c68cb64496485710cdb5b8480f8fee287058c93farmvixl
203c68cb64496485710cdb5b8480f8fee287058c93farmvixl
2045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::RegisterUnresolvedBranch(ptrdiff_t branch_pos,
2055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                          Label* label,
2065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                          ImmBranchType branch_type) {
2075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!label->IsBound());
2085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  BranchInfo branch_info = BranchInfo(branch_pos, label, branch_type);
2095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unresolved_branches_.insert(branch_info);
2105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UpdateNextCheckPoint();
2115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // TODO: In debug mode register the label with the assembler to make sure it
2125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // is bound with masm Bind and not asm bind.
2135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
2145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::DeleteUnresolvedBranchInfoForLabel(Label* label) {
217c68cb64496485710cdb5b8480f8fee287058c93farmvixl  if (IsEmpty()) {
2185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(checkpoint_ == kNoCheckpointRequired);
2195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
220c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
221c68cb64496485710cdb5b8480f8fee287058c93farmvixl
2225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsLinked()) {
2235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label::LabelLinksIterator links_it(label);
2245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (; !links_it.Done(); links_it.Advance()) {
2255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      ptrdiff_t link_offset = *links_it.Current();
22688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Instruction* link = masm_->GetInstructionAt(link_offset);
227c68cb64496485710cdb5b8480f8fee287058c93farmvixl
2285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // ADR instructions are not handled.
22988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (BranchTypeUsesVeneers(link->GetBranchType())) {
23088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        BranchInfo branch_info(link_offset, label, link->GetBranchType());
2315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        unresolved_branches_.erase(branch_info);
2325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
2335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
2345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UpdateNextCheckPoint();
2375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
2385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2407e0f1ebcf5ac1f83fd4b85a5b8f2e80dc991ed67Georgia Kouvelibool VeneerPool::ShouldEmitVeneer(int64_t first_unreacheable_pc,
2417e0f1ebcf5ac1f83fd4b85a5b8f2e80dc991ed67Georgia Kouveli                                  size_t amount) {
2425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  ptrdiff_t offset =
24388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      kPoolNonVeneerCodeSize + amount + GetMaxSize() + GetOtherPoolsMaxSize();
2447e0f1ebcf5ac1f83fd4b85a5b8f2e80dc991ed67Georgia Kouveli  return (masm_->GetCursorOffset() + offset) > first_unreacheable_pc;
2455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
2465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::CheckEmitFor(size_t amount, EmitOption option) {
2495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsEmpty()) return;
2505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2517e0f1ebcf5ac1f83fd4b85a5b8f2e80dc991ed67Georgia Kouveli  VIXL_ASSERT(masm_->GetCursorOffset() + kPoolNonVeneerCodeSize <
2527e0f1ebcf5ac1f83fd4b85a5b8f2e80dc991ed67Georgia Kouveli              unresolved_branches_.GetFirstLimit());
2535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsBlocked()) return;
2555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (ShouldEmitVeneers(amount)) {
2575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Emit(option, amount);
2585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
2595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UpdateNextCheckPoint();
2605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
2625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::Emit(EmitOption option, size_t amount) {
2655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // There is an issue if we are asked to emit a blocked or empty pool.
2665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!IsBlocked());
2675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!IsEmpty());
2685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Label end;
2705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (option == kBranchRequired) {
27107d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames    ExactAssemblyScopeWithoutPoolsCheck guard(masm_, kInstructionSize);
2725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    masm_->b(&end);
2735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // We want to avoid generating veneer pools too often, so generate veneers for
2765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // branches that don't immediately require a veneer but will soon go out of
2775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // range.
2785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  static const size_t kVeneerEmissionMargin = 1 * KBytes;
2795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (BranchInfoSetIterator it(&unresolved_branches_); !it.Done();) {
2815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    BranchInfo* branch_info = it.Current();
2827e0f1ebcf5ac1f83fd4b85a5b8f2e80dc991ed67Georgia Kouveli    if (ShouldEmitVeneer(branch_info->first_unreacheable_pc_,
2835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                         amount + kVeneerEmissionMargin)) {
284de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      CodeBufferCheckScope scope(masm_,
285de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                 kVeneerCodeSize,
286de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                 CodeBufferCheckScope::kCheck,
287de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                 CodeBufferCheckScope::kExactSize);
2885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      ptrdiff_t branch_pos = branch_info->pc_offset_;
28988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Instruction* branch = masm_->GetInstructionAt(branch_pos);
2905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Label* label = branch_info->label_;
2915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // Patch the branch to point to the current position, and emit a branch
2935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // to the label.
2945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Instruction* veneer = masm_->GetCursorAddress<Instruction*>();
2955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      branch->SetImmPCOffsetTarget(veneer);
296de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      {
29707d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames        ExactAssemblyScopeWithoutPoolsCheck guard(masm_, kInstructionSize);
298de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames        masm_->b(label);
299de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      }
3005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
3015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // Update the label. The branch patched does not point to it any longer.
3025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      label->DeleteLink(branch_pos);
3035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
3045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      it.DeleteCurrentAndAdvance();
3055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
3065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      it.AdvanceToNextType();
3075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
3085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
3095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
3105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UpdateNextCheckPoint();
3115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
3125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  masm_->bind(&end);
313c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
314c68cb64496485710cdb5b8480f8fee287058c93farmvixl
315c68cb64496485710cdb5b8480f8fee287058c93farmvixl
316f2f550c0bfd0f15a4d1c51ff06ec898536f14205Alexandre RamesMacroAssembler::MacroAssembler(PositionIndependentCodeOption pic)
317f2f550c0bfd0f15a4d1c51ff06ec898536f14205Alexandre Rames    : Assembler(pic),
318b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames#ifdef VIXL_DEBUG
319b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      allow_macro_instructions_(true),
320b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames#endif
3211e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois      generate_simulator_code_(VIXL_AARCH64_GENERATE_SIMULATOR_CODE),
322b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      sp_(sp),
323b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      tmp_list_(ip0, ip1),
324b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      fptmp_list_(d31),
325e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley      current_scratch_scope_(NULL),
326b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      literal_pool_(this),
327b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      veneer_pool_(this),
328b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      recommended_checkpoint_(Pool::kNoCheckpointRequired) {
329b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames  checkpoint_ = GetNextCheckPoint();
330fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames#ifndef VIXL_DEBUG
331fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames  USE(allow_macro_instructions_);
332fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames#endif
333b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames}
334b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames
335b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames
336c68cb64496485710cdb5b8480f8fee287058c93farmvixlMacroAssembler::MacroAssembler(size_t capacity,
337c68cb64496485710cdb5b8480f8fee287058c93farmvixl                               PositionIndependentCodeOption pic)
338c68cb64496485710cdb5b8480f8fee287058c93farmvixl    : Assembler(capacity, pic),
339330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
340c68cb64496485710cdb5b8480f8fee287058c93farmvixl      allow_macro_instructions_(true),
341c68cb64496485710cdb5b8480f8fee287058c93farmvixl#endif
3421e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois      generate_simulator_code_(VIXL_AARCH64_GENERATE_SIMULATOR_CODE),
343c68cb64496485710cdb5b8480f8fee287058c93farmvixl      sp_(sp),
344c68cb64496485710cdb5b8480f8fee287058c93farmvixl      tmp_list_(ip0, ip1),
345c68cb64496485710cdb5b8480f8fee287058c93farmvixl      fptmp_list_(d31),
346e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley      current_scratch_scope_(NULL),
3475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      literal_pool_(this),
348db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      veneer_pool_(this),
349db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      recommended_checkpoint_(Pool::kNoCheckpointRequired) {
35088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
351c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
352c68cb64496485710cdb5b8480f8fee287058c93farmvixl
353c68cb64496485710cdb5b8480f8fee287058c93farmvixl
3540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlMacroAssembler::MacroAssembler(byte* buffer,
355c68cb64496485710cdb5b8480f8fee287058c93farmvixl                               size_t capacity,
356c68cb64496485710cdb5b8480f8fee287058c93farmvixl                               PositionIndependentCodeOption pic)
357c68cb64496485710cdb5b8480f8fee287058c93farmvixl    : Assembler(buffer, capacity, pic),
358330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
359c68cb64496485710cdb5b8480f8fee287058c93farmvixl      allow_macro_instructions_(true),
360c68cb64496485710cdb5b8480f8fee287058c93farmvixl#endif
3611e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois      generate_simulator_code_(VIXL_AARCH64_GENERATE_SIMULATOR_CODE),
362c68cb64496485710cdb5b8480f8fee287058c93farmvixl      sp_(sp),
363c68cb64496485710cdb5b8480f8fee287058c93farmvixl      tmp_list_(ip0, ip1),
364c68cb64496485710cdb5b8480f8fee287058c93farmvixl      fptmp_list_(d31),
365e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley      current_scratch_scope_(NULL),
3665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      literal_pool_(this),
367db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      veneer_pool_(this),
368db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      recommended_checkpoint_(Pool::kNoCheckpointRequired) {
36988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
370c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
371c68cb64496485710cdb5b8480f8fee287058c93farmvixl
372c68cb64496485710cdb5b8480f8fee287058c93farmvixl
3730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlMacroAssembler::~MacroAssembler() {}
374c68cb64496485710cdb5b8480f8fee287058c93farmvixl
375c68cb64496485710cdb5b8480f8fee287058c93farmvixl
376c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid MacroAssembler::Reset() {
377c68cb64496485710cdb5b8480f8fee287058c93farmvixl  Assembler::Reset();
378c68cb64496485710cdb5b8480f8fee287058c93farmvixl
379c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!literal_pool_.IsBlocked());
380c68cb64496485710cdb5b8480f8fee287058c93farmvixl  literal_pool_.Reset();
3815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.Reset();
382c68cb64496485710cdb5b8480f8fee287058c93farmvixl
38388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
384c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
385c68cb64496485710cdb5b8480f8fee287058c93farmvixl
386c68cb64496485710cdb5b8480f8fee287058c93farmvixl
3878571b89fb163d8f3551327ceb46deb1cda359ceePierre Langloisvoid MacroAssembler::FinalizeCode(FinalizeOption option) {
3888571b89fb163d8f3551327ceb46deb1cda359ceePierre Langlois  if (!literal_pool_.IsEmpty()) {
3898571b89fb163d8f3551327ceb46deb1cda359ceePierre Langlois    // The user may decide to emit more code after Finalize, emit a branch if
3908571b89fb163d8f3551327ceb46deb1cda359ceePierre Langlois    // that's the case.
3918571b89fb163d8f3551327ceb46deb1cda359ceePierre Langlois    literal_pool_.Emit(option == kUnreachable ? Pool::kNoBranchRequired
3928571b89fb163d8f3551327ceb46deb1cda359ceePierre Langlois                                              : Pool::kBranchRequired);
3938571b89fb163d8f3551327ceb46deb1cda359ceePierre Langlois  }
3945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(veneer_pool_.IsEmpty());
395c68cb64496485710cdb5b8480f8fee287058c93farmvixl
396c68cb64496485710cdb5b8480f8fee287058c93farmvixl  Assembler::FinalizeCode();
397c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
398c68cb64496485710cdb5b8480f8fee287058c93farmvixl
399c68cb64496485710cdb5b8480f8fee287058c93farmvixl
4005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::CheckEmitFor(size_t amount) {
4019fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames  CheckEmitPoolsFor(amount);
4026a049f97861bd71c69d81f643e42308d28c5de31Alexandre Rames  GetBuffer()->EnsureSpaceFor(amount);
4039fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames}
4049fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames
4055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
4069fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Ramesvoid MacroAssembler::CheckEmitPoolsFor(size_t amount) {
4079fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames  literal_pool_.CheckEmitFor(amount);
4089fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames  veneer_pool_.CheckEmitFor(amount);
40988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
4105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
4115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
4125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
413330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlint MacroAssembler::MoveImmediateHelper(MacroAssembler* masm,
4140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                        const Register& rd,
415330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl                                        uint64_t imm) {
416330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  bool emit_code = (masm != NULL);
41788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint32(imm) || IsInt32(imm) || rd.Is64Bits());
418330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The worst case for size is mov 64-bit immediate to sp:
419330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  * up to 4 instructions to materialise the constant
420330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  * 1 instruction to move to sp
421330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MacroEmissionCheckScope guard(masm);
422330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
423330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Immediates on Aarch64 can be produced using an initial value, and zero to
424330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // three move keep operations.
425330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //
426330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Initial values can be generated with:
427330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  1. 64-bit move zero (movz).
428330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  2. 32-bit move inverted (movn).
429330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  3. 64-bit move inverted.
430330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  4. 32-bit orr immediate.
431330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  5. 64-bit orr immediate.
432330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Move-keep may then be used to modify each of the 16-bit half words.
433330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //
434330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The code below supports all five initial value generators, and
435330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // applying move-keep operations to move-zero and move-inverted initial
436330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // values.
437330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
438330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Try to move the immediate in one instruction, and if that fails, switch to
439330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // using multiple instructions.
440330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (OneInstrMoveImmediateHelper(masm, rd, imm)) {
441330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return 1;
442330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else {
443330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    int instruction_count = 0;
44488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    unsigned reg_size = rd.GetSizeInBits();
445330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
446330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Generic immediate case. Imm will be represented by
447330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    //   [imm3, imm2, imm1, imm0], where each imm is 16 bits.
448330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // A move-zero or move-inverted is generated for the first non-zero or
449330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // non-0xffff immX, and a move-keep for subsequent non-zero immX.
450330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
451330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    uint64_t ignored_halfword = 0;
452330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    bool invert_move = false;
453330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // If the number of 0xffff halfwords is greater than the number of 0x0000
454330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // halfwords, it's more efficient to use move-inverted.
455330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (CountClearHalfWords(~imm, reg_size) >
456330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        CountClearHalfWords(imm, reg_size)) {
457330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      ignored_halfword = 0xffff;
458330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      invert_move = true;
459330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
460330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
461330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Mov instructions can't move values into the stack pointer, so set up a
462330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // temporary register, if needed.
463330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    UseScratchRegisterScope temps;
464330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    Register temp;
465330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
466330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      temps.Open(masm);
467330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      temp = rd.IsSP() ? temps.AcquireSameSizeAs(rd) : rd;
468330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
469330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
470330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Iterate through the halfwords. Use movn/movz for the first non-ignored
471330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // halfword, and movk for subsequent halfwords.
472330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    VIXL_ASSERT((reg_size % 16) == 0);
473330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    bool first_mov_done = false;
4740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    for (unsigned i = 0; i < (reg_size / 16); i++) {
475330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      uint64_t imm16 = (imm >> (16 * i)) & 0xffff;
476330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      if (imm16 != ignored_halfword) {
477330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        if (!first_mov_done) {
478330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          if (invert_move) {
479330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            if (emit_code) masm->movn(temp, ~imm16 & 0xffff, 16 * i);
480330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            instruction_count++;
481330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          } else {
482330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            if (emit_code) masm->movz(temp, imm16, 16 * i);
483330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            instruction_count++;
484330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          }
485330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          first_mov_done = true;
486330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        } else {
487330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          // Construct a wider constant.
488330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          if (emit_code) masm->movk(temp, imm16, 16 * i);
489330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          instruction_count++;
490330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        }
491330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      }
492330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
493330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
494330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    VIXL_ASSERT(first_mov_done);
495330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
496330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Move the temporary if the original destination register was the stack
497330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // pointer.
498330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (rd.IsSP()) {
499330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      if (emit_code) masm->mov(rd, temp);
500330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      instruction_count++;
501330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
502330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return instruction_count;
503330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
504330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
505330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
506330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
507330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlbool MacroAssembler::OneInstrMoveImmediateHelper(MacroAssembler* masm,
508330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl                                                 const Register& dst,
509330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl                                                 int64_t imm) {
510330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  bool emit_code = masm != NULL;
511330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  unsigned n, imm_s, imm_r;
51288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = dst.GetSizeInBits();
513330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
514330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (IsImmMovz(imm, reg_size) && !dst.IsSP()) {
515330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate can be represented in a move zero instruction. Movz can't write
516330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // to the stack pointer.
517330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
518330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      masm->movz(dst, imm);
519330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
520330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return true;
521330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else if (IsImmMovn(imm, reg_size) && !dst.IsSP()) {
522330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate can be represented in a move negative instruction. Movn can't
523330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // write to the stack pointer.
524330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
525330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      masm->movn(dst, dst.Is64Bits() ? ~imm : (~imm & kWRegMask));
526330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
527330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return true;
528330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) {
529330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate can be represented in a logical orr instruction.
530330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    VIXL_ASSERT(!dst.IsZero());
531330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
5320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->LogicalImmediate(dst,
5330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             AppropriateZeroRegFor(dst),
5340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             n,
5350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             imm_s,
5360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             imm_r,
5370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             ORR);
538330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
539330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return true;
540330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
541330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  return false;
542330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
543330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
544330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
545b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid MacroAssembler::B(Label* label, BranchType type, Register reg, int bit) {
546b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((reg.Is(NoReg) || (type >= kBranchTypeFirstUsingReg)) &&
547b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl              ((bit == -1) || (type >= kBranchTypeFirstUsingBit)));
548b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
549b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    B(static_cast<Condition>(type), label);
550b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
551b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    switch (type) {
5520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case always:
5530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        B(label);
5540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5550f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case never:
5560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5570f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_zero:
5580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Cbz(reg, label);
5590f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_not_zero:
5610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Cbnz(reg, label);
5620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_bit_clear:
5640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Tbz(reg, bit, label);
5650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_bit_set:
5670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Tbnz(reg, bit, label);
5680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
569b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      default:
570b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl        VIXL_UNREACHABLE();
571b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    }
572b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
573b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
574b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
5755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::B(Label* label) {
577896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // We don't need to check the size of the literal pool, because the size of
578896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // the literal pool is already bounded by the literal range, which is smaller
579896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // than the range of this branch.
580896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  VIXL_ASSERT(Instruction::GetImmBranchForwardRange(UncondBranchType) >
581896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli              Instruction::kLoadLiteralRange);
5825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  SingleEmissionCheckScope guard(this);
5835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  b(label);
5845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
5855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::B(Label* label, Condition cond) {
588896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // We don't need to check the size of the literal pool, because the size of
589896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // the literal pool is already bounded by the literal range, which is smaller
590896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // than the range of this branch.
591896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  VIXL_ASSERT(Instruction::GetImmBranchForwardRange(CondBranchType) >
592896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli              Instruction::kLoadLiteralRange);
5935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
5945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
5955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
5965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) {
5985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
5995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(&done, InvertCondition(cond));
6005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
60488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            CondBranchType);
6075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label, cond);
6095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Cbnz(const Register& rt, Label* label) {
614896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // We don't need to check the size of the literal pool, because the size of
615896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // the literal pool is already bounded by the literal range, which is smaller
616896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // than the range of this branch.
617896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  VIXL_ASSERT(Instruction::GetImmBranchForwardRange(CompareBranchType) >
618896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli              Instruction::kLoadLiteralRange);
6195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) {
6245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbz(rt, &done);
6265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
63088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            CompareBranchType);
6335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbnz(rt, label);
6355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Cbz(const Register& rt, Label* label) {
640896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // We don't need to check the size of the literal pool, because the size of
641896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // the literal pool is already bounded by the literal range, which is smaller
642896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // than the range of this branch.
643896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  VIXL_ASSERT(Instruction::GetImmBranchForwardRange(CompareBranchType) >
644896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli              Instruction::kLoadLiteralRange);
6455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) {
6505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbnz(rt, &done);
6525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
65688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            CompareBranchType);
6595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbz(rt, label);
6615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Tbnz(const Register& rt, unsigned bit_pos, Label* label) {
666896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // This is to avoid a situation where emitting a veneer for a TBZ/TBNZ branch
667896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // can become impossible because we emit the literal pool first.
668896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  literal_pool_.CheckEmitForBranch(
669896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli      Instruction::GetImmBranchForwardRange(TestBranchType));
6705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, TestBranchType)) {
6755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbz(rt, bit_pos, &done);
6775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
68188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            TestBranchType);
6845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbnz(rt, bit_pos, label);
6865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Tbz(const Register& rt, unsigned bit_pos, Label* label) {
691896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // This is to avoid a situation where emitting a veneer for a TBZ/TBNZ branch
692896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  // can become impossible because we emit the literal pool first.
693896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli  literal_pool_.CheckEmitForBranch(
694896682f0411643afa78e8c62caf723ec5f2b4dbeGeorgia Kouveli      Instruction::GetImmBranchForwardRange(TestBranchType));
6955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, TestBranchType)) {
7005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
7015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbnz(rt, bit_pos, &done);
7025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
7035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
7045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
7055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
70688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
7075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
7085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            TestBranchType);
7095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
7105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbz(rt, bit_pos, label);
7115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
7125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
7135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Bind(Label* label) {
7165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
7175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.DeleteUnresolvedBranchInfoForLabel(label);
7185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  bind(label);
7195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
7205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// Bind a label to a specified offset from the start of the buffer.
7235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::BindToOffset(Label* label, ptrdiff_t offset) {
7245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
7255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.DeleteUnresolvedBranchInfoForLabel(label);
7265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Assembler::BindToOffset(label, offset);
7275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
7285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
730ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::And(const Register& rd,
731ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
732f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
733b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
734f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, AND);
735f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
736f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
737f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
738f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Ands(const Register& rd,
739f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
740f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
741b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
742f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, ANDS);
743ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
744ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
745ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
7460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Tst(const Register& rn, const Operand& operand) {
747b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
748f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Ands(AppropriateZeroRegFor(rn), rn, operand);
749ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
750ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
751ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
752ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Bic(const Register& rd,
753ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
754f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
755b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
756f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, BIC);
757f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
758f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
759f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
760f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Bics(const Register& rd,
761f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
762f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
763b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
764f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, BICS);
765ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
766ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
767ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
768ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Orr(const Register& rd,
769ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
770ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
771b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
772ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, ORR);
773ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
774ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
775ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
776ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Orn(const Register& rd,
777ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
778ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
779b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
780ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, ORN);
781ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
782ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
783ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
784ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Eor(const Register& rd,
785ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
786ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
787b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
788ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, EOR);
789ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
790ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
791ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
792ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Eon(const Register& rd,
793ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
794ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
795b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
796ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, EON);
797ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
798ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
799ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
800ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::LogicalMacro(const Register& rd,
801ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  const Register& rn,
802ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  const Operand& operand,
803ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  LogicalOp op) {
804c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is logical immediate to sp:
805c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
806c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to do the operation
807c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to move to sp
808c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
809b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
810b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
811ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
81285919f840e8ddd06573def57eb587cc77661e7d0Jacob Bramley    uint64_t immediate = operand.GetImmediate();
81388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    unsigned reg_size = rd.GetSizeInBits();
814ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
815ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the operation is NOT, invert the operation and immediate.
816ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if ((op & NOT) == NOT) {
817ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      op = static_cast<LogicalOp>(op & ~NOT);
818ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      immediate = ~immediate;
819ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
820ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
8214a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Ignore the top 32 bits of an immediate if we're moving to a W register.
8224a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (rd.Is32Bits()) {
8234a102baf640077d6794c0b33bb976f94b86c532barmvixl      // Check that the top 32 bits are consistent.
8244a102baf640077d6794c0b33bb976f94b86c532barmvixl      VIXL_ASSERT(((immediate >> kWRegSize) == 0) ||
82585919f840e8ddd06573def57eb587cc77661e7d0Jacob Bramley                  ((immediate >> kWRegSize) == 0xffffffff));
8264a102baf640077d6794c0b33bb976f94b86c532barmvixl      immediate &= kWRegMask;
8274a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
8284a102baf640077d6794c0b33bb976f94b86c532barmvixl
82988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rd.Is64Bits() || IsUint32(immediate));
8304a102baf640077d6794c0b33bb976f94b86c532barmvixl
831ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Special cases for all set or all clear immediates.
832ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (immediate == 0) {
833ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (op) {
834ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case AND:
835ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, 0);
836ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
8376e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        case ORR:
8386e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl          VIXL_FALLTHROUGH();
839ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case EOR:
840ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, rn);
841ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
8426e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        case ANDS:
8436e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl          VIXL_FALLTHROUGH();
844ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case BICS:
845ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
846ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        default:
847b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl          VIXL_UNREACHABLE();
848ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
84985919f840e8ddd06573def57eb587cc77661e7d0Jacob Bramley    } else if ((rd.Is64Bits() && (immediate == UINT64_C(0xffffffffffffffff))) ||
85085919f840e8ddd06573def57eb587cc77661e7d0Jacob Bramley               (rd.Is32Bits() && (immediate == UINT64_C(0x00000000ffffffff)))) {
851ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (op) {
852ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case AND:
853ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, rn);
854ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
855ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case ORR:
856ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, immediate);
857ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
858ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case EOR:
859ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mvn(rd, rn);
860ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
8616e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        case ANDS:
8626e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl          VIXL_FALLTHROUGH();
863ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case BICS:
864ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
865ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        default:
866b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl          VIXL_UNREACHABLE();
867ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
868ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
869ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    unsigned n, imm_s, imm_r;
871ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
872ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Immediate can be encoded in the instruction.
873ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
874ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
875ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Immediate can't be encoded: synthesize using move immediate.
876b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      Register temp = temps.AcquireSameSizeAs(rn);
877210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell
878210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      // If the left-hand input is the stack pointer, we can't pre-shift the
879210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      // immediate, as the encoding won't allow the subsequent post shift.
880210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      PreShiftImmMode mode = rn.IsSP() ? kNoShift : kAnyShift;
881210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      Operand imm_operand = MoveImmediateForShiftedOp(temp, immediate, mode);
8824a102baf640077d6794c0b33bb976f94b86c532barmvixl
883ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd.Is(sp)) {
884ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // If rd is the stack pointer we cannot use it as the destination
885ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // register so we use the temp register as an intermediate again.
8864a102baf640077d6794c0b33bb976f94b86c532barmvixl        Logical(temp, rn, imm_operand, op);
887ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        Mov(sp, temp);
888ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
8894a102baf640077d6794c0b33bb976f94b86c532barmvixl        Logical(rd, rn, imm_operand, op);
890ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
891ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
892ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
89388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() <= rd.GetSizeInBits());
894ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub extended supports shift <= 4. We want to support exactly the
895ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // same modes here.
89688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShiftAmount() <= 4);
89788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
89888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        operand.GetRegister().Is64Bits() ||
89988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        ((operand.GetExtend() != UXTX) && (operand.GetExtend() != SXTX)));
900b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
90188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
902b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
9030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
90488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
90588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
90688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
907ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Logical(rd, rn, Operand(temp), op);
908ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
909ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The operand can be encoded in the instruction.
910b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT(operand.IsShiftedRegister());
911ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Logical(rd, rn, operand, op);
912ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
913ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
914ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
915ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
916f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Mov(const Register& rd,
917f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand,
918f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         DiscardMoveMode discard_mode) {
919b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
920c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is mov immediate with up to 4 instructions.
921c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
922c68cb64496485710cdb5b8480f8fee287058c93farmvixl
923ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
924ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Call the macro assembler for generic immediates.
92588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(rd, operand.GetImmediate());
92688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } else if (operand.IsShiftedRegister() && (operand.GetShiftAmount() != 0)) {
927ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit a shift instruction if moving a shifted register. This operation
928ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // could also be achieved using an orr instruction (like orn used by Mvn),
929ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // but using a shift instruction makes the disassembly clearer.
93088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    EmitShift(rd,
93188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetRegister(),
93288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShift(),
93388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShiftAmount());
934ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
935ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit an extend instruction if moving an extended register. This handles
936ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // extend with post-shift operations, too.
9370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(rd,
93888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
93988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
94088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
941ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
9421c78c34397f2c08c012733cc661076e8bd029eabAlexandre Rames    Mov(rd, operand.GetRegister(), discard_mode);
943ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
944ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
945ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
946ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
9475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi16bitHelper(const VRegister& vd, uint64_t imm) {
94888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint16(imm));
9495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  int byte1 = (imm & 0xff);
9505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  int byte2 = ((imm >> 8) & 0xff);
9515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (byte1 == byte2) {
9525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd.Is64Bits() ? vd.V8B() : vd.V16B(), byte1);
9535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte1 == 0) {
9545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, byte2, LSL, 8);
9555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte2 == 0) {
9565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, byte1);
9575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte1 == 0xff) {
9585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~byte2 & 0xff, LSL, 8);
9595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte2 == 0xff) {
9605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~byte1 & 0xff);
9615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
9625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
9635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireW();
9645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movz(temp, imm);
9655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    dup(vd, temp);
9665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
9685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi32bitHelper(const VRegister& vd, uint64_t imm) {
97188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint32(imm));
9725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  uint8_t bytes[sizeof(imm)];
9745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  memcpy(bytes, &imm, sizeof(imm));
9755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // All bytes are either 0x00 or 0xff.
9775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
9785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bool all0orff = true;
9795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (int i = 0; i < 4; ++i) {
9805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if ((bytes[i] != 0) && (bytes[i] != 0xff)) {
9815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        all0orff = false;
9825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        break;
9835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
9845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
9855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (all0orff == true) {
9875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd.Is64Bits() ? vd.V1D() : vd.V2D(), ((imm << 32) | imm));
9885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
9895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
9905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Of the 4 bytes, only one byte is non-zero.
9935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (int i = 0; i < 4; i++) {
9945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if ((imm & (0xff << (i * 8))) == imm) {
9955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd, bytes[i], LSL, i * 8);
9965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
9975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
9985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Of the 4 bytes, only one byte is not 0xff.
10015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (int i = 0; i < 4; i++) {
10025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    uint32_t mask = ~(0xff << (i * 8));
10035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if ((imm & mask) == mask) {
10045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      mvni(vd, ~bytes[i] & 0xff, LSL, i * 8);
10055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0x00MMFFFF.
10105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xff00ffff) == 0x0000ffff) {
10115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, bytes[2], MSL, 16);
10125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0x0000MMFF.
10165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xffff00ff) == 0x000000ff) {
10175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, bytes[1], MSL, 8);
10185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0xFFMM0000.
10225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xff00ffff) == 0xff000000) {
10235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~bytes[2] & 0xff, MSL, 16);
10245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0xFFFFMM00.
10275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xffff00ff) == 0xffff0000) {
10285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~bytes[1] & 0xff, MSL, 8);
10295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Top and bottom 16-bits are equal.
10335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (((imm >> 16) & 0xffff) == (imm & 0xffff)) {
10345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi16bitHelper(vd.Is64Bits() ? vd.V4H() : vd.V8H(), imm & 0xffff);
10355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Default case.
10395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
10415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireW();
10425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Mov(temp, imm);
10435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    dup(vd, temp);
10445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
10465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi64bitHelper(const VRegister& vd, uint64_t imm) {
10495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // All bytes are either 0x00 or 0xff.
10505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bool all0orff = true;
10525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (int i = 0; i < 8; ++i) {
10535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      int byteval = (imm >> (i * 8)) & 0xff;
10545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (byteval != 0 && byteval != 0xff) {
10555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        all0orff = false;
10565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        break;
10575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
10585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (all0orff == true) {
10605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd, imm);
10615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Top and bottom 32-bits are equal.
10665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (((imm >> 32) & 0xffffffff) == (imm & 0xffffffff)) {
10675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi32bitHelper(vd.Is64Bits() ? vd.V2S() : vd.V4S(), imm & 0xffffffff);
10685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Default case.
10725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
10745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireX();
10755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Mov(temp, imm);
10765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.Is1D()) {
10775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      mov(vd.D(), 0, temp);
10785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
10795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      dup(vd.V2D(), temp);
10805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
10835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi(const VRegister& vd,
10865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          uint64_t imm,
10875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          Shift shift,
10885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          int shift_amount) {
10895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
10905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  MacroEmissionCheckScope guard(this);
10915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (shift_amount != 0 || shift != LSL) {
10925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, imm, shift, shift_amount);
10935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is8B() || vd.Is16B()) {
10945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 8-bit immediate.
109588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsUint8(imm));
10965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, imm);
10975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is4H() || vd.Is8H()) {
10985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 16-bit immediate.
10995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi16bitHelper(vd, imm);
11005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is2S() || vd.Is4S()) {
11015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 32-bit immediate.
11025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi32bitHelper(vd, imm);
11035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
11045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 64-bit immediate.
11055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi64bitHelper(vd, imm);
11065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
11075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
11085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11100f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Movi(const VRegister& vd, uint64_t hi, uint64_t lo) {
11115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // TODO: Move 128-bit values in a more efficient way.
11125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is128Bits());
11135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UseScratchRegisterScope temps(this);
11145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Movi(vd.V2D(), lo);
11155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Register temp = temps.AcquireX();
11165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Mov(temp, hi);
11175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Ins(vd.V2D(), 1, temp);
11185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
11195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
1122b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1123c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is mvn immediate with up to 4 instructions.
1124c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1125c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
1127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Call the macro assembler for generic immediates.
112888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mvn(rd, operand.GetImmediate());
1129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
1130b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
113188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1132b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit two instructions for the extend case. This differs from Mov, as
1134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the extend and invert can't be achieved in one instruction.
1135b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rd);
11360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
113788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
113888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
113988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
1140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, Operand(temp));
1141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Otherwise, register and shifted register cases can be handled by the
1143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // assembler directly, using orn.
1144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, operand);
1145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mov(const Register& rd, uint64_t imm) {
1150b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1151330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MoveImmediateHelper(this, rd, imm);
1152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmp(const Register& rn,
1156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
1157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
1158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
1159b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
116088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0)) {
116188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ConditionalCompareMacro(rn, -operand.GetImmediate(), nzcv, cond, CCMN);
1162f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
1163f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
1164f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmn(const Register& rn,
1169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
1170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
1171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
1172b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
117388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0)) {
117488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ConditionalCompareMacro(rn, -operand.GetImmediate(), nzcv, cond, CCMP);
1175f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
1176f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
1177f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::ConditionalCompareMacro(const Register& rn,
1182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             const Operand& operand,
1183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             StatusFlags nzcv,
1184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             Condition cond,
1185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             ConditionalCompareOp op) {
1186b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
1187c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is ccmp immediate:
1188c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1189c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ccmp
1190c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1191c68cb64496485710cdb5b8480f8fee287058c93farmvixl
119288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((operand.IsShiftedRegister() && (operand.GetShiftAmount() == 0)) ||
119388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsImmediate() &&
119488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois       IsImmConditionalCompare(operand.GetImmediate()))) {
1195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The immediate can be encoded in the instruction, or the operand is an
1196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // unshifted register: call the assembler.
1197ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    ConditionalCompare(rn, operand, nzcv, cond, op);
1198ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1199b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1200ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The operand isn't directly supported by the instruction: perform the
1201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // operation on a temporary register.
1202b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
1203f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Mov(temp, operand);
1204f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompare(rn, temp, nzcv, cond, op);
1205f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1206f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1207f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1208f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
12090f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::CselHelper(MacroAssembler* masm,
12100f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                const Register& rd,
12110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Operand left,
12120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Operand right,
12130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Condition cond,
12140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                bool* should_synthesise_left,
12150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                bool* should_synthesise_right) {
12160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
12170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12180f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(!emit_code || masm->allow_macro_instructions_);
1219b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
12200f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(!rd.IsZero() && !rd.IsSP());
122188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(left.IsImmediate() || !left.GetRegister().IsSP());
122288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(right.IsImmediate() || !right.GetRegister().IsSP());
12230f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_left != NULL) *should_synthesise_left = false;
12250f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_right != NULL) *should_synthesise_right = false;
12260f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // The worst case for size occurs when the inputs are two non encodable
12280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // constants:
12290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  //  * up to 4 instructions to materialise the left constant
12300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  //  * up to 4 instructions to materialise the right constant
1231c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for csel
12320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  EmissionCheckScope guard(masm, 9 * kInstructionSize);
12330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  UseScratchRegisterScope temps;
12340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (masm != NULL) {
12350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    temps.Open(masm);
12360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Try to handle cases where both inputs are immediates.
12390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool left_is_immediate = left.IsImmediate() || left.IsZero();
12400f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool right_is_immediate = right.IsImmediate() || right.IsZero();
12410f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left_is_immediate && right_is_immediate &&
12420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      CselSubHelperTwoImmediates(masm,
12430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 rd,
12440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 left.GetEquivalentImmediate(),
12450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 right.GetEquivalentImmediate(),
12460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 cond,
12470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 should_synthesise_left,
12480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 should_synthesise_right)) {
12490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
12500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1251c68cb64496485710cdb5b8480f8fee287058c93farmvixl
12520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Handle cases where one of the two inputs is -1, 0, or 1.
12530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool left_is_small_immediate =
12540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left_is_immediate && ((-1 <= left.GetEquivalentImmediate()) &&
12550f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                            (left.GetEquivalentImmediate() <= 1));
12560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool right_is_small_immediate =
12570f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      right_is_immediate && ((-1 <= right.GetEquivalentImmediate()) &&
12580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             (right.GetEquivalentImmediate() <= 1));
12590f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (right_is_small_immediate || left_is_small_immediate) {
12600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    bool swapped_inputs = false;
12610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (!right_is_small_immediate) {
12620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      std::swap(left, right);
12630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      cond = InvertCondition(cond);
12640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      swapped_inputs = true;
12650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    CselSubHelperRightSmallImmediate(masm,
12670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     &temps,
12680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     rd,
12690f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     left,
12700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     right,
12710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     cond,
12720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     swapped_inputs ? should_synthesise_right
12730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                    : should_synthesise_left);
12740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
12750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Otherwise both inputs need to be available in registers. Synthesise them
12780f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // if necessary and emit the `csel`.
12790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (!left.IsPlainRegister()) {
12800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
12810f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Register temp = temps.AcquireSameSizeAs(rd);
12820f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(temp, left);
12830f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left = temp;
12840f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12850f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_left != NULL) *should_synthesise_left = true;
12860f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12870f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (!right.IsPlainRegister()) {
12880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
12890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Register temp = temps.AcquireSameSizeAs(rd);
12900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(temp, right);
12910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      right = temp;
12920f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_right != NULL) *should_synthesise_right = true;
12940f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (emit_code) {
12960f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(left.IsPlainRegister() && right.IsPlainRegister());
129788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (left.GetRegister().Is(right.GetRegister())) {
129888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      masm->Mov(rd, left.GetRegister());
12990f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    } else {
130088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      masm->csel(rd, left.GetRegister(), right.GetRegister(), cond);
13010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13020f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13050f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13060f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlbool MacroAssembler::CselSubHelperTwoImmediates(MacroAssembler* masm,
13070f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                const Register& rd,
13080f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                int64_t left,
13090f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                int64_t right,
13100f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                Condition cond,
13110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                bool* should_synthesise_left,
13120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                bool* should_synthesise_right) {
13130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_left != NULL) *should_synthesise_left = false;
13150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_right != NULL) *should_synthesise_right = false;
13160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left == right) {
13180f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) masm->Mov(rd, left);
13190f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13200f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else if (left == -right) {
13210f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_right != NULL) *should_synthesise_right = true;
13220f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
13230f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(rd, right);
13240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Cneg(rd, rd, cond);
13250f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13260f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (CselSubHelperTwoOrderedImmediates(masm, rd, left, right, cond)) {
13300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else {
13320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    std::swap(left, right);
13330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (CselSubHelperTwoOrderedImmediates(masm,
13340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          rd,
13350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          left,
13360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          right,
13370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          InvertCondition(cond))) {
13380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      return true;
13390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13400f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13410f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // TODO: Handle more situations. For example handle `csel rd, #5, #6, cond`
13430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // with `cinc`.
13440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  return false;
13450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlbool MacroAssembler::CselSubHelperTwoOrderedImmediates(MacroAssembler* masm,
13490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       const Register& rd,
13500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       int64_t left,
13510f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       int64_t right,
13520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       Condition cond) {
13530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
1355dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames  if ((left == 1) && (right == 0)) {
13560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) masm->cset(rd, cond);
13570f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
1358dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames  } else if ((left == -1) && (right == 0)) {
1359dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames    if (emit_code) masm->csetm(rd, cond);
13600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  return false;
13630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::CselSubHelperRightSmallImmediate(
13670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    MacroAssembler* masm,
13680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    UseScratchRegisterScope* temps,
13690f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Register& rd,
13700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Operand& left,
13710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Operand& right,
13720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    Condition cond,
13730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    bool* should_synthesise_left) {
13740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT((right.IsImmediate() || right.IsZero()) &&
13760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl              (-1 <= right.GetEquivalentImmediate()) &&
13770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl              (right.GetEquivalentImmediate() <= 1));
13780f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  Register left_register;
13790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left.IsPlainRegister()) {
138188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    left_register = left.GetRegister();
13820f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else {
13830f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
13840f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left_register = temps->AcquireSameSizeAs(rd);
13850f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(left_register, left);
13860f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13870f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_left != NULL) *should_synthesise_left = true;
13880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (emit_code) {
13900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    int64_t imm = right.GetEquivalentImmediate();
13910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    Register zr = AppropriateZeroRegFor(rd);
1392f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if (imm == 0) {
13930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csel(rd, left_register, zr, cond);
1394f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    } else if (imm == 1) {
13950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csinc(rd, left_register, zr, cond);
1396ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
13970f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      VIXL_ASSERT(imm == -1);
13980f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csinv(rd, left_register, zr, cond);
1399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1401ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1404ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Add(const Register& rd,
1405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
14066e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         const Operand& operand,
14076e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         FlagsUpdate S) {
1408b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
140988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0) &&
141088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      IsImmAddSub(-operand.GetImmediate())) {
141188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    AddSubMacro(rd, rn, -operand.GetImmediate(), S, SUB);
1412ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
14136e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    AddSubMacro(rd, rn, operand, S, ADD);
1414f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1415f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1416f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1417f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1418f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adds(const Register& rd,
1419f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1420f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
14216e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Add(rd, rn, operand, SetFlags);
1422ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1423ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1424ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1425ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sub(const Register& rd,
1426ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
14276e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         const Operand& operand,
14286e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         FlagsUpdate S) {
1429b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
143088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0) &&
143188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      IsImmAddSub(-operand.GetImmediate())) {
143288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    AddSubMacro(rd, rn, -operand.GetImmediate(), S, ADD);
1433f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
14346e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    AddSubMacro(rd, rn, operand, S, SUB);
1435f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1436f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1437f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1438f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1439f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Subs(const Register& rd,
1440f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1441f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
14426e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Sub(rd, rn, operand, SetFlags);
1443ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1444ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1445ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1446ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
1447b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1448f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Adds(AppropriateZeroRegFor(rn), rn, operand);
1449ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1450ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1451ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1452ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
1453b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1454f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(AppropriateZeroRegFor(rn), rn, operand);
1455ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1456ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1457ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
14580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Fcmp(const FPRegister& fn,
14590f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          double value,
14606e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                          FPTrapFlags trap) {
1461b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1462c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is:
1463c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 to materialise the constant, using literal pool if necessary
14646e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  //  * 1 instruction for fcmp{e}
1465c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1466b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (value != 0.0) {
1467b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1468b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    FPRegister tmp = temps.AcquireSameSizeAs(fn);
1469b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Fmov(tmp, value);
14706e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    FPCompareMacro(fn, tmp, trap);
1471b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
14726e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    FPCompareMacro(fn, value, trap);
1473b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1474b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1475b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1476b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
14776e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::Fcmpe(const FPRegister& fn, double value) {
14786e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Fcmp(fn, value, EnableTrap);
14796e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
14806e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
14816e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
14825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Fmov(VRegister vd, double imm) {
1483b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1484c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Floating point immediates are loaded through the literal pool.
1485c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1486c68cb64496485710cdb5b8480f8fee287058c93farmvixl
14875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (vd.Is1S() || vd.Is2S() || vd.Is4S()) {
14885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Fmov(vd, static_cast<float>(imm));
1489b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    return;
1490b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1491b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
14925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is1D() || vd.Is2D());
1493b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (IsImmFP64(imm)) {
14945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    fmov(vd, imm);
1495b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
149688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint64_t rawbits = DoubleToRawbits(imm);
14975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.IsScalar()) {
14985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (rawbits == 0) {
14995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        fmov(vd, xzr);
15005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      } else {
1501db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl        ldr(vd,
1502db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl            new Literal<double>(imm,
1503db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                                &literal_pool_,
1504db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                                RawLiteral::kDeletedOnPlacementByPool));
15055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
15065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
15075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // TODO: consider NEON support for load literal.
15085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Movi(vd, rawbits);
15095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
1510b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1511b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1512b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1513b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Fmov(VRegister vd, float imm) {
1515b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1516c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Floating point immediates are loaded through the literal pool.
1517c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1518c68cb64496485710cdb5b8480f8fee287058c93farmvixl
15195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (vd.Is1D() || vd.Is2D()) {
15205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Fmov(vd, static_cast<double>(imm));
1521b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    return;
1522b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1523b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is1S() || vd.Is2S() || vd.Is4S());
1525b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (IsImmFP32(imm)) {
15265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    fmov(vd, imm);
1527b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
152888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint32_t rawbits = FloatToRawbits(imm);
15295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.IsScalar()) {
15305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (rawbits == 0) {
15315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        fmov(vd, wzr);
15325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      } else {
1533db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl        ldr(vd,
1534db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl            new Literal<float>(imm,
1535db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                               &literal_pool_,
1536db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                               RawLiteral::kDeletedOnPlacementByPool));
15375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
15385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
15395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // TODO: consider NEON support for load literal.
15405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Movi(vd, rawbits);
15415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
1542b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1543b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1544b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1545b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Neg(const Register& rd, const Operand& operand) {
1547b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1548ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
154988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(rd, -operand.GetImmediate());
1550ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1551f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Sub(rd, AppropriateZeroRegFor(rd), operand);
1552ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1553ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1554ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1555ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
15560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Negs(const Register& rd, const Operand& operand) {
1557b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1558f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(rd, AppropriateZeroRegFor(rd), operand);
1559f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1560f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1561f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
15624a102baf640077d6794c0b33bb976f94b86c532barmvixlbool MacroAssembler::TryOneInstrMoveImmediate(const Register& dst,
15634a102baf640077d6794c0b33bb976f94b86c532barmvixl                                              int64_t imm) {
1564330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  return OneInstrMoveImmediateHelper(this, dst, imm);
15654a102baf640077d6794c0b33bb976f94b86c532barmvixl}
15664a102baf640077d6794c0b33bb976f94b86c532barmvixl
15674a102baf640077d6794c0b33bb976f94b86c532barmvixl
15684a102baf640077d6794c0b33bb976f94b86c532barmvixlOperand MacroAssembler::MoveImmediateForShiftedOp(const Register& dst,
1569210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell                                                  int64_t imm,
1570210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell                                                  PreShiftImmMode mode) {
157188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = dst.GetSizeInBits();
15724a102baf640077d6794c0b33bb976f94b86c532barmvixl
15734a102baf640077d6794c0b33bb976f94b86c532barmvixl  // Encode the immediate in a single move instruction, if possible.
15744a102baf640077d6794c0b33bb976f94b86c532barmvixl  if (TryOneInstrMoveImmediate(dst, imm)) {
15754a102baf640077d6794c0b33bb976f94b86c532barmvixl    // The move was successful; nothing to do here.
15764a102baf640077d6794c0b33bb976f94b86c532barmvixl  } else {
15774a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Pre-shift the immediate to the least-significant bits of the register.
15784a102baf640077d6794c0b33bb976f94b86c532barmvixl    int shift_low = CountTrailingZeros(imm, reg_size);
1579210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell    if (mode == kLimitShiftForSP) {
1580210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      // When applied to the stack pointer, the subsequent arithmetic operation
1581210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      // can use the extend form to shift left by a maximum of four bits. Right
1582210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      // shifts are not allowed, so we filter them out later before the new
1583210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      // immediate is tested.
1584210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      shift_low = std::min(shift_low, 4);
1585210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell    }
15864a102baf640077d6794c0b33bb976f94b86c532barmvixl    int64_t imm_low = imm >> shift_low;
15874a102baf640077d6794c0b33bb976f94b86c532barmvixl
15884a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Pre-shift the immediate to the most-significant bits of the register,
15894a102baf640077d6794c0b33bb976f94b86c532barmvixl    // inserting set bits in the least-significant bits.
15904a102baf640077d6794c0b33bb976f94b86c532barmvixl    int shift_high = CountLeadingZeros(imm, reg_size);
15915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    int64_t imm_high = (imm << shift_high) | ((INT64_C(1) << shift_high) - 1);
15924a102baf640077d6794c0b33bb976f94b86c532barmvixl
1593210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell    if ((mode != kNoShift) && TryOneInstrMoveImmediate(dst, imm_low)) {
15944a102baf640077d6794c0b33bb976f94b86c532barmvixl      // The new immediate has been moved into the destination's low bits:
15954a102baf640077d6794c0b33bb976f94b86c532barmvixl      // return a new leftward-shifting operand.
15964a102baf640077d6794c0b33bb976f94b86c532barmvixl      return Operand(dst, LSL, shift_low);
1597210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell    } else if ((mode == kAnyShift) && TryOneInstrMoveImmediate(dst, imm_high)) {
15984a102baf640077d6794c0b33bb976f94b86c532barmvixl      // The new immediate has been moved into the destination's high bits:
15994a102baf640077d6794c0b33bb976f94b86c532barmvixl      // return a new rightward-shifting operand.
16004a102baf640077d6794c0b33bb976f94b86c532barmvixl      return Operand(dst, LSR, shift_high);
16014a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else {
16024a102baf640077d6794c0b33bb976f94b86c532barmvixl      Mov(dst, imm);
16034a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
16044a102baf640077d6794c0b33bb976f94b86c532barmvixl  }
16054a102baf640077d6794c0b33bb976f94b86c532barmvixl  return Operand(dst);
16064a102baf640077d6794c0b33bb976f94b86c532barmvixl}
16074a102baf640077d6794c0b33bb976f94b86c532barmvixl
16084a102baf640077d6794c0b33bb976f94b86c532barmvixl
16094e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Ramesvoid MacroAssembler::Move(const GenericOperand& dst,
16104e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames                          const GenericOperand& src) {
16114e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.Equals(src)) {
16124e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    return;
16134e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16144e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16154e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  VIXL_ASSERT(dst.IsValid() && src.IsValid());
16164e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16174e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  // The sizes of the operands must match exactly.
16184e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  VIXL_ASSERT(dst.GetSizeInBits() == src.GetSizeInBits());
1619f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  VIXL_ASSERT(dst.GetSizeInBits() <= kXRegSize);
1620f5348cedd702124c90fc75e75d0195e2e485c620Pierre Langlois  int operand_size = static_cast<int>(dst.GetSizeInBits());
16214e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16224e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.IsCPURegister() && src.IsCPURegister()) {
16234e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    CPURegister dst_reg = dst.GetCPURegister();
16244e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    CPURegister src_reg = src.GetCPURegister();
16254e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    if (dst_reg.IsRegister() && src_reg.IsRegister()) {
16264e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      Mov(Register(dst_reg), Register(src_reg));
16274e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    } else if (dst_reg.IsVRegister() && src_reg.IsVRegister()) {
16284e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      Fmov(VRegister(dst_reg), VRegister(src_reg));
16294e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    } else {
16304e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      if (dst_reg.IsRegister()) {
16314e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames        Fmov(Register(dst_reg), VRegister(src_reg));
16324e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      } else {
16334e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames        Fmov(VRegister(dst_reg), Register(src_reg));
16344e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      }
16354e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    }
16364e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    return;
16374e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16384e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16394e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.IsMemOperand() && src.IsMemOperand()) {
16404e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    UseScratchRegisterScope temps(this);
16414e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    CPURegister temp = temps.AcquireCPURegisterOfSize(operand_size);
16424e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Ldr(temp, src.GetMemOperand());
16434e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Str(temp, dst.GetMemOperand());
16444e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    return;
16454e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16464e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16474e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.IsCPURegister()) {
16484e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Ldr(dst.GetCPURegister(), src.GetMemOperand());
16494e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  } else {
16504e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Str(src.GetCPURegister(), dst.GetMemOperand());
16514e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16524e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames}
16534e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16544e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::ComputeAddress(const Register& dst,
16565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                    const MemOperand& mem_op) {
16575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // We cannot handle pre-indexing or post-indexing.
165888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(mem_op.GetAddrMode() == Offset);
165988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register base = mem_op.GetBaseRegister();
16605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (mem_op.IsImmediateOffset()) {
166188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(dst, base, mem_op.GetOffset());
16625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
16635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(mem_op.IsRegisterOffset());
166488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register reg_offset = mem_op.GetRegisterOffset();
166588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Shift shift = mem_op.GetShift();
166688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Extend extend = mem_op.GetExtend();
16675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (shift == NO_SHIFT) {
16685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(extend != NO_EXTEND);
166988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Add(dst, base, Operand(reg_offset, extend, mem_op.GetShiftAmount()));
16705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
16715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(extend == NO_EXTEND);
167288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Add(dst, base, Operand(reg_offset, shift, mem_op.GetShiftAmount()));
16735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
16745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
16755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
16765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
16775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1678ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubMacro(const Register& rd,
1679ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Register& rn,
1680ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Operand& operand,
1681ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 FlagsUpdate S,
1682ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 AddSubOp op) {
1683c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is add/sub immediate:
1684c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1685c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for add/sub
1686c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1687c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1688f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsZero() && rd.Is(rn) && rd.Is64Bits() && rn.Is64Bits() &&
1689f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      (S == LeaveFlags)) {
1690f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // The instruction would be a nop. Avoid generating useless code.
1691f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
1692f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1693f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
169488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((operand.IsImmediate() && !IsImmAddSub(operand.GetImmediate())) ||
16950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      (rn.IsZero() && !operand.IsShiftedRegister()) ||
169688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsShiftedRegister() && (operand.GetShift() == ROR))) {
1697b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1698b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
16994a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (operand.IsImmediate()) {
1700210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      PreShiftImmMode mode = kAnyShift;
1701210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell
1702210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      // If the destination or source register is the stack pointer, we can
1703210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      // only pre-shift the immediate right by values supported in the add/sub
1704210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      // extend encoding.
1705210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      if (rd.IsSP()) {
1706210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell        // If the destination is SP and flags will be set, we can't pre-shift
1707210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell        // the immediate at all.
1708210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell        mode = (S == SetFlags) ? kNoShift : kLimitShiftForSP;
1709210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      } else if (rn.IsSP()) {
1710210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell        mode = kLimitShiftForSP;
1711210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell      }
1712210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell
17134a102baf640077d6794c0b33bb976f94b86c532barmvixl      Operand imm_operand =
1714210db2113e52bd22a2835e366ed4abac6e7df2a6Martyn Capewell          MoveImmediateForShiftedOp(temp, operand.GetImmediate(), mode);
17154a102baf640077d6794c0b33bb976f94b86c532barmvixl      AddSub(rd, rn, imm_operand, S, op);
17164a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else {
17174a102baf640077d6794c0b33bb976f94b86c532barmvixl      Mov(temp, operand);
17184a102baf640077d6794c0b33bb976f94b86c532barmvixl      AddSub(rd, rn, temp, S, op);
17194a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
1720ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1721ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSub(rd, rn, operand, S, op);
1722ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1723ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1724ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1725ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1726ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Adc(const Register& rd,
1727ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
1728f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
1729b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1730f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, ADC);
1731f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1732f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1733f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1734f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adcs(const Register& rd,
1735f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1736f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
1737b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1738f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, ADC);
1739ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1740ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1741ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1742ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sbc(const Register& rd,
1743ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
1744f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
1745b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1746f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, SBC);
1747f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1748f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1749f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1750f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Sbcs(const Register& rd,
1751f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1752f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
1753b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1754f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, SBC);
1755ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1756ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1757ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
17580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Ngc(const Register& rd, const Operand& operand) {
1759b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1760ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register zr = AppropriateZeroRegFor(rd);
1761f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbc(rd, zr, operand);
1762f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1763f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1764f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
17650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Ngcs(const Register& rd, const Operand& operand) {
1766b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1767f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Register zr = AppropriateZeroRegFor(rd);
1768f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbcs(rd, zr, operand);
1769ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1770ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1771ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1772ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubWithCarryMacro(const Register& rd,
1773ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Register& rn,
1774ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Operand& operand,
1775ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          FlagsUpdate S,
1776ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          AddSubWithCarryOp op) {
177788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(rd.GetSizeInBits() == rn.GetSizeInBits());
1778c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is addc/subc immediate:
1779c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1780c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for add/sub
1781c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1782b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
1783ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1784ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate() ||
178588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsShiftedRegister() && (operand.GetShift() == ROR))) {
1786ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (immediate or ROR shifted register.)
1787b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
1788ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mov(temp, operand);
1789ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
179088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } else if (operand.IsShiftedRegister() && (operand.GetShiftAmount() != 0)) {
1791ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (shifted register).
179288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() == rd.GetSizeInBits());
179388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShift() != ROR);
179488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
179588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        IsUintN(rd.GetSizeInBits() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
179688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                operand.GetShiftAmount()));
179788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1798b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
179988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    EmitShift(temp,
180088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetRegister(),
180188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShift(),
180288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShiftAmount());
1803ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
1804ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
1805ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (extended register).
180688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() <= rd.GetSizeInBits());
1807ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub extended supports a shift <= 4. We want to support exactly the
1808ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // same modes.
180988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShiftAmount() <= 4);
181088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
181188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        operand.GetRegister().Is64Bits() ||
181288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        ((operand.GetExtend() != UXTX) && (operand.GetExtend() != SXTX)));
181388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1814b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
18150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
181688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
181788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
181888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
1819ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
1820ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1821ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The addressing mode is directly supported by the instruction.
1822ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, operand, S, op);
1823ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1824ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1825ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1826ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
18270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl#define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                          \
18280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) { \
18290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(allow_macro_instructions_);                            \
18300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    LoadStoreMacro(REG, addr, OP);                                     \
18310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1832ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlLS_MACRO_LIST(DEFINE_FUNCTION)
1833ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#undef DEFINE_FUNCTION
1834ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1835330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1836ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::LoadStoreMacro(const CPURegister& rt,
1837ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    const MemOperand& addr,
1838ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    LoadStoreOp op) {
1839c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is ldr/str pre/post index:
1840c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ldr/str
1841c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1842c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to update the base
1843c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1844c68cb64496485710cdb5b8480f8fee287058c93farmvixl
184588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t offset = addr.GetOffset();
18465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned access_size = CalcLSDataSize(op);
1847ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1848ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check if an immediate offset fits in the immediate field of the
1849ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // appropriate instruction. If not, emit two instructions to perform
1850ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the operation.
18515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (addr.IsImmediateOffset() && !IsImmLSScaled(offset, access_size) &&
1852ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      !IsImmLSUnscaled(offset)) {
1853ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Immediate offset that can't be encoded using unsigned or unscaled
1854ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // addressing modes.
1855b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
185688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register temp = temps.AcquireSameSizeAs(addr.GetBaseRegister());
185788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(temp, addr.GetOffset());
185888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister(), temp), op);
1859ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPostIndex() && !IsImmLSUnscaled(offset)) {
1860ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Post-index beyond unscaled addressing range.
186188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister()), op);
186288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(addr.GetBaseRegister(), addr.GetBaseRegister(), Operand(offset));
1863ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPreIndex() && !IsImmLSUnscaled(offset)) {
1864ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Pre-index beyond unscaled addressing range.
186588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(addr.GetBaseRegister(), addr.GetBaseRegister(), Operand(offset));
186688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister()), op);
1867ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1868ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Encodable in one load/store instruction.
1869ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LoadStore(rt, addr, op);
1870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1871ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1872ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1873ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
18740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl#define DEFINE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \
18750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  void MacroAssembler::FN(const REGTYPE REG,        \
18760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const REGTYPE REG2,       \
18770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const MemOperand& addr) { \
18780f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(allow_macro_instructions_);         \
18790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    LoadStorePairMacro(REG, REG2, addr, OP);        \
18800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1881c68cb64496485710cdb5b8480f8fee287058c93farmvixlLSPAIR_MACRO_LIST(DEFINE_FUNCTION)
1882c68cb64496485710cdb5b8480f8fee287058c93farmvixl#undef DEFINE_FUNCTION
1883c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1884c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid MacroAssembler::LoadStorePairMacro(const CPURegister& rt,
1885c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        const CPURegister& rt2,
1886c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        const MemOperand& addr,
1887c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        LoadStorePairOp op) {
1888c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we support register offset for load-store-pair?
1889c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!addr.IsRegisterOffset());
1890c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is ldp/stp immediate:
1891c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ldp/stp
1892c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1893c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to update the base
1894c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1895c68cb64496485710cdb5b8480f8fee287058c93farmvixl
189688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t offset = addr.GetOffset();
18975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned access_size = CalcLSPairDataSize(op);
1898c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1899c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Check if the offset fits in the immediate field of the appropriate
1900c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // instruction. If not, emit two instructions to perform the operation.
19015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsImmLSPair(offset, access_size)) {
1902c68cb64496485710cdb5b8480f8fee287058c93farmvixl    // Encodable in one load/store pair instruction.
1903c68cb64496485710cdb5b8480f8fee287058c93farmvixl    LoadStorePair(rt, rt2, addr, op);
1904c68cb64496485710cdb5b8480f8fee287058c93farmvixl  } else {
190588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register base = addr.GetBaseRegister();
1906c68cb64496485710cdb5b8480f8fee287058c93farmvixl    if (addr.IsImmediateOffset()) {
1907c68cb64496485710cdb5b8480f8fee287058c93farmvixl      UseScratchRegisterScope temps(this);
1908c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Register temp = temps.AcquireSameSizeAs(base);
1909c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(temp, base, offset);
1910c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(temp), op);
1911c68cb64496485710cdb5b8480f8fee287058c93farmvixl    } else if (addr.IsPostIndex()) {
1912c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(base), op);
1913c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(base, base, offset);
1914c68cb64496485710cdb5b8480f8fee287058c93farmvixl    } else {
1915c68cb64496485710cdb5b8480f8fee287058c93farmvixl      VIXL_ASSERT(addr.IsPreIndex());
1916c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(base, base, offset);
1917c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(base), op);
1918c68cb64496485710cdb5b8480f8fee287058c93farmvixl    }
1919c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
1920c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
1921c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1922330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1923330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid MacroAssembler::Prfm(PrefetchOperation op, const MemOperand& addr) {
1924330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MacroEmissionCheckScope guard(this);
1925330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1926330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // There are no pre- or post-index modes for prfm.
1927330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(addr.IsImmediateOffset() || addr.IsRegisterOffset());
1928330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1929330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The access size is implicitly 8 bytes for all prefetch operations.
19305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned size = kXRegSizeInBytesLog2;
1931330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1932330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Check if an immediate offset fits in the immediate field of the
1933330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // appropriate instruction. If not, emit two instructions to perform
1934330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // the operation.
193588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (addr.IsImmediateOffset() && !IsImmLSScaled(addr.GetOffset(), size) &&
193688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      !IsImmLSUnscaled(addr.GetOffset())) {
1937330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate offset that can't be encoded using unsigned or unscaled
1938330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // addressing modes.
1939330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    UseScratchRegisterScope temps(this);
194088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register temp = temps.AcquireSameSizeAs(addr.GetBaseRegister());
194188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(temp, addr.GetOffset());
194288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Prefetch(op, MemOperand(addr.GetBaseRegister(), temp));
1943330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else {
1944330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Simple register-offsets are encodable in one instruction.
1945330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    Prefetch(op, addr);
1946330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
1947330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
1948330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1949330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
19500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Push(const CPURegister& src0,
19510f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src1,
19520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src2,
19530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src3) {
1954b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1955b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
1956b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(src0.IsValid());
1957ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1958ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid();
195988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = src0.GetSizeInBytes();
1960ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1961ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
1962ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushHelper(count, size, src0, src1, src2, src3);
1963ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1964ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1965ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
19660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Pop(const CPURegister& dst0,
19670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst1,
19680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst2,
19690f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst3) {
1970ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // It is not valid to pop into the same register more than once in one
1971ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // instruction, not even into the zero register.
1972b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1973b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(dst0, dst1, dst2, dst3));
1974b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
1975b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(dst0.IsValid());
1976ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1977ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid();
197888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = dst0.GetSizeInBytes();
1979ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1980ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPop(count, size);
1981ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopHelper(count, size, dst0, dst1, dst2, dst3);
1982ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1983ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1984ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1985ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCPURegList(CPURegList registers) {
198688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchRegisterList()));
198788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchFPRegisterList()));
1988b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
19896e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
199088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = registers.GetRegisterSizeInBytes();
199188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  PrepareForPush(registers.GetCount(), reg_size);
19926e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
19936e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // Bump the stack pointer and store two registers at the bottom.
199488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = registers.GetTotalSizeInBytes();
19956e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_0 = registers.PopLowestIndex();
19966e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_1 = registers.PopLowestIndex();
19976e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (bottom_0.IsValid() && bottom_1.IsValid()) {
19986e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Stp(bottom_0, bottom_1, MemOperand(StackPointer(), -size, PreIndex));
19996e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (bottom_0.IsValid()) {
20006e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Str(bottom_0, MemOperand(StackPointer(), -size, PreIndex));
20016e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
20026e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20036e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  int offset = 2 * reg_size;
2004ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
20056e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& src0 = registers.PopLowestIndex();
20066e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& src1 = registers.PopLowestIndex();
20076e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (src1.IsValid()) {
20086e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Stp(src0, src1, MemOperand(StackPointer(), offset));
20096e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
20106e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Str(src0, MemOperand(StackPointer(), offset));
20116e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
20126e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    offset += 2 * reg_size;
2013ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2014ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2015ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2016ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2017ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCPURegList(CPURegList registers) {
201888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchRegisterList()));
201988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchFPRegisterList()));
2020b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
20216e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
202288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = registers.GetRegisterSizeInBytes();
202388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  PrepareForPop(registers.GetCount(), reg_size);
20246e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20256e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
202688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = registers.GetTotalSizeInBytes();
20276e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_0 = registers.PopLowestIndex();
20286e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_1 = registers.PopLowestIndex();
20296e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20306e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  int offset = 2 * reg_size;
2031ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
2032ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst0 = registers.PopLowestIndex();
2033ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst1 = registers.PopLowestIndex();
20346e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (dst1.IsValid()) {
20356e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldp(dst0, dst1, MemOperand(StackPointer(), offset));
20366e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
20376e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldr(dst0, MemOperand(StackPointer(), offset));
20386e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
20396e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    offset += 2 * reg_size;
20406e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
20416e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20426e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // Load the two registers at the bottom and drop the stack pointer.
20436e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (bottom_0.IsValid() && bottom_1.IsValid()) {
20446e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Ldp(bottom_0, bottom_1, MemOperand(StackPointer(), size, PostIndex));
20456e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (bottom_0.IsValid()) {
20466e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Ldr(bottom_0, MemOperand(StackPointer(), size, PostIndex));
2047ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2048ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2049ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2050ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2051ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushMultipleTimes(int count, Register src) {
2052b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
205388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = src.GetSizeInBytes();
2054ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2055ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
2056ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push up to four registers at a time if possible because if the current
2057ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer is sp and the register size is 32, registers must be pushed
2058ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in blocks of four in order to maintain the 16-byte alignment for sp.
2059ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (count >= 4) {
2060ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(4, size, src, src, src, src);
2061ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 4;
2062ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2063ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count >= 2) {
2064ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(2, size, src, src, NoReg, NoReg);
2065ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 2;
2066ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2067ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count == 1) {
2068ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(1, size, src, NoReg, NoReg, NoReg);
2069ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 1;
2070ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2071b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(count == 0);
2072ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2073ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2074ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
20750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PushHelper(int count,
20760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                int size,
2077ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src0,
2078ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src1,
2079ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src2,
2080ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src3) {
2081ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
2082c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case for size is 2 stp.
208307d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  ExactAssemblyScope scope(this,
208407d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames                           2 * kInstructionSize,
208507d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames                           ExactAssemblyScope::kMaximumSize);
2086ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2087b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
208888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(size == src0.GetSizeInBytes());
2089ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2090ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When pushing multiple registers, the store order is chosen such that
2091ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push(a, b) is equivalent to Push(a) followed by Push(b).
2092ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
2093ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
2094b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src1.IsNone() && src2.IsNone() && src3.IsNone());
2095ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), -1 * size, PreIndex));
2096ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2097ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
2098b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src2.IsNone() && src3.IsNone());
2099ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), -2 * size, PreIndex));
2100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
2102b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src3.IsNone());
2103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src2, src1, MemOperand(StackPointer(), -3 * size, PreIndex));
2104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), 2 * size));
2105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
2107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Skip over 4 * size, then fill in the gap. This allows four W registers
2108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be pushed using sp, whilst maintaining 16-byte alignment for sp at
2109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
2110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src3, src2, MemOperand(StackPointer(), -4 * size, PreIndex));
2111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), 2 * size));
2112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
2114b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_UNREACHABLE();
2115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
21190f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PopHelper(int count,
21200f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                               int size,
2121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst0,
2122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst1,
2123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst2,
2124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst3) {
2125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
2126c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case for size is 2 ldp.
212707d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  ExactAssemblyScope scope(this,
212807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames                           2 * kInstructionSize,
212907d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames                           ExactAssemblyScope::kMaximumSize);
2130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2131b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
213288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(size == dst0.GetSizeInBytes());
2133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When popping multiple registers, the load order is chosen such that
2135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Pop(a, b) is equivalent to Pop(a) followed by Pop(b).
2136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
2137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
2138b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst1.IsNone() && dst2.IsNone() && dst3.IsNone());
2139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst0, MemOperand(StackPointer(), 1 * size, PostIndex));
2140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
2142b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst2.IsNone() && dst3.IsNone());
2143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 2 * size, PostIndex));
2144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
2146b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst3.IsNone());
2147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst2, MemOperand(StackPointer(), 2 * size));
2148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 3 * size, PostIndex));
2149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
2151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Load the higher addresses first, then load the lower addresses and skip
2152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // the whole block in the second instruction. This allows four W registers
2153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be popped using sp, whilst maintaining 16-byte alignment for sp at
2154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
2155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size));
2156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex));
2157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
2159b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_UNREACHABLE();
2160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPush(int count, int size) {
2165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
2166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
2167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
2168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
2169b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT((count * size) % 16 == 0);
2170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
2171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Even if the current stack pointer is not the system stack pointer (sp),
2172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the system stack pointer will still be modified in order to comply with
2173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // ABI rules about accessing memory below the system stack pointer.
2174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(count * size);
2175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPop(int count, int size) {
2180db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  USE(count, size);
2181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
2182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
2183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
2184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
2185b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT((count * size) % 16 == 0);
2186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Poke(const Register& src, const Operand& offset) {
2190b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
219288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(offset.GetImmediate() >= 0);
2193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2194ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Str(src, MemOperand(StackPointer(), offset));
2196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2197ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2198ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2199ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Peek(const Register& dst, const Operand& offset) {
2200b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
220288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(offset.GetImmediate() >= 0);
2203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2205ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Ldr(dst, MemOperand(StackPointer(), offset));
2206ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2207ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2208ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2209ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Claim(const Operand& size) {
2210b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2211f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2212f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
2213f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
2214f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
2215f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
221788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(size.GetImmediate() > 0);
2218ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
221988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      VIXL_ASSERT((size.GetImmediate() % 16) == 0);
2220ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2221ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2222ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
2224ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(size);
2225ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2226ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2227ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Sub(StackPointer(), StackPointer(), size);
2228ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2229ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2230ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2231ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Drop(const Operand& size) {
2232b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2233f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2234f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
2235f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
2236f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
2237f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2238ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
223988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(size.GetImmediate() > 0);
2240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
224188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      VIXL_ASSERT((size.GetImmediate() % 16) == 0);
2242ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2243ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Add(StackPointer(), StackPointer(), size);
2246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2247ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2248ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2249ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCalleeSavedRegisters() {
2250ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
2251c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // 10 stp will be emitted.
2252c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we use GetCalleeSaved and SavedFP.
225307d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  ExactAssemblyScope scope(this, 10 * kInstructionSize);
2254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2255ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
2256b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
2257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2258db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  MemOperand tos(sp, -2 * static_cast<int>(kXRegSizeInBytes), PreIndex);
2259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2260ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x29, x30, tos);
2261ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x27, x28, tos);
2262ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x25, x26, tos);
2263ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x23, x24, tos);
2264ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x21, x22, tos);
2265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x19, x20, tos);
22665799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
22675799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d14, d15, tos);
22685799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d12, d13, tos);
22695799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d10, d11, tos);
22705799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d8, d9, tos);
2271ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2272ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2273ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2274ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCalleeSavedRegisters() {
2275ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
2276c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // 10 ldp will be emitted.
2277c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we use GetCalleeSaved and SavedFP.
227807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  ExactAssemblyScope scope(this, 10 * kInstructionSize);
2279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
2281b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
2282ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2283ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemOperand tos(sp, 2 * kXRegSizeInBytes, PostIndex);
2284ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
22855799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d8, d9, tos);
22865799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d10, d11, tos);
22875799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d12, d13, tos);
22885799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d14, d15, tos);
22895799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x19, x20, tos);
2291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x21, x22, tos);
2292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x23, x24, tos);
2293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x25, x26, tos);
2294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x27, x28, tos);
2295ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x29, x30, tos);
2296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2297ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
22986e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::LoadCPURegList(CPURegList registers,
22996e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                    const MemOperand& src) {
23006e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  LoadStoreCPURegListHelper(kLoad, registers, src);
23016e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
23026e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23036e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::StoreCPURegList(CPURegList registers,
23046e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                     const MemOperand& dst) {
23056e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  LoadStoreCPURegListHelper(kStore, registers, dst);
23066e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
23076e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23086e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23096e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::LoadStoreCPURegListHelper(LoadStoreCPURegListAction op,
23106e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                               CPURegList registers,
23116e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                               const MemOperand& mem) {
23126e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // We do not handle pre-indexing or post-indexing.
23136e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!(mem.IsPreIndex() || mem.IsPostIndex()));
23146e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.Overlaps(tmp_list_));
23156e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.Overlaps(fptmp_list_));
23166e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.IncludesAliasOf(sp));
23176e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23186e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  UseScratchRegisterScope temps(this);
23196e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23200f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  MemOperand loc = BaseMemOperandForLoadStoreCPURegList(registers, mem, &temps);
23216a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  const int reg_size = registers.GetRegisterSizeInBytes();
23226e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23236a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  VIXL_ASSERT(IsPowerOf2(reg_size));
23246a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov
23256a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // Since we are operating on register pairs, we would like to align on double
23266a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // the standard size; on the other hand, we don't want to insert an extra
23276a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // operation, which will happen if the number of registers is even. Note that
23286a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // the alignment of the base pointer is unknown here, but we assume that it
23296a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // is more likely to be aligned.
23306a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  if (((loc.GetOffset() & (2 * reg_size - 1)) != 0) &&
23316a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      ((registers.GetCount() % 2) != 0)) {
23326a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    if (op == kStore) {
23336a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      Str(registers.PopLowestIndex(), loc);
23346a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    } else {
23356a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      VIXL_ASSERT(op == kLoad);
23366a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      Ldr(registers.PopLowestIndex(), loc);
23376a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    }
23386a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    loc.AddOffset(reg_size);
23396a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  }
234088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  while (registers.GetCount() >= 2) {
23416e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& dst0 = registers.PopLowestIndex();
23426e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& dst1 = registers.PopLowestIndex();
23436e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (op == kStore) {
23446e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Stp(dst0, dst1, loc);
23456e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
23466e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      VIXL_ASSERT(op == kLoad);
23476e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldp(dst0, dst1, loc);
23486e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
23496a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    loc.AddOffset(2 * reg_size);
23506e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
23516e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (!registers.IsEmpty()) {
23526e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (op == kStore) {
23536e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Str(registers.PopLowestIndex(), loc);
23546e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
23556e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      VIXL_ASSERT(op == kLoad);
23566e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldr(registers.PopLowestIndex(), loc);
23576e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
23586e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
23596e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
23606e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23616e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlMemOperand MacroAssembler::BaseMemOperandForLoadStoreCPURegList(
23626e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegList& registers,
23636e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const MemOperand& mem,
23646e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    UseScratchRegisterScope* scratch_scope) {
23656e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // If necessary, pre-compute the base address for the accesses.
23666e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (mem.IsRegisterOffset()) {
23676e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Register reg_base = scratch_scope->AcquireX();
23686e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    ComputeAddress(reg_base, mem);
23696e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    return MemOperand(reg_base);
23706e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23716e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (mem.IsImmediateOffset()) {
237288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int reg_size = registers.GetRegisterSizeInBytes();
237388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int total_size = registers.GetTotalSizeInBytes();
237488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t min_offset = mem.GetOffset();
237588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t max_offset =
237688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        mem.GetOffset() + std::max(0, total_size - 2 * reg_size);
237788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if ((registers.GetCount() >= 2) &&
23786e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        (!Assembler::IsImmLSPair(min_offset, WhichPowerOf2(reg_size)) ||
23796e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl         !Assembler::IsImmLSPair(max_offset, WhichPowerOf2(reg_size)))) {
23806e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Register reg_base = scratch_scope->AcquireX();
23816e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      ComputeAddress(reg_base, mem);
23826e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      return MemOperand(reg_base);
23836e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
23846e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
23856e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23866e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  return mem;
23876e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
23886e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
2389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::BumpSystemStackPointer(const Operand& space) {
2390b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!sp.Is(StackPointer()));
2391ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // TODO: Several callers rely on this not using scratch registers, so we use
2392ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the assembler directly here. However, this means that large immediate
2393ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // values of 'space' cannot be handled.
239407d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  ExactAssemblyScope scope(this, kInstructionSize);
2395ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  sub(sp, StackPointer(), space);
2396ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2397ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2398ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
23995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// TODO(all): Fix printf for NEON registers, and resolve whether we should be
24005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// using FPRegister or VRegister here.
24015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// This is the main Printf implementation. All callee-saved registers are
2403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// preserved, but NZCV and the caller-saved registers may be clobbered.
24040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PrintfNoPreserve(const char* format,
2405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg0,
2406ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg1,
2407ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg2,
2408ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg3) {
2409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We cannot handle a caller-saved stack pointer. It doesn't make much sense
2410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in most cases anyway, so this restriction shouldn't be too serious.
2411b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!kCallerSaved.IncludesAliasOf(StackPointer()));
2412b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
24135799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // The provided arguments, and their proper PCS registers.
24145799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegister args[kPrintfMaxArgCount] = {arg0, arg1, arg2, arg3};
24155799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegister pcs[kPrintfMaxArgCount];
24165799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24175799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  int arg_count = kPrintfMaxArgCount;
24185799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24195799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // The PCS varargs registers for printf. Note that x0 is used for the printf
24205799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // format string.
24215799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  static const CPURegList kPCSVarargs =
24225799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      CPURegList(CPURegister::kRegister, kXRegSize, 1, arg_count);
24235799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  static const CPURegList kPCSVarargsFP =
24245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      CPURegList(CPURegister::kVRegister, kDRegSize, 0, arg_count - 1);
24255799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24265799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // We can use caller-saved registers as scratch values, except for the
24275799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // arguments and the PCS registers where they might need to go.
2428b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
24295799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Include(kCallerSaved);
24305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  temps.Include(kCallerSavedV);
24315799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(kPCSVarargs);
24325799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(kPCSVarargsFP);
2433b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  temps.Exclude(arg0, arg1, arg2, arg3);
2434ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24355799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Copies of the arg lists that we can iterate through.
24365799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegList pcs_varargs = kPCSVarargs;
24375799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegList pcs_varargs_fp = kPCSVarargsFP;
24385799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24395799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Place the arguments. There are lots of clever tricks and optimizations we
24405799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // could use here, but Printf is a debug tool so instead we just try to keep
24415799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // it simple: Move each input that isn't already in the right place to a
24425799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // scratch register, then move everything back.
24435799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  for (unsigned i = 0; i < kPrintfMaxArgCount; i++) {
24445799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Work out the proper PCS register for this argument.
2445ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (args[i].IsRegister()) {
24465799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      pcs[i] = pcs_varargs.PopLowestIndex().X();
24475799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // We might only need a W register here. We need to know the size of the
24485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // argument so we can properly encode it for the simulator call.
24495799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (args[i].Is32Bits()) pcs[i] = pcs[i].W();
24505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else if (args[i].IsVRegister()) {
24515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // In C, floats are always cast to doubles for varargs calls.
24525799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      pcs[i] = pcs_varargs_fp.PopLowestIndex().D();
2453ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
24545799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      VIXL_ASSERT(args[i].IsNone());
2455ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      arg_count = i;
2456ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2457ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2458ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24595799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // If the argument is already in the right place, leave it where it is.
24605799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (args[i].Aliases(pcs[i])) continue;
24615799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24625799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Otherwise, if the argument is in a PCS argument register, allocate an
24635799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // appropriate scratch register and then move it out of the way.
24645799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (kPCSVarargs.IncludesAliasOf(args[i]) ||
24655799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        kPCSVarargsFP.IncludesAliasOf(args[i])) {
24665799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (args[i].IsRegister()) {
24675799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Register old_arg = Register(args[i]);
24685799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Register new_arg = temps.AcquireSameSizeAs(old_arg);
24695799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Mov(new_arg, old_arg);
24705799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        args[i] = new_arg;
24715799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
24725799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        FPRegister old_arg = FPRegister(args[i]);
24735799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        FPRegister new_arg = temps.AcquireSameSizeAs(old_arg);
24745799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fmov(new_arg, old_arg);
24755799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        args[i] = new_arg;
24765799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
24775799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
2478ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2479ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24805799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Do a second pass to move values into their final positions and perform any
24815799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // conversions that may be required.
24825799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  for (int i = 0; i < arg_count; i++) {
248388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(pcs[i].GetType() == args[i].GetType());
24845799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (pcs[i].IsRegister()) {
24855799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      Mov(Register(pcs[i]), Register(args[i]), kDiscardForSameWReg);
2486ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
24875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(pcs[i].IsVRegister());
248888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (pcs[i].GetSizeInBits() == args[i].GetSizeInBits()) {
24895799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fmov(FPRegister(pcs[i]), FPRegister(args[i]));
24905799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
24915799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fcvt(FPRegister(pcs[i]), FPRegister(args[i]));
24925799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
2493ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2494ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2495ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2496ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Load the format string into x0, as per the procedure-call standard.
2497ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //
2498ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // To make the code as portable as possible, the format string is encoded
2499ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // directly in the instruction stream. It might be cleaner to encode it in a
2500ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // literal pool, but since Printf is usually used for debugging, it is
2501ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // beneficial for it to be minimally dependent on other features.
25025799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(x0);
2503ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Label format_address;
2504ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Adr(x0, &format_address);
2505ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2506ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Emit the format string directly in the instruction stream.
2507c68cb64496485710cdb5b8480f8fee287058c93farmvixl  {
25085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    BlockPoolsScope scope(this);
2509c68cb64496485710cdb5b8480f8fee287058c93farmvixl    // Data emitted:
2510c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   branch
2511c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   strlen(format) + 1 (includes null termination)
2512c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   padding to next instruction
2513c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   unreachable
25140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmissionCheckScope guard(this,
25150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             AlignUp(strlen(format) + 1, kInstructionSize) +
25160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2 * kInstructionSize);
2517ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Label after_data;
2518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    B(&after_data);
2519ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&format_address);
2520c68cb64496485710cdb5b8480f8fee287058c93farmvixl    EmitString(format);
2521ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Unreachable();
2522ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&after_data);
2523ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2524ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2525ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We don't pass any arguments on the stack, but we still need to align the C
2526ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer to a 16-byte boundary for PCS compliance.
2527ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
2528ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bic(sp, StackPointer(), 0xf);
2529ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2530ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2531ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Actually call printf. This part needs special handling for the simulator,
2532ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // since the system printf function will use a different instruction set and
2533ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the procedure-call standard will not be compatible.
2534703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
253507d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames    ExactAssemblyScope scope(this, kPrintfLength);
2536ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    hlt(kPrintfOpcode);
25370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    dc32(arg_count);  // kPrintfArgCountOffset
25385799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
25395799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Determine the argument pattern.
25405799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    uint32_t arg_pattern_list = 0;
25415799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    for (int i = 0; i < arg_count; i++) {
25425799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      uint32_t arg_pattern;
25435799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (pcs[i].IsRegister()) {
25445799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        arg_pattern = pcs[i].Is32Bits() ? kPrintfArgW : kPrintfArgX;
25455799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
25465799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        VIXL_ASSERT(pcs[i].Is64Bits());
25475799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        arg_pattern = kPrintfArgD;
25485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
25495799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      VIXL_ASSERT(arg_pattern < (1 << kPrintfArgPatternBits));
25505799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i));
25515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
25520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    dc32(arg_pattern_list);  // kPrintfArgPatternListOffset
2553684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2554684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Register tmp = temps.AcquireX();
2555684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Mov(tmp, reinterpret_cast<uintptr_t>(printf));
2556684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Blr(tmp);
2557ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2558ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2559ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2560ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
25610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Printf(const char* format,
25625799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg0,
25635799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg1,
25645799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg2,
25655799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg3) {
25665799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // We can only print sp if it is the current stack pointer.
25675799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  if (!sp.Is(StackPointer())) {
25685799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg0));
25695799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg1));
25705799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg2));
25715799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg3));
25725799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
25735799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2574b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // Make sure that the macro assembler doesn't try to use any of our arguments
2575b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // as scratch registers.
2576b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope exclude_all(this);
2577b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  exclude_all.ExcludeAll();
2578b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2579ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Preserve all caller-saved registers as well as NZCV.
2580ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // If sp is the stack pointer, PushCPURegList asserts that the size of each
2581ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // list is a multiple of 16 bytes.
2582ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushCPURegList(kCallerSaved);
25835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  PushCPURegList(kCallerSavedV);
2584ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
25850f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  {
25860f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    UseScratchRegisterScope temps(this);
2587b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    // We can use caller-saved registers as scratch values (except for argN).
25885799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Include(kCallerSaved);
25895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    temps.Include(kCallerSavedV);
2590b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    temps.Exclude(arg0, arg1, arg2, arg3);
2591b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
25925799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // If any of the arguments are the current stack pointer, allocate a new
25935799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // register for them, and adjust the value to compensate for pushing the
25945799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // caller-saved registers.
25955799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg0_sp = StackPointer().Aliases(arg0);
25965799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg1_sp = StackPointer().Aliases(arg1);
25975799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg2_sp = StackPointer().Aliases(arg2);
25985799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg3_sp = StackPointer().Aliases(arg3);
25995799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (arg0_sp || arg1_sp || arg2_sp || arg3_sp) {
26005799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // Allocate a register to hold the original stack pointer value, to pass
26015799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // to PrintfNoPreserve as an argument.
26025799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      Register arg_sp = temps.AcquireX();
26030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Add(arg_sp,
26040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl          StackPointer(),
260588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          kCallerSaved.GetTotalSizeInBytes() +
260688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              kCallerSavedV.GetTotalSizeInBytes());
260788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg0_sp) arg0 = Register(arg_sp.GetCode(), arg0.GetSizeInBits());
260888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg1_sp) arg1 = Register(arg_sp.GetCode(), arg1.GetSizeInBits());
260988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg2_sp) arg2 = Register(arg_sp.GetCode(), arg2.GetSizeInBits());
261088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg3_sp) arg3 = Register(arg_sp.GetCode(), arg3.GetSizeInBits());
26115799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
26125799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2613b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    // Preserve NZCV.
2614b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register tmp = temps.AcquireX();
2615b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Mrs(tmp, NZCV);
2616b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Push(tmp, xzr);
26175799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Release(tmp);
2618b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2619b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    PrintfNoPreserve(format, arg0, arg1, arg2, arg3);
2620b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
26215799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Restore NZCV.
26225799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    tmp = temps.AcquireX();
2623b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Pop(xzr, tmp);
2624b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Msr(NZCV, tmp);
26255799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Release(tmp);
2626b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2627ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
26285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  PopCPURegList(kCallerSavedV);
2629ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopCPURegList(kCallerSaved);
2630ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2631ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2632ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Trace(TraceParameters parameters, TraceCommand command) {
2633b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2634ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2635703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2636684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // The arguments to the trace pseudo instruction need to be contiguous in
2637684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // memory, so make sure we don't try to emit a literal pool.
263807d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames    ExactAssemblyScope scope(this, kTraceLength);
2639ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2640684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Label start;
2641684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    bind(&start);
2642ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2643d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames    // Refer to simulator-aarch64.h for a description of the marker and its
2644684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // arguments.
2645684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    hlt(kTraceOpcode);
2646ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
264788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kTraceParamsOffset);
2648684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(parameters);
2649ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
265088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kTraceCommandOffset);
2651684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(command);
2652684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2653684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // Emit nothing on real hardware.
2654684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    USE(parameters, command);
2655684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  }
2656ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2657ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2658ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2659ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Log(TraceParameters parameters) {
2660b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2661ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2662703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2663684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // The arguments to the log pseudo instruction need to be contiguous in
2664684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // memory, so make sure we don't try to emit a literal pool.
266507d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames    ExactAssemblyScope scope(this, kLogLength);
2666ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2667684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Label start;
2668684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    bind(&start);
2669ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2670d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames    // Refer to simulator-aarch64.h for a description of the marker and its
2671684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // arguments.
2672684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    hlt(kLogOpcode);
2673ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
267488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kLogParamsOffset);
2675684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(parameters);
2676684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2677684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // Emit nothing on real hardware.
2678684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    USE(parameters);
2679684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  }
2680ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2681ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2682578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2683578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::EnableInstrumentation() {
2684b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!isprint(InstrumentStateEnable));
268507d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  ExactAssemblyScope scope(this, kInstructionSize);
2686578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateEnable);
2687578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2688578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2689578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2690578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::DisableInstrumentation() {
2691b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!isprint(InstrumentStateDisable));
269207d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  ExactAssemblyScope scope(this, kInstructionSize);
2693578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateDisable);
2694578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2695578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2696578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2697578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
2698b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(strlen(marker_name) == 2);
2699578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2700578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // We allow only printable characters in the marker names. Unprintable
2701578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // characters are reserved for controlling features of the instrumentation.
2702b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(isprint(marker_name[0]) && isprint(marker_name[1]));
2703578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
270407d1aa5b941ace15deb01e5df2c79e677039c4aeAlexandre Rames  ExactAssemblyScope scope(this, kInstructionSize);
2705578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, (marker_name[1] << 8) | marker_name[0]);
2706578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2707578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2708b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2709330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid UseScratchRegisterScope::Open(MacroAssembler* masm) {
2710e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  VIXL_ASSERT(masm_ == NULL);
27110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(masm != NULL);
2712e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  masm_ = masm;
2713330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2714e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  CPURegList* available = masm->GetScratchRegisterList();
2715e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  CPURegList* available_fp = masm->GetScratchFPRegisterList();
2716e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  old_available_ = available->GetList();
2717e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  old_availablefp_ = available_fp->GetList();
2718e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  VIXL_ASSERT(available->GetType() == CPURegister::kRegister);
2719e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  VIXL_ASSERT(available_fp->GetType() == CPURegister::kVRegister);
2720330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2721e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  parent_ = masm->GetCurrentScratchRegisterScope();
2722e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  masm->SetCurrentScratchRegisterScope(this);
2723330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2724330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2725330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2726e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramleyvoid UseScratchRegisterScope::Close() {
2727e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  if (masm_ != NULL) {
2728e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    // Ensure that scopes nest perfectly, and do not outlive their parents.
2729e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    // This is a run-time check because the order of destruction of objects in
2730e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    // the _same_ scope is implementation-defined, and is likely to change in
2731e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    // optimised builds.
2732e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    VIXL_CHECK(masm_->GetCurrentScratchRegisterScope() == this);
2733e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    masm_->SetCurrentScratchRegisterScope(parent_);
2734330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2735e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    masm_->GetScratchRegisterList()->SetList(old_available_);
2736e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    masm_->GetScratchFPRegisterList()->SetList(old_availablefp_);
2737330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2738e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    masm_ = NULL;
2739e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  }
2740e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley}
2741b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2742b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27435799d6c5d10729eaade85ad608109c83ed1ae63barmvixlbool UseScratchRegisterScope::IsAvailable(const CPURegister& reg) const {
2744e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  return masm_->GetScratchRegisterList()->IncludesAliasOf(reg) ||
2745e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley         masm_->GetScratchFPRegisterList()->IncludesAliasOf(reg);
27465799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
27475799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
27485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
27494e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre RamesRegister UseScratchRegisterScope::AcquireRegisterOfSize(int size_in_bits) {
2750e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  int code = AcquireNextAvailable(masm_->GetScratchRegisterList()).GetCode();
27514e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  return Register(code, size_in_bits);
2752b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2753b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2754b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27554e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre RamesFPRegister UseScratchRegisterScope::AcquireVRegisterOfSize(int size_in_bits) {
2756e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  int code = AcquireNextAvailable(masm_->GetScratchFPRegisterList()).GetCode();
27574e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  return FPRegister(code, size_in_bits);
2758b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2759b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2760b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2761b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Release(const CPURegister& reg) {
2762e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  VIXL_ASSERT(masm_ != NULL);
2763b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (reg.IsRegister()) {
2764e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    ReleaseByCode(masm_->GetScratchRegisterList(), reg.GetCode());
276573d8387decc511b147888da15fe5128e47fe2f28Artem Serov  } else if (reg.IsVRegister()) {
2766e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    ReleaseByCode(masm_->GetScratchFPRegisterList(), reg.GetCode());
2767b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
2768b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT(reg.IsNone());
2769b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2770b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2771b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2772b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27735799d6c5d10729eaade85ad608109c83ed1ae63barmvixlvoid UseScratchRegisterScope::Include(const CPURegList& list) {
2774e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  VIXL_ASSERT(masm_ != NULL);
277588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (list.GetType() == CPURegister::kRegister) {
27765799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Make sure that neither sp nor xzr are included the list.
2777e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    IncludeByRegList(masm_->GetScratchRegisterList(),
277888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                     list.GetList() & ~(xzr.GetBit() | sp.GetBit()));
27795799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  } else {
278088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(list.GetType() == CPURegister::kVRegister);
2781e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    IncludeByRegList(masm_->GetScratchFPRegisterList(), list.GetList());
27825799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
27835799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
27845799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
27855799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2786b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Include(const Register& reg1,
2787b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg2,
2788b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg3,
2789b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg4) {
2790e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  VIXL_ASSERT(masm_ != NULL);
279188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList include =
279288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2793b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // Make sure that neither sp nor xzr are included the list.
279488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  include &= ~(xzr.GetBit() | sp.GetBit());
2795b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2796e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  IncludeByRegList(masm_->GetScratchRegisterList(), include);
2797b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2798b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2799b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2800b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Include(const FPRegister& reg1,
2801b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg2,
2802b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg3,
2803b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg4) {
280488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList include =
280588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2806e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  IncludeByRegList(masm_->GetScratchFPRegisterList(), include);
2807b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2808b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2809b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
28105799d6c5d10729eaade85ad608109c83ed1ae63barmvixlvoid UseScratchRegisterScope::Exclude(const CPURegList& list) {
281188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (list.GetType() == CPURegister::kRegister) {
2812e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    ExcludeByRegList(masm_->GetScratchRegisterList(), list.GetList());
28135799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  } else {
281488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(list.GetType() == CPURegister::kVRegister);
2815e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley    ExcludeByRegList(masm_->GetScratchFPRegisterList(), list.GetList());
28165799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
28175799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
28185799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
28195799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2820b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const Register& reg1,
2821b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg2,
2822b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg3,
2823b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg4) {
282488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList exclude =
282588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2826e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  ExcludeByRegList(masm_->GetScratchRegisterList(), exclude);
2827b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2828b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2829b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2830b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const FPRegister& reg1,
2831b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg2,
2832b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg3,
2833b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg4) {
283488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList excludefp =
283588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2836e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  ExcludeByRegList(masm_->GetScratchFPRegisterList(), excludefp);
2837b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2838b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2839b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2840b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const CPURegister& reg1,
2841b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg2,
2842b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg3,
2843b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg4) {
2844b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  RegList exclude = 0;
2845b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  RegList excludefp = 0;
2846b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2847b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  const CPURegister regs[] = {reg1, reg2, reg3, reg4};
2848b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2849b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  for (unsigned i = 0; i < (sizeof(regs) / sizeof(regs[0])); i++) {
2850b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (regs[i].IsRegister()) {
285188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      exclude |= regs[i].GetBit();
2852b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else if (regs[i].IsFPRegister()) {
285388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      excludefp |= regs[i].GetBit();
2854b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else {
2855b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(regs[i].IsNone());
2856b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    }
2857b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2858b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2859e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  ExcludeByRegList(masm_->GetScratchRegisterList(), exclude);
2860e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  ExcludeByRegList(masm_->GetScratchFPRegisterList(), excludefp);
2861b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2862b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2863b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2864b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ExcludeAll() {
2865e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  ExcludeByRegList(masm_->GetScratchRegisterList(),
2866e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley                   masm_->GetScratchRegisterList()->GetList());
2867e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley  ExcludeByRegList(masm_->GetScratchFPRegisterList(),
2868e8ce9f0ec7fe9484fca0c446ecc8a9d7929bea66Jacob Bramley                   masm_->GetScratchFPRegisterList()->GetList());
2869b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2870b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2871b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2872b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlCPURegister UseScratchRegisterScope::AcquireNextAvailable(
2873b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    CPURegList* available) {
2874b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_CHECK(!available->IsEmpty());
2875b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  CPURegister result = available->PopLowestIndex();
2876b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(result, xzr, sp));
2877b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  return result;
2878b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2879b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2880b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2881b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ReleaseByCode(CPURegList* available, int code) {
2882b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ReleaseByRegList(available, static_cast<RegList>(1) << code);
2883b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2884b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2885b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2886b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ReleaseByRegList(CPURegList* available,
2887b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList regs) {
288888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() | regs);
2889b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2890b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2891b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2892b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::IncludeByRegList(CPURegList* available,
2893b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList regs) {
289488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() | regs);
2895b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2896b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2897b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2898b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ExcludeByRegList(CPURegList* available,
2899b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList exclude) {
290088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() & ~exclude);
2901b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2902b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
290388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch64
2904ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
2905