macro-assembler-aarch64.cc revision 78973f258039f6e96eba85f1b5ecdb14b3c51dbb
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
29d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames#include "aarch64/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() {
68c68cb64496485710cdb5b8480f8fee287058c93farmvixl  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
93c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid LiteralPool::Emit(EmitOption option) {
94c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // There is an issue if we are asked to emit a blocked or empty pool.
95c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!IsBlocked());
96c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!IsEmpty());
97c68cb64496485710cdb5b8480f8fee287058c93farmvixl
9888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  size_t pool_size = GetSize();
99c68cb64496485710cdb5b8480f8fee287058c93farmvixl  size_t emit_size = pool_size;
100c68cb64496485710cdb5b8480f8fee287058c93farmvixl  if (option == kBranchRequired) emit_size += kInstructionSize;
101c68cb64496485710cdb5b8480f8fee287058c93farmvixl  Label end_of_pool;
102c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(emit_size % kInstructionSize == 0);
104de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  {
105de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    CodeBufferCheckScope guard(masm_,
106de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                               emit_size,
107de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                               CodeBufferCheckScope::kCheck,
108de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                               CodeBufferCheckScope::kExactSize);
109de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames#ifdef VIXL_DEBUG
110de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    // Also explicitly disallow usage of the `MacroAssembler` here.
111de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    masm_->SetAllowMacroInstructions(false);
112de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames#endif
113de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    if (option == kBranchRequired) {
114de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      InstructionAccurateScope guard(masm_,
115de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                     1,
116de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                     CodeBufferCheckScope::kExactSize,
117de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                     EmissionCheckScope::kIgnorePools);
118de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      masm_->b(&end_of_pool);
119de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    }
120c68cb64496485710cdb5b8480f8fee287058c93farmvixl
121de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    {
122de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      // Marker indicating the size of the literal pool in 32-bit words.
123de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      VIXL_ASSERT((pool_size % kWRegSizeInBytes) == 0);
124de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      InstructionAccurateScope guard(masm_,
125de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                     1,
126de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                     CodeBufferCheckScope::kExactSize,
127de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                     EmissionCheckScope::kIgnorePools);
128de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      masm_->ldr(xzr, static_cast<int>(pool_size / kWRegSizeInBytes));
129de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    }
130c68cb64496485710cdb5b8480f8fee287058c93farmvixl
131de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    // Now populate the literal pool.
132de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    std::vector<RawLiteral*>::iterator it, end;
133de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    for (it = entries_.begin(), end = entries_.end(); it != end; ++it) {
134de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      VIXL_ASSERT((*it)->IsUsed());
135de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      masm_->place(*it);
136de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    }
137c68cb64496485710cdb5b8480f8fee287058c93farmvixl
138de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    if (option == kBranchRequired) masm_->bind(&end_of_pool);
139de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames#ifdef VIXL_DEBUG
140de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    masm_->SetAllowMacroInstructions(true);
141de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames#endif
142de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  }
143c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Reset();
1455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
148db6443499376478f5281607a3923e6ffc4c8d8ecarmvixlvoid LiteralPool::AddEntry(RawLiteral* literal) {
149db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  // A literal must be registered immediately before its first use. Here we
150db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  // cannot control that it is its first use, but we check no code has been
151db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  // emitted since its last use.
15288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(masm_->GetCursorOffset() == literal->GetLastUse());
1535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
15488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  UpdateFirstUse(masm_->GetCursorOffset());
15588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(masm_->GetCursorOffset() >= first_use_);
1565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  entries_.push_back(literal);
15788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  size_ += literal->GetSize();
158db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl}
159db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl
1605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
161db6443499376478f5281607a3923e6ffc4c8d8ecarmvixlvoid LiteralPool::UpdateFirstUse(ptrdiff_t use_position) {
162db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  first_use_ = std::min(first_use_, use_position);
163db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  if (first_use_ == -1) {
164db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    first_use_ = use_position;
16588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    SetNextRecommendedCheckpoint(GetNextRecommendedCheckpoint());
166db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    SetNextCheckpoint(first_use_ + Instruction::kLoadLiteralRange);
167db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  } else {
168db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    VIXL_ASSERT(use_position > first_use_);
169db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  }
1705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::Reset() {
1745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Pool::Reset();
1755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unresolved_branches_.Reset();
1765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::Release() {
1805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (--monitor_ == 0) {
1815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(IsEmpty() ||
18288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                masm_->GetCursorOffset() <
18388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    unresolved_branches_.GetFirstLimit());
1845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
185c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
186c68cb64496485710cdb5b8480f8fee287058c93farmvixl
187c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::RegisterUnresolvedBranch(ptrdiff_t branch_pos,
1895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                          Label* label,
1905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                          ImmBranchType branch_type) {
1915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!label->IsBound());
1925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  BranchInfo branch_info = BranchInfo(branch_pos, label, branch_type);
1935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unresolved_branches_.insert(branch_info);
1945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UpdateNextCheckPoint();
1955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // TODO: In debug mode register the label with the assembler to make sure it
1965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // is bound with masm Bind and not asm bind.
1975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::DeleteUnresolvedBranchInfoForLabel(Label* label) {
201c68cb64496485710cdb5b8480f8fee287058c93farmvixl  if (IsEmpty()) {
2025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(checkpoint_ == kNoCheckpointRequired);
2035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
204c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
205c68cb64496485710cdb5b8480f8fee287058c93farmvixl
2065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsLinked()) {
2075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label::LabelLinksIterator links_it(label);
2085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (; !links_it.Done(); links_it.Advance()) {
2095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      ptrdiff_t link_offset = *links_it.Current();
21088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Instruction* link = masm_->GetInstructionAt(link_offset);
211c68cb64496485710cdb5b8480f8fee287058c93farmvixl
2125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // ADR instructions are not handled.
21388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (BranchTypeUsesVeneers(link->GetBranchType())) {
21488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        BranchInfo branch_info(link_offset, label, link->GetBranchType());
2155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        unresolved_branches_.erase(branch_info);
2165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
2175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
2185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UpdateNextCheckPoint();
2215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
2225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
224db6443499376478f5281607a3923e6ffc4c8d8ecarmvixlbool VeneerPool::ShouldEmitVeneer(int64_t max_reachable_pc, size_t amount) {
2255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  ptrdiff_t offset =
22688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      kPoolNonVeneerCodeSize + amount + GetMaxSize() + GetOtherPoolsMaxSize();
22788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return (masm_->GetCursorOffset() + offset) > max_reachable_pc;
2285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
2295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::CheckEmitFor(size_t amount, EmitOption option) {
2325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsEmpty()) return;
2335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
23488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(masm_->GetCursorOffset() < unresolved_branches_.GetFirstLimit());
2355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsBlocked()) return;
2375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (ShouldEmitVeneers(amount)) {
2395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Emit(option, amount);
2405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
2415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UpdateNextCheckPoint();
2425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
2445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::Emit(EmitOption option, size_t amount) {
2475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // There is an issue if we are asked to emit a blocked or empty pool.
2485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!IsBlocked());
2495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!IsEmpty());
2505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Label end;
2525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (option == kBranchRequired) {
253de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    InstructionAccurateScope guard(masm_,
254de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                   1,
255de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                   CodeBufferCheckScope::kExactSize,
256de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                   EmissionCheckScope::kIgnorePools);
2575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    masm_->b(&end);
2585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // We want to avoid generating veneer pools too often, so generate veneers for
2615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // branches that don't immediately require a veneer but will soon go out of
2625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // range.
2635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  static const size_t kVeneerEmissionMargin = 1 * KBytes;
2645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (BranchInfoSetIterator it(&unresolved_branches_); !it.Done();) {
2665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    BranchInfo* branch_info = it.Current();
2675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (ShouldEmitVeneer(branch_info->max_reachable_pc_,
2685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                         amount + kVeneerEmissionMargin)) {
269de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      CodeBufferCheckScope scope(masm_,
270de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                 kVeneerCodeSize,
271de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                 CodeBufferCheckScope::kCheck,
272de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                 CodeBufferCheckScope::kExactSize);
2735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      ptrdiff_t branch_pos = branch_info->pc_offset_;
27488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Instruction* branch = masm_->GetInstructionAt(branch_pos);
2755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Label* label = branch_info->label_;
2765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // Patch the branch to point to the current position, and emit a branch
2785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // to the label.
2795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Instruction* veneer = masm_->GetCursorAddress<Instruction*>();
2805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      branch->SetImmPCOffsetTarget(veneer);
281de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      {
282de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames        InstructionAccurateScope guard(masm_,
283de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                       1,
284de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                       CodeBufferCheckScope::kExactSize,
285de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                       EmissionCheckScope::kIgnorePools);
286de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames        masm_->b(label);
287de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames      }
2885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // Update the label. The branch patched does not point to it any longer.
2905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      label->DeleteLink(branch_pos);
2915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      it.DeleteCurrentAndAdvance();
2935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
2945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      it.AdvanceToNextType();
2955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
2965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UpdateNextCheckPoint();
2995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
3005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  masm_->bind(&end);
301c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
302c68cb64496485710cdb5b8480f8fee287058c93farmvixl
303c68cb64496485710cdb5b8480f8fee287058c93farmvixl
304de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre RamesEmissionCheckScope::EmissionCheckScope(MacroAssembler* masm,
305de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                       size_t size,
306de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                       AssertPolicy assert_policy) {
307de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  Open(masm, size, assert_policy);
308de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames}
309de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames
310de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames
311de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre RamesEmissionCheckScope::~EmissionCheckScope() { Close(); }
312de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames
313de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames
314de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre RamesEmissionCheckScope::EmissionCheckScope(MacroAssembler* masm,
315de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                       size_t size,
316de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                       AssertPolicy assert_policy,
317de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                                       PoolPolicy pool_policy) {
318de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  Open(masm, size, assert_policy, pool_policy);
319de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames}
320de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames
321de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames
322de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Ramesvoid EmissionCheckScope::Open(MacroAssembler* masm,
323de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                              size_t size,
324de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                              AssertPolicy assert_policy,
325de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames                              PoolPolicy pool_policy) {
326de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  masm_ = masm;
327de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  pool_policy_ = pool_policy;
3280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (masm_ == NULL) {
3290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    // Nothing to do.
3300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    // We may reach this point in a context of conditional code generation. See
3310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    // `MacroAssembler::MoveImmediateHelper()` for an example.
3320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
3330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
334de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  if (pool_policy_ == kCheckPools) {
335de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    // Do not use the more generic `EnsureEmitFor()` to avoid duplicating the
336de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    // work to check that enough space is available in the buffer. It is done
337de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    // below when opening `CodeBufferCheckScope`.
338de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    masm_->EnsureEmitPoolsFor(size);
339de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    masm_->BlockPools();
340de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  }
3419fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames  // The buffer should be checked *after* we emit the pools.
342de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  CodeBufferCheckScope::Open(masm_, size, kCheck, assert_policy);
343c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
344c68cb64496485710cdb5b8480f8fee287058c93farmvixl
345c68cb64496485710cdb5b8480f8fee287058c93farmvixl
346de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Ramesvoid EmissionCheckScope::Close() {
3470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (masm_ == NULL) {
3480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    // Nothing to do.
3490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
3500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
351de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  if (pool_policy_ == kCheckPools) {
352de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames    masm_->ReleasePools();
353de5bb0beb4a3342bb9f0d7e7fe16737a171517b0Alexandre Rames  }
354c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
355c68cb64496485710cdb5b8480f8fee287058c93farmvixl
356c68cb64496485710cdb5b8480f8fee287058c93farmvixl
357f2f550c0bfd0f15a4d1c51ff06ec898536f14205Alexandre RamesMacroAssembler::MacroAssembler(PositionIndependentCodeOption pic)
358f2f550c0bfd0f15a4d1c51ff06ec898536f14205Alexandre Rames    : Assembler(pic),
359b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames#ifdef VIXL_DEBUG
360b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      allow_macro_instructions_(true),
361b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames#endif
362703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames      generate_simulator_code_(VIXL_GENERATE_SIMULATOR_CODE),
363b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      sp_(sp),
364b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      tmp_list_(ip0, ip1),
365b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      fptmp_list_(d31),
366b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      literal_pool_(this),
367b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      veneer_pool_(this),
368b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      recommended_checkpoint_(Pool::kNoCheckpointRequired) {
369b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames  checkpoint_ = GetNextCheckPoint();
370fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames#ifndef VIXL_DEBUG
371fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames  USE(allow_macro_instructions_);
372fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames#endif
373b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames}
374b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames
375b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames
376c68cb64496485710cdb5b8480f8fee287058c93farmvixlMacroAssembler::MacroAssembler(size_t capacity,
377c68cb64496485710cdb5b8480f8fee287058c93farmvixl                               PositionIndependentCodeOption pic)
378c68cb64496485710cdb5b8480f8fee287058c93farmvixl    : Assembler(capacity, pic),
379330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
380c68cb64496485710cdb5b8480f8fee287058c93farmvixl      allow_macro_instructions_(true),
381c68cb64496485710cdb5b8480f8fee287058c93farmvixl#endif
382703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames      generate_simulator_code_(VIXL_GENERATE_SIMULATOR_CODE),
383c68cb64496485710cdb5b8480f8fee287058c93farmvixl      sp_(sp),
384c68cb64496485710cdb5b8480f8fee287058c93farmvixl      tmp_list_(ip0, ip1),
385c68cb64496485710cdb5b8480f8fee287058c93farmvixl      fptmp_list_(d31),
3865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      literal_pool_(this),
387db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      veneer_pool_(this),
388db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      recommended_checkpoint_(Pool::kNoCheckpointRequired) {
38988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
390c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
391c68cb64496485710cdb5b8480f8fee287058c93farmvixl
392c68cb64496485710cdb5b8480f8fee287058c93farmvixl
3930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlMacroAssembler::MacroAssembler(byte* buffer,
394c68cb64496485710cdb5b8480f8fee287058c93farmvixl                               size_t capacity,
395c68cb64496485710cdb5b8480f8fee287058c93farmvixl                               PositionIndependentCodeOption pic)
396c68cb64496485710cdb5b8480f8fee287058c93farmvixl    : Assembler(buffer, capacity, pic),
397330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
398c68cb64496485710cdb5b8480f8fee287058c93farmvixl      allow_macro_instructions_(true),
399c68cb64496485710cdb5b8480f8fee287058c93farmvixl#endif
400703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames      generate_simulator_code_(VIXL_GENERATE_SIMULATOR_CODE),
401c68cb64496485710cdb5b8480f8fee287058c93farmvixl      sp_(sp),
402c68cb64496485710cdb5b8480f8fee287058c93farmvixl      tmp_list_(ip0, ip1),
403c68cb64496485710cdb5b8480f8fee287058c93farmvixl      fptmp_list_(d31),
4045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      literal_pool_(this),
405db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      veneer_pool_(this),
406db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      recommended_checkpoint_(Pool::kNoCheckpointRequired) {
40788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
408c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
409c68cb64496485710cdb5b8480f8fee287058c93farmvixl
410c68cb64496485710cdb5b8480f8fee287058c93farmvixl
4110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlMacroAssembler::~MacroAssembler() {}
412c68cb64496485710cdb5b8480f8fee287058c93farmvixl
413c68cb64496485710cdb5b8480f8fee287058c93farmvixl
414c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid MacroAssembler::Reset() {
415c68cb64496485710cdb5b8480f8fee287058c93farmvixl  Assembler::Reset();
416c68cb64496485710cdb5b8480f8fee287058c93farmvixl
417c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!literal_pool_.IsBlocked());
418c68cb64496485710cdb5b8480f8fee287058c93farmvixl  literal_pool_.Reset();
4195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.Reset();
420c68cb64496485710cdb5b8480f8fee287058c93farmvixl
42188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
422c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
423c68cb64496485710cdb5b8480f8fee287058c93farmvixl
424c68cb64496485710cdb5b8480f8fee287058c93farmvixl
425c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid MacroAssembler::FinalizeCode() {
426c68cb64496485710cdb5b8480f8fee287058c93farmvixl  if (!literal_pool_.IsEmpty()) literal_pool_.Emit();
4275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(veneer_pool_.IsEmpty());
428c68cb64496485710cdb5b8480f8fee287058c93farmvixl
429c68cb64496485710cdb5b8480f8fee287058c93farmvixl  Assembler::FinalizeCode();
430c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
431c68cb64496485710cdb5b8480f8fee287058c93farmvixl
432c68cb64496485710cdb5b8480f8fee287058c93farmvixl
4335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::CheckEmitFor(size_t amount) {
4349fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames  CheckEmitPoolsFor(amount);
4355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  ptrdiff_t offset = amount;
4365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Ensure there's enough space for the emit, keep in mind the cursor will
4375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // have moved if a pool was emitted.
43888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((GetCursorOffset() + offset) > GetBufferEndOffset()) {
4395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    EnsureSpaceFor(amount);
4405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
4419fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames}
4429fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames
4435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
4449fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Ramesvoid MacroAssembler::CheckEmitPoolsFor(size_t amount) {
4459fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames  literal_pool_.CheckEmitFor(amount);
4469fbd11bbc6a56071f455df28e08854a848f46c3bAlexandre Rames  veneer_pool_.CheckEmitFor(amount);
44788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
4485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
4495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
4505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
451330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlint MacroAssembler::MoveImmediateHelper(MacroAssembler* masm,
4520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                        const Register& rd,
453330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl                                        uint64_t imm) {
454330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  bool emit_code = (masm != NULL);
45588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint32(imm) || IsInt32(imm) || rd.Is64Bits());
456330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The worst case for size is mov 64-bit immediate to sp:
457330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  * up to 4 instructions to materialise the constant
458330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  * 1 instruction to move to sp
459330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MacroEmissionCheckScope guard(masm);
460330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
461330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Immediates on Aarch64 can be produced using an initial value, and zero to
462330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // three move keep operations.
463330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //
464330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Initial values can be generated with:
465330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  1. 64-bit move zero (movz).
466330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  2. 32-bit move inverted (movn).
467330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  3. 64-bit move inverted.
468330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  4. 32-bit orr immediate.
469330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  5. 64-bit orr immediate.
470330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Move-keep may then be used to modify each of the 16-bit half words.
471330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //
472330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The code below supports all five initial value generators, and
473330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // applying move-keep operations to move-zero and move-inverted initial
474330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // values.
475330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
476330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Try to move the immediate in one instruction, and if that fails, switch to
477330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // using multiple instructions.
478330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (OneInstrMoveImmediateHelper(masm, rd, imm)) {
479330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return 1;
480330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else {
481330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    int instruction_count = 0;
48288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    unsigned reg_size = rd.GetSizeInBits();
483330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
484330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Generic immediate case. Imm will be represented by
485330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    //   [imm3, imm2, imm1, imm0], where each imm is 16 bits.
486330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // A move-zero or move-inverted is generated for the first non-zero or
487330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // non-0xffff immX, and a move-keep for subsequent non-zero immX.
488330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
489330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    uint64_t ignored_halfword = 0;
490330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    bool invert_move = false;
491330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // If the number of 0xffff halfwords is greater than the number of 0x0000
492330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // halfwords, it's more efficient to use move-inverted.
493330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (CountClearHalfWords(~imm, reg_size) >
494330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        CountClearHalfWords(imm, reg_size)) {
495330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      ignored_halfword = 0xffff;
496330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      invert_move = true;
497330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
498330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
499330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Mov instructions can't move values into the stack pointer, so set up a
500330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // temporary register, if needed.
501330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    UseScratchRegisterScope temps;
502330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    Register temp;
503330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
504330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      temps.Open(masm);
505330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      temp = rd.IsSP() ? temps.AcquireSameSizeAs(rd) : rd;
506330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
507330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
508330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Iterate through the halfwords. Use movn/movz for the first non-ignored
509330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // halfword, and movk for subsequent halfwords.
510330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    VIXL_ASSERT((reg_size % 16) == 0);
511330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    bool first_mov_done = false;
5120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    for (unsigned i = 0; i < (reg_size / 16); i++) {
513330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      uint64_t imm16 = (imm >> (16 * i)) & 0xffff;
514330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      if (imm16 != ignored_halfword) {
515330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        if (!first_mov_done) {
516330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          if (invert_move) {
517330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            if (emit_code) masm->movn(temp, ~imm16 & 0xffff, 16 * i);
518330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            instruction_count++;
519330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          } else {
520330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            if (emit_code) masm->movz(temp, imm16, 16 * i);
521330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            instruction_count++;
522330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          }
523330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          first_mov_done = true;
524330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        } else {
525330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          // Construct a wider constant.
526330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          if (emit_code) masm->movk(temp, imm16, 16 * i);
527330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          instruction_count++;
528330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        }
529330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      }
530330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
531330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
532330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    VIXL_ASSERT(first_mov_done);
533330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
534330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Move the temporary if the original destination register was the stack
535330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // pointer.
536330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (rd.IsSP()) {
537330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      if (emit_code) masm->mov(rd, temp);
538330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      instruction_count++;
539330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
540330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return instruction_count;
541330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
542330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
543330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
544330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
545330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlbool MacroAssembler::OneInstrMoveImmediateHelper(MacroAssembler* masm,
546330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl                                                 const Register& dst,
547330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl                                                 int64_t imm) {
548330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  bool emit_code = masm != NULL;
549330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  unsigned n, imm_s, imm_r;
55088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = dst.GetSizeInBits();
551330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
552330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (IsImmMovz(imm, reg_size) && !dst.IsSP()) {
553330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate can be represented in a move zero instruction. Movz can't write
554330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // to the stack pointer.
555330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
556330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      masm->movz(dst, imm);
557330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
558330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return true;
559330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else if (IsImmMovn(imm, reg_size) && !dst.IsSP()) {
560330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate can be represented in a move negative instruction. Movn can't
561330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // write to the stack pointer.
562330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
563330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      masm->movn(dst, dst.Is64Bits() ? ~imm : (~imm & kWRegMask));
564330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
565330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return true;
566330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) {
567330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate can be represented in a logical orr instruction.
568330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    VIXL_ASSERT(!dst.IsZero());
569330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
5700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->LogicalImmediate(dst,
5710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             AppropriateZeroRegFor(dst),
5720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             n,
5730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             imm_s,
5740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             imm_r,
5750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             ORR);
576330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
577330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return true;
578330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
579330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  return false;
580330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
581330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
582330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
583b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid MacroAssembler::B(Label* label, BranchType type, Register reg, int bit) {
584b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((reg.Is(NoReg) || (type >= kBranchTypeFirstUsingReg)) &&
585b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl              ((bit == -1) || (type >= kBranchTypeFirstUsingBit)));
586b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
587b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    B(static_cast<Condition>(type), label);
588b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
589b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    switch (type) {
5900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case always:
5910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        B(label);
5920f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case never:
5940f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_zero:
5960f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Cbz(reg, label);
5970f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5980f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_not_zero:
5990f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Cbnz(reg, label);
6000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
6010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_bit_clear:
6020f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Tbz(reg, bit, label);
6030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
6040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_bit_set:
6050f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Tbnz(reg, bit, label);
6060f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
607b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      default:
608b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl        VIXL_UNREACHABLE();
609b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    }
610b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
611b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
612b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
6135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::B(Label* label) {
6155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  SingleEmissionCheckScope guard(this);
6165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  b(label);
6175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::B(Label* label, Condition cond) {
6215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
6235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) {
6265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(&done, InvertCondition(cond));
6285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
63288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            CondBranchType);
6355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label, cond);
6375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Cbnz(const Register& rt, Label* label) {
6425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) {
6475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbz(rt, &done);
6495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
65388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            CompareBranchType);
6565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbnz(rt, label);
6585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Cbz(const Register& rt, Label* label) {
6635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) {
6685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbnz(rt, &done);
6705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
67488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            CompareBranchType);
6775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbz(rt, label);
6795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Tbnz(const Register& rt, unsigned bit_pos, Label* label) {
6845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, TestBranchType)) {
6895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbz(rt, bit_pos, &done);
6915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
69588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            TestBranchType);
6985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbnz(rt, bit_pos, label);
7005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
7015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
7025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Tbz(const Register& rt, unsigned bit_pos, Label* label) {
7055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
7065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
7075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
7085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, TestBranchType)) {
7105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
7115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbnz(rt, bit_pos, &done);
7125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
7135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
7145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
7155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
71688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
7175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
7185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            TestBranchType);
7195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
7205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbz(rt, bit_pos, label);
7215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
7225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
7235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Bind(Label* label) {
7265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
7275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.DeleteUnresolvedBranchInfoForLabel(label);
7285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  bind(label);
7295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
7305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// Bind a label to a specified offset from the start of the buffer.
7335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::BindToOffset(Label* label, ptrdiff_t offset) {
7345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
7355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.DeleteUnresolvedBranchInfoForLabel(label);
7365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Assembler::BindToOffset(label, offset);
7375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
7385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
7395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
740ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::And(const Register& rd,
741ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
742f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
743b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
744f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, AND);
745f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
746f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
747f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
748f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Ands(const Register& rd,
749f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
750f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
751b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
752f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, ANDS);
753ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
754ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
755ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
7560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Tst(const Register& rn, const Operand& operand) {
757b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
758f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Ands(AppropriateZeroRegFor(rn), rn, operand);
759ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
760ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
761ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
762ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Bic(const Register& rd,
763ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
764f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
765b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
766f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, BIC);
767f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
768f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
769f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
770f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Bics(const Register& rd,
771f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
772f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
773b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
774f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, BICS);
775ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
776ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
777ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
778ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Orr(const Register& rd,
779ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
780ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
781b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
782ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, ORR);
783ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
784ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
785ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
786ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Orn(const Register& rd,
787ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
788ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
789b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
790ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, ORN);
791ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
792ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
793ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
794ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Eor(const Register& rd,
795ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
796ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
797b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
798ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, EOR);
799ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
800ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
801ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
802ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Eon(const Register& rd,
803ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
804ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
805b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
806ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, EON);
807ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
808ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
809ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
810ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::LogicalMacro(const Register& rd,
811ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  const Register& rn,
812ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  const Operand& operand,
813ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  LogicalOp op) {
814c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is logical immediate to sp:
815c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
816c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to do the operation
817c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to move to sp
818c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
819b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
820b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
821ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
82288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t immediate = operand.GetImmediate();
82388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    unsigned reg_size = rd.GetSizeInBits();
824ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
825ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the operation is NOT, invert the operation and immediate.
826ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if ((op & NOT) == NOT) {
827ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      op = static_cast<LogicalOp>(op & ~NOT);
828ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      immediate = ~immediate;
829ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
830ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
8314a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Ignore the top 32 bits of an immediate if we're moving to a W register.
8324a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (rd.Is32Bits()) {
8334a102baf640077d6794c0b33bb976f94b86c532barmvixl      // Check that the top 32 bits are consistent.
8344a102baf640077d6794c0b33bb976f94b86c532barmvixl      VIXL_ASSERT(((immediate >> kWRegSize) == 0) ||
8354a102baf640077d6794c0b33bb976f94b86c532barmvixl                  ((immediate >> kWRegSize) == -1));
8364a102baf640077d6794c0b33bb976f94b86c532barmvixl      immediate &= kWRegMask;
8374a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
8384a102baf640077d6794c0b33bb976f94b86c532barmvixl
83988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rd.Is64Bits() || IsUint32(immediate));
8404a102baf640077d6794c0b33bb976f94b86c532barmvixl
841ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Special cases for all set or all clear immediates.
842ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (immediate == 0) {
843ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (op) {
844ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case AND:
845ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, 0);
846ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
8476e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        case ORR:
8486e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl          VIXL_FALLTHROUGH();
849ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case EOR:
850ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, rn);
851ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
8526e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        case ANDS:
8536e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl          VIXL_FALLTHROUGH();
854ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case BICS:
855ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
856ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        default:
857b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl          VIXL_UNREACHABLE();
858ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
859b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else if ((rd.Is64Bits() && (immediate == -1)) ||
860b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl               (rd.Is32Bits() && (immediate == 0xffffffff))) {
861ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (op) {
862ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case AND:
863ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, rn);
864ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
865ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case ORR:
866ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, immediate);
867ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
868ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case EOR:
869ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mvn(rd, rn);
870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
8716e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        case ANDS:
8726e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl          VIXL_FALLTHROUGH();
873ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case BICS:
874ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
875ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        default:
876b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl          VIXL_UNREACHABLE();
877ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
878ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
879ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
880ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    unsigned n, imm_s, imm_r;
881ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
882ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Immediate can be encoded in the instruction.
883ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
884ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
885ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Immediate can't be encoded: synthesize using move immediate.
886b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      Register temp = temps.AcquireSameSizeAs(rn);
8874a102baf640077d6794c0b33bb976f94b86c532barmvixl      Operand imm_operand = MoveImmediateForShiftedOp(temp, immediate);
8884a102baf640077d6794c0b33bb976f94b86c532barmvixl
889ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd.Is(sp)) {
890ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // If rd is the stack pointer we cannot use it as the destination
891ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // register so we use the temp register as an intermediate again.
8924a102baf640077d6794c0b33bb976f94b86c532barmvixl        Logical(temp, rn, imm_operand, op);
893ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        Mov(sp, temp);
894ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
8954a102baf640077d6794c0b33bb976f94b86c532barmvixl        Logical(rd, rn, imm_operand, op);
896ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
897ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
898ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
89988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() <= rd.GetSizeInBits());
900ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub extended supports shift <= 4. We want to support exactly the
901ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // same modes here.
90288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShiftAmount() <= 4);
90388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
90488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        operand.GetRegister().Is64Bits() ||
90588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        ((operand.GetExtend() != UXTX) && (operand.GetExtend() != SXTX)));
906b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
90788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
908b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
9090f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
91088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
91188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
91288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
913ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Logical(rd, rn, Operand(temp), op);
914ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
915ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The operand can be encoded in the instruction.
916b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT(operand.IsShiftedRegister());
917ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Logical(rd, rn, operand, op);
918ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
919ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
920ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
921ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
922f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Mov(const Register& rd,
923f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand,
924f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         DiscardMoveMode discard_mode) {
925b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
926c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is mov immediate with up to 4 instructions.
927c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
928c68cb64496485710cdb5b8480f8fee287058c93farmvixl
929ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
930ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Call the macro assembler for generic immediates.
93188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(rd, operand.GetImmediate());
93288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } else if (operand.IsShiftedRegister() && (operand.GetShiftAmount() != 0)) {
933ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit a shift instruction if moving a shifted register. This operation
934ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // could also be achieved using an orr instruction (like orn used by Mvn),
935ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // but using a shift instruction makes the disassembly clearer.
93688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    EmitShift(rd,
93788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetRegister(),
93888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShift(),
93988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShiftAmount());
940ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
941ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit an extend instruction if moving an extended register. This handles
942ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // extend with post-shift operations, too.
9430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(rd,
94488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
94588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
94688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
947ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
948ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Otherwise, emit a register move only if the registers are distinct, or
949f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // if they are not X registers.
950f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    //
951f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // Note that mov(w0, w0) is not a no-op because it clears the top word of
952f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // x0. A flag is provided (kDiscardForSameWReg) if a move between the same W
953f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // registers is not required to clear the top word of the X register. In
954f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // this case, the instruction is discarded.
955f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    //
956ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the sp is an operand, add #0 is emitted, otherwise, orr #0.
95788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (!rd.Is(operand.GetRegister()) ||
9580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        (rd.Is32Bits() && (discard_mode == kDontDiscardForSameWReg))) {
95988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      mov(rd, operand.GetRegister());
960ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
961ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
962ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
963ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
964ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
9655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi16bitHelper(const VRegister& vd, uint64_t imm) {
96688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint16(imm));
9675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  int byte1 = (imm & 0xff);
9685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  int byte2 = ((imm >> 8) & 0xff);
9695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (byte1 == byte2) {
9705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd.Is64Bits() ? vd.V8B() : vd.V16B(), byte1);
9715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte1 == 0) {
9725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, byte2, LSL, 8);
9735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte2 == 0) {
9745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, byte1);
9755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte1 == 0xff) {
9765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~byte2 & 0xff, LSL, 8);
9775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte2 == 0xff) {
9785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~byte1 & 0xff);
9795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
9805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
9815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireW();
9825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movz(temp, imm);
9835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    dup(vd, temp);
9845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
9865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi32bitHelper(const VRegister& vd, uint64_t imm) {
98988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint32(imm));
9905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  uint8_t bytes[sizeof(imm)];
9925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  memcpy(bytes, &imm, sizeof(imm));
9935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // All bytes are either 0x00 or 0xff.
9955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
9965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bool all0orff = true;
9975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (int i = 0; i < 4; ++i) {
9985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if ((bytes[i] != 0) && (bytes[i] != 0xff)) {
9995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        all0orff = false;
10005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        break;
10015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
10025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (all0orff == true) {
10055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd.Is64Bits() ? vd.V1D() : vd.V2D(), ((imm << 32) | imm));
10065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Of the 4 bytes, only one byte is non-zero.
10115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (int i = 0; i < 4; i++) {
10125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if ((imm & (0xff << (i * 8))) == imm) {
10135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd, bytes[i], LSL, i * 8);
10145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Of the 4 bytes, only one byte is not 0xff.
10195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (int i = 0; i < 4; i++) {
10205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    uint32_t mask = ~(0xff << (i * 8));
10215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if ((imm & mask) == mask) {
10225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      mvni(vd, ~bytes[i] & 0xff, LSL, i * 8);
10235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0x00MMFFFF.
10285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xff00ffff) == 0x0000ffff) {
10295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, bytes[2], MSL, 16);
10305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0x0000MMFF.
10345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xffff00ff) == 0x000000ff) {
10355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, bytes[1], MSL, 8);
10365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0xFFMM0000.
10405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xff00ffff) == 0xff000000) {
10415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~bytes[2] & 0xff, MSL, 16);
10425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0xFFFFMM00.
10455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xffff00ff) == 0xffff0000) {
10465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~bytes[1] & 0xff, MSL, 8);
10475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Top and bottom 16-bits are equal.
10515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (((imm >> 16) & 0xffff) == (imm & 0xffff)) {
10525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi16bitHelper(vd.Is64Bits() ? vd.V4H() : vd.V8H(), imm & 0xffff);
10535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Default case.
10575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
10595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireW();
10605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Mov(temp, imm);
10615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    dup(vd, temp);
10625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
10645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi64bitHelper(const VRegister& vd, uint64_t imm) {
10675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // All bytes are either 0x00 or 0xff.
10685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bool all0orff = true;
10705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (int i = 0; i < 8; ++i) {
10715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      int byteval = (imm >> (i * 8)) & 0xff;
10725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (byteval != 0 && byteval != 0xff) {
10735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        all0orff = false;
10745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        break;
10755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
10765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (all0orff == true) {
10785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd, imm);
10795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Top and bottom 32-bits are equal.
10845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (((imm >> 32) & 0xffffffff) == (imm & 0xffffffff)) {
10855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi32bitHelper(vd.Is64Bits() ? vd.V2S() : vd.V4S(), imm & 0xffffffff);
10865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Default case.
10905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
10925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireX();
10935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Mov(temp, imm);
10945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.Is1D()) {
10955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      mov(vd.D(), 0, temp);
10965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
10975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      dup(vd.V2D(), temp);
10985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
11005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
11015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi(const VRegister& vd,
11045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          uint64_t imm,
11055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          Shift shift,
11065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          int shift_amount) {
11075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
11085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  MacroEmissionCheckScope guard(this);
11095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (shift_amount != 0 || shift != LSL) {
11105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, imm, shift, shift_amount);
11115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is8B() || vd.Is16B()) {
11125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 8-bit immediate.
111388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsUint8(imm));
11145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, imm);
11155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is4H() || vd.Is8H()) {
11165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 16-bit immediate.
11175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi16bitHelper(vd, imm);
11185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is2S() || vd.Is4S()) {
11195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 32-bit immediate.
11205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi32bitHelper(vd, imm);
11215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
11225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 64-bit immediate.
11235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi64bitHelper(vd, imm);
11245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
11255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
11265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Movi(const VRegister& vd, uint64_t hi, uint64_t lo) {
11295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // TODO: Move 128-bit values in a more efficient way.
11305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is128Bits());
11315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UseScratchRegisterScope temps(this);
11325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Movi(vd.V2D(), lo);
11335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Register temp = temps.AcquireX();
11345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Mov(temp, hi);
11355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Ins(vd.V2D(), 1, temp);
11365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
11375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
1140b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1141c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is mvn immediate with up to 4 instructions.
1142c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1143c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
1145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Call the macro assembler for generic immediates.
114688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mvn(rd, operand.GetImmediate());
1147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
1148b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
114988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1150b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit two instructions for the extend case. This differs from Mov, as
1152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the extend and invert can't be achieved in one instruction.
1153b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rd);
11540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
115588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
115688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
115788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
1158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, Operand(temp));
1159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Otherwise, register and shifted register cases can be handled by the
1161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // assembler directly, using orn.
1162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, operand);
1163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mov(const Register& rd, uint64_t imm) {
1168b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1169330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MoveImmediateHelper(this, rd, imm);
1170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmp(const Register& rn,
1174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
1175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
1176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
1177b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
117888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0)) {
117988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ConditionalCompareMacro(rn, -operand.GetImmediate(), nzcv, cond, CCMN);
1180f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
1181f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
1182f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmn(const Register& rn,
1187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
1188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
1189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
1190b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
119188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0)) {
119288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ConditionalCompareMacro(rn, -operand.GetImmediate(), nzcv, cond, CCMP);
1193f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
1194f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
1195f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1197ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1198ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1199ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::ConditionalCompareMacro(const Register& rn,
1200ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             const Operand& operand,
1201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             StatusFlags nzcv,
1202ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             Condition cond,
1203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             ConditionalCompareOp op) {
1204b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
1205c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is ccmp immediate:
1206c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1207c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ccmp
1208c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1209c68cb64496485710cdb5b8480f8fee287058c93farmvixl
121088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((operand.IsShiftedRegister() && (operand.GetShiftAmount() == 0)) ||
121188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsImmediate() &&
121288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois       IsImmConditionalCompare(operand.GetImmediate()))) {
1213ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The immediate can be encoded in the instruction, or the operand is an
1214ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // unshifted register: call the assembler.
1215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    ConditionalCompare(rn, operand, nzcv, cond, op);
1216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1217b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1218ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The operand isn't directly supported by the instruction: perform the
1219ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // operation on a temporary register.
1220b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
1221f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Mov(temp, operand);
1222f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompare(rn, temp, nzcv, cond, op);
1223f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1224f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1225f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1226f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
12270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::CselHelper(MacroAssembler* masm,
12280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                const Register& rd,
12290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Operand left,
12300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Operand right,
12310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Condition cond,
12320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                bool* should_synthesise_left,
12330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                bool* should_synthesise_right) {
12340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
12350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(!emit_code || masm->allow_macro_instructions_);
1237b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
12380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(!rd.IsZero() && !rd.IsSP());
123988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(left.IsImmediate() || !left.GetRegister().IsSP());
124088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(right.IsImmediate() || !right.GetRegister().IsSP());
12410f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_left != NULL) *should_synthesise_left = false;
12430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_right != NULL) *should_synthesise_right = false;
12440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // The worst case for size occurs when the inputs are two non encodable
12460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // constants:
12470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  //  * up to 4 instructions to materialise the left constant
12480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  //  * up to 4 instructions to materialise the right constant
1249c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for csel
12500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  EmissionCheckScope guard(masm, 9 * kInstructionSize);
12510f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  UseScratchRegisterScope temps;
12520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (masm != NULL) {
12530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    temps.Open(masm);
12540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12550f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Try to handle cases where both inputs are immediates.
12570f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool left_is_immediate = left.IsImmediate() || left.IsZero();
12580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool right_is_immediate = right.IsImmediate() || right.IsZero();
12590f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left_is_immediate && right_is_immediate &&
12600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      CselSubHelperTwoImmediates(masm,
12610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 rd,
12620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 left.GetEquivalentImmediate(),
12630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 right.GetEquivalentImmediate(),
12640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 cond,
12650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 should_synthesise_left,
12660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 should_synthesise_right)) {
12670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
12680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1269c68cb64496485710cdb5b8480f8fee287058c93farmvixl
12700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Handle cases where one of the two inputs is -1, 0, or 1.
12710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool left_is_small_immediate =
12720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left_is_immediate && ((-1 <= left.GetEquivalentImmediate()) &&
12730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                            (left.GetEquivalentImmediate() <= 1));
12740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool right_is_small_immediate =
12750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      right_is_immediate && ((-1 <= right.GetEquivalentImmediate()) &&
12760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             (right.GetEquivalentImmediate() <= 1));
12770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (right_is_small_immediate || left_is_small_immediate) {
12780f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    bool swapped_inputs = false;
12790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (!right_is_small_immediate) {
12800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      std::swap(left, right);
12810f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      cond = InvertCondition(cond);
12820f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      swapped_inputs = true;
12830f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12840f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    CselSubHelperRightSmallImmediate(masm,
12850f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     &temps,
12860f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     rd,
12870f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     left,
12880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     right,
12890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     cond,
12900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     swapped_inputs ? should_synthesise_right
12910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                    : should_synthesise_left);
12920f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
12930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12940f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Otherwise both inputs need to be available in registers. Synthesise them
12960f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // if necessary and emit the `csel`.
12970f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (!left.IsPlainRegister()) {
12980f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
12990f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Register temp = temps.AcquireSameSizeAs(rd);
13000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(temp, left);
13010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left = temp;
13020f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_left != NULL) *should_synthesise_left = true;
13040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13050f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (!right.IsPlainRegister()) {
13060f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
13070f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Register temp = temps.AcquireSameSizeAs(rd);
13080f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(temp, right);
13090f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      right = temp;
13100f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_right != NULL) *should_synthesise_right = true;
13120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (emit_code) {
13140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(left.IsPlainRegister() && right.IsPlainRegister());
131588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (left.GetRegister().Is(right.GetRegister())) {
131688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      masm->Mov(rd, left.GetRegister());
13170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    } else {
131888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      masm->csel(rd, left.GetRegister(), right.GetRegister(), cond);
13190f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13200f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13210f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13220f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13230f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlbool MacroAssembler::CselSubHelperTwoImmediates(MacroAssembler* masm,
13250f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                const Register& rd,
13260f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                int64_t left,
13270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                int64_t right,
13280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                Condition cond,
13290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                bool* should_synthesise_left,
13300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                bool* should_synthesise_right) {
13310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_left != NULL) *should_synthesise_left = false;
13330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_right != NULL) *should_synthesise_right = false;
13340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left == right) {
13360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) masm->Mov(rd, left);
13370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else if (left == -right) {
13390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_right != NULL) *should_synthesise_right = true;
13400f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
13410f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(rd, right);
13420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Cneg(rd, rd, cond);
13430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (CselSubHelperTwoOrderedImmediates(masm, rd, left, right, cond)) {
13480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else {
13500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    std::swap(left, right);
13510f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (CselSubHelperTwoOrderedImmediates(masm,
13520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          rd,
13530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          left,
13540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          right,
13550f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          InvertCondition(cond))) {
13560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      return true;
13570f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13590f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // TODO: Handle more situations. For example handle `csel rd, #5, #6, cond`
13610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // with `cinc`.
13620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  return false;
13630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlbool MacroAssembler::CselSubHelperTwoOrderedImmediates(MacroAssembler* masm,
13670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       const Register& rd,
13680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       int64_t left,
13690f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       int64_t right,
13700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       Condition cond) {
13710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
1373dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames  if ((left == 1) && (right == 0)) {
13740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) masm->cset(rd, cond);
13750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
1376dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames  } else if ((left == -1) && (right == 0)) {
1377dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames    if (emit_code) masm->csetm(rd, cond);
13780f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  return false;
13810f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13820f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13830f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13840f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::CselSubHelperRightSmallImmediate(
13850f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    MacroAssembler* masm,
13860f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    UseScratchRegisterScope* temps,
13870f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Register& rd,
13880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Operand& left,
13890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Operand& right,
13900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    Condition cond,
13910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    bool* should_synthesise_left) {
13920f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT((right.IsImmediate() || right.IsZero()) &&
13940f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl              (-1 <= right.GetEquivalentImmediate()) &&
13950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl              (right.GetEquivalentImmediate() <= 1));
13960f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  Register left_register;
13970f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13980f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left.IsPlainRegister()) {
139988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    left_register = left.GetRegister();
14000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else {
14010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
14020f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left_register = temps->AcquireSameSizeAs(rd);
14030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(left_register, left);
14040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
14050f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_left != NULL) *should_synthesise_left = true;
14060f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
14070f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (emit_code) {
14080f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    int64_t imm = right.GetEquivalentImmediate();
14090f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    Register zr = AppropriateZeroRegFor(rd);
1410f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if (imm == 0) {
14110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csel(rd, left_register, zr, cond);
1412f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    } else if (imm == 1) {
14130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csinc(rd, left_register, zr, cond);
1414ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
14150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      VIXL_ASSERT(imm == -1);
14160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csinv(rd, left_register, zr, cond);
1417ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1418ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1419ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1420ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1421ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1422ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Add(const Register& rd,
1423ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
14246e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         const Operand& operand,
14256e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         FlagsUpdate S) {
1426b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
142788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0) &&
142888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      IsImmAddSub(-operand.GetImmediate())) {
142988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    AddSubMacro(rd, rn, -operand.GetImmediate(), S, SUB);
1430ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
14316e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    AddSubMacro(rd, rn, operand, S, ADD);
1432f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1433f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1434f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1435f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1436f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adds(const Register& rd,
1437f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1438f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
14396e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Add(rd, rn, operand, SetFlags);
1440ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1441ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1442ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1443ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sub(const Register& rd,
1444ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
14456e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         const Operand& operand,
14466e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         FlagsUpdate S) {
1447b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
144888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0) &&
144988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      IsImmAddSub(-operand.GetImmediate())) {
145088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    AddSubMacro(rd, rn, -operand.GetImmediate(), S, ADD);
1451f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
14526e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    AddSubMacro(rd, rn, operand, S, SUB);
1453f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1454f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1455f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1456f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1457f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Subs(const Register& rd,
1458f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1459f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
14606e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Sub(rd, rn, operand, SetFlags);
1461ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1462ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1463ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1464ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
1465b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1466f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Adds(AppropriateZeroRegFor(rn), rn, operand);
1467ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1468ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1469ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1470ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
1471b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1472f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(AppropriateZeroRegFor(rn), rn, operand);
1473ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1474ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1475ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
14760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Fcmp(const FPRegister& fn,
14770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          double value,
14786e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                          FPTrapFlags trap) {
1479b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1480c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is:
1481c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 to materialise the constant, using literal pool if necessary
14826e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  //  * 1 instruction for fcmp{e}
1483c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1484b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (value != 0.0) {
1485b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1486b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    FPRegister tmp = temps.AcquireSameSizeAs(fn);
1487b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Fmov(tmp, value);
14886e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    FPCompareMacro(fn, tmp, trap);
1489b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
14906e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    FPCompareMacro(fn, value, trap);
1491b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1492b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1493b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1494b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
14956e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::Fcmpe(const FPRegister& fn, double value) {
14966e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Fcmp(fn, value, EnableTrap);
14976e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
14986e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
14996e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
15005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Fmov(VRegister vd, double imm) {
1501b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1502c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Floating point immediates are loaded through the literal pool.
1503c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1504c68cb64496485710cdb5b8480f8fee287058c93farmvixl
15055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (vd.Is1S() || vd.Is2S() || vd.Is4S()) {
15065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Fmov(vd, static_cast<float>(imm));
1507b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    return;
1508b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1509b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is1D() || vd.Is2D());
1511b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (IsImmFP64(imm)) {
15125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    fmov(vd, imm);
1513b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
151488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint64_t rawbits = DoubleToRawbits(imm);
15155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.IsScalar()) {
15165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (rawbits == 0) {
15175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        fmov(vd, xzr);
15185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      } else {
1519db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl        ldr(vd,
1520db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl            new Literal<double>(imm,
1521db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                                &literal_pool_,
1522db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                                RawLiteral::kDeletedOnPlacementByPool));
15235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
15245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
15255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // TODO: consider NEON support for load literal.
15265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Movi(vd, rawbits);
15275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
1528b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1529b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1530b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1531b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Fmov(VRegister vd, float imm) {
1533b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1534c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Floating point immediates are loaded through the literal pool.
1535c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1536c68cb64496485710cdb5b8480f8fee287058c93farmvixl
15375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (vd.Is1D() || vd.Is2D()) {
15385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Fmov(vd, static_cast<double>(imm));
1539b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    return;
1540b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1541b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is1S() || vd.Is2S() || vd.Is4S());
1543b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (IsImmFP32(imm)) {
15445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    fmov(vd, imm);
1545b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
154688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint32_t rawbits = FloatToRawbits(imm);
15475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.IsScalar()) {
15485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (rawbits == 0) {
15495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        fmov(vd, wzr);
15505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      } else {
1551db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl        ldr(vd,
1552db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl            new Literal<float>(imm,
1553db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                               &literal_pool_,
1554db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                               RawLiteral::kDeletedOnPlacementByPool));
15555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
15565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
15575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // TODO: consider NEON support for load literal.
15585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Movi(vd, rawbits);
15595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
1560b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1561b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1562b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1563b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Neg(const Register& rd, const Operand& operand) {
1565b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1566ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
156788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(rd, -operand.GetImmediate());
1568ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1569f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Sub(rd, AppropriateZeroRegFor(rd), operand);
1570ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1571ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1572ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1573ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
15740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Negs(const Register& rd, const Operand& operand) {
1575b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1576f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(rd, AppropriateZeroRegFor(rd), operand);
1577f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1578f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1579f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
15804a102baf640077d6794c0b33bb976f94b86c532barmvixlbool MacroAssembler::TryOneInstrMoveImmediate(const Register& dst,
15814a102baf640077d6794c0b33bb976f94b86c532barmvixl                                              int64_t imm) {
1582330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  return OneInstrMoveImmediateHelper(this, dst, imm);
15834a102baf640077d6794c0b33bb976f94b86c532barmvixl}
15844a102baf640077d6794c0b33bb976f94b86c532barmvixl
15854a102baf640077d6794c0b33bb976f94b86c532barmvixl
15864a102baf640077d6794c0b33bb976f94b86c532barmvixlOperand MacroAssembler::MoveImmediateForShiftedOp(const Register& dst,
15874a102baf640077d6794c0b33bb976f94b86c532barmvixl                                                  int64_t imm) {
158888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = dst.GetSizeInBits();
15894a102baf640077d6794c0b33bb976f94b86c532barmvixl
15904a102baf640077d6794c0b33bb976f94b86c532barmvixl  // Encode the immediate in a single move instruction, if possible.
15914a102baf640077d6794c0b33bb976f94b86c532barmvixl  if (TryOneInstrMoveImmediate(dst, imm)) {
15924a102baf640077d6794c0b33bb976f94b86c532barmvixl    // The move was successful; nothing to do here.
15934a102baf640077d6794c0b33bb976f94b86c532barmvixl  } else {
15944a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Pre-shift the immediate to the least-significant bits of the register.
15954a102baf640077d6794c0b33bb976f94b86c532barmvixl    int shift_low = CountTrailingZeros(imm, reg_size);
15964a102baf640077d6794c0b33bb976f94b86c532barmvixl    int64_t imm_low = imm >> shift_low;
15974a102baf640077d6794c0b33bb976f94b86c532barmvixl
15984a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Pre-shift the immediate to the most-significant bits of the register,
15994a102baf640077d6794c0b33bb976f94b86c532barmvixl    // inserting set bits in the least-significant bits.
16004a102baf640077d6794c0b33bb976f94b86c532barmvixl    int shift_high = CountLeadingZeros(imm, reg_size);
16015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    int64_t imm_high = (imm << shift_high) | ((INT64_C(1) << shift_high) - 1);
16024a102baf640077d6794c0b33bb976f94b86c532barmvixl
16034a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (TryOneInstrMoveImmediate(dst, imm_low)) {
16044a102baf640077d6794c0b33bb976f94b86c532barmvixl      // The new immediate has been moved into the destination's low bits:
16054a102baf640077d6794c0b33bb976f94b86c532barmvixl      // return a new leftward-shifting operand.
16064a102baf640077d6794c0b33bb976f94b86c532barmvixl      return Operand(dst, LSL, shift_low);
16074a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else if (TryOneInstrMoveImmediate(dst, imm_high)) {
16084a102baf640077d6794c0b33bb976f94b86c532barmvixl      // The new immediate has been moved into the destination's high bits:
16094a102baf640077d6794c0b33bb976f94b86c532barmvixl      // return a new rightward-shifting operand.
16104a102baf640077d6794c0b33bb976f94b86c532barmvixl      return Operand(dst, LSR, shift_high);
16114a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else {
16124a102baf640077d6794c0b33bb976f94b86c532barmvixl      Mov(dst, imm);
16134a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
16144a102baf640077d6794c0b33bb976f94b86c532barmvixl  }
16154a102baf640077d6794c0b33bb976f94b86c532barmvixl  return Operand(dst);
16164a102baf640077d6794c0b33bb976f94b86c532barmvixl}
16174a102baf640077d6794c0b33bb976f94b86c532barmvixl
16184a102baf640077d6794c0b33bb976f94b86c532barmvixl
16194e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Ramesvoid MacroAssembler::Move(const GenericOperand& dst,
16204e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames                          const GenericOperand& src) {
16214e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.Equals(src)) {
16224e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    return;
16234e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16244e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16254e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  VIXL_ASSERT(dst.IsValid() && src.IsValid());
16264e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16274e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  // The sizes of the operands must match exactly.
16284e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  VIXL_ASSERT(dst.GetSizeInBits() == src.GetSizeInBits());
16294e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  size_t operand_size = dst.GetSizeInBits();
16304e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  VIXL_ASSERT(operand_size <= kXRegSize);
16314e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16324e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.IsCPURegister() && src.IsCPURegister()) {
16334e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    CPURegister dst_reg = dst.GetCPURegister();
16344e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    CPURegister src_reg = src.GetCPURegister();
16354e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    if (dst_reg.IsRegister() && src_reg.IsRegister()) {
16364e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      Mov(Register(dst_reg), Register(src_reg));
16374e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    } else if (dst_reg.IsVRegister() && src_reg.IsVRegister()) {
16384e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      Fmov(VRegister(dst_reg), VRegister(src_reg));
16394e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    } else {
16404e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      if (dst_reg.IsRegister()) {
16414e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames        Fmov(Register(dst_reg), VRegister(src_reg));
16424e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      } else {
16434e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames        Fmov(VRegister(dst_reg), Register(src_reg));
16444e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      }
16454e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    }
16464e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    return;
16474e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16484e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16494e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.IsMemOperand() && src.IsMemOperand()) {
16504e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    UseScratchRegisterScope temps(this);
16514e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    CPURegister temp = temps.AcquireCPURegisterOfSize(operand_size);
16524e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Ldr(temp, src.GetMemOperand());
16534e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Str(temp, dst.GetMemOperand());
16544e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    return;
16554e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16564e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16574e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.IsCPURegister()) {
16584e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Ldr(dst.GetCPURegister(), src.GetMemOperand());
16594e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  } else {
16604e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Str(src.GetCPURegister(), dst.GetMemOperand());
16614e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16624e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames}
16634e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16644e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::ComputeAddress(const Register& dst,
16665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                    const MemOperand& mem_op) {
16675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // We cannot handle pre-indexing or post-indexing.
166888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(mem_op.GetAddrMode() == Offset);
166988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register base = mem_op.GetBaseRegister();
16705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (mem_op.IsImmediateOffset()) {
167188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(dst, base, mem_op.GetOffset());
16725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
16735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(mem_op.IsRegisterOffset());
167488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register reg_offset = mem_op.GetRegisterOffset();
167588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Shift shift = mem_op.GetShift();
167688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Extend extend = mem_op.GetExtend();
16775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (shift == NO_SHIFT) {
16785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(extend != NO_EXTEND);
167988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Add(dst, base, Operand(reg_offset, extend, mem_op.GetShiftAmount()));
16805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
16815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(extend == NO_EXTEND);
168288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Add(dst, base, Operand(reg_offset, shift, mem_op.GetShiftAmount()));
16835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
16845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
16855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
16865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
16875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1688ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubMacro(const Register& rd,
1689ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Register& rn,
1690ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Operand& operand,
1691ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 FlagsUpdate S,
1692ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 AddSubOp op) {
1693c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is add/sub immediate:
1694c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1695c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for add/sub
1696c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1697c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1698f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsZero() && rd.Is(rn) && rd.Is64Bits() && rn.Is64Bits() &&
1699f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      (S == LeaveFlags)) {
1700f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // The instruction would be a nop. Avoid generating useless code.
1701f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
1702f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1703f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
170488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((operand.IsImmediate() && !IsImmAddSub(operand.GetImmediate())) ||
17050f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      (rn.IsZero() && !operand.IsShiftedRegister()) ||
170688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsShiftedRegister() && (operand.GetShift() == ROR))) {
1707b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1708b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
17094a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (operand.IsImmediate()) {
17104a102baf640077d6794c0b33bb976f94b86c532barmvixl      Operand imm_operand =
171188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          MoveImmediateForShiftedOp(temp, operand.GetImmediate());
17124a102baf640077d6794c0b33bb976f94b86c532barmvixl      AddSub(rd, rn, imm_operand, S, op);
17134a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else {
17144a102baf640077d6794c0b33bb976f94b86c532barmvixl      Mov(temp, operand);
17154a102baf640077d6794c0b33bb976f94b86c532barmvixl      AddSub(rd, rn, temp, S, op);
17164a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
1717ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1718ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSub(rd, rn, operand, S, op);
1719ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1720ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1721ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1722ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1723ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Adc(const Register& rd,
1724ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
1725f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
1726b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1727f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, ADC);
1728f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1729f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1730f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1731f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adcs(const Register& rd,
1732f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1733f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
1734b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1735f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, ADC);
1736ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1737ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1738ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1739ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sbc(const Register& rd,
1740ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
1741f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
1742b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1743f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, SBC);
1744f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1745f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1746f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1747f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Sbcs(const Register& rd,
1748f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1749f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
1750b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1751f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, SBC);
1752ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1753ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1754ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
17550f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Ngc(const Register& rd, const Operand& operand) {
1756b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1757ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register zr = AppropriateZeroRegFor(rd);
1758f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbc(rd, zr, operand);
1759f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1760f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1761f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
17620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Ngcs(const Register& rd, const Operand& operand) {
1763b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1764f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Register zr = AppropriateZeroRegFor(rd);
1765f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbcs(rd, zr, operand);
1766ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1767ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1768ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1769ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubWithCarryMacro(const Register& rd,
1770ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Register& rn,
1771ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Operand& operand,
1772ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          FlagsUpdate S,
1773ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          AddSubWithCarryOp op) {
177488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(rd.GetSizeInBits() == rn.GetSizeInBits());
1775c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is addc/subc immediate:
1776c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1777c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for add/sub
1778c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1779b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
1780ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1781ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate() ||
178288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsShiftedRegister() && (operand.GetShift() == ROR))) {
1783ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (immediate or ROR shifted register.)
1784b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
1785ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mov(temp, operand);
1786ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
178788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } else if (operand.IsShiftedRegister() && (operand.GetShiftAmount() != 0)) {
1788ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (shifted register).
178988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() == rd.GetSizeInBits());
179088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShift() != ROR);
179188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
179288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        IsUintN(rd.GetSizeInBits() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
179388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                operand.GetShiftAmount()));
179488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1795b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
179688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    EmitShift(temp,
179788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetRegister(),
179888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShift(),
179988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShiftAmount());
1800ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
1801ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
1802ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (extended register).
180388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() <= rd.GetSizeInBits());
1804ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub extended supports a shift <= 4. We want to support exactly the
1805ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // same modes.
180688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShiftAmount() <= 4);
180788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
180888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        operand.GetRegister().Is64Bits() ||
180988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        ((operand.GetExtend() != UXTX) && (operand.GetExtend() != SXTX)));
181088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1811b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
18120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
181388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
181488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
181588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
1816ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
1817ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1818ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The addressing mode is directly supported by the instruction.
1819ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, operand, S, op);
1820ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1821ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1822ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1823ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
18240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl#define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                          \
18250f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) { \
18260f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(allow_macro_instructions_);                            \
18270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    LoadStoreMacro(REG, addr, OP);                                     \
18280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1829ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlLS_MACRO_LIST(DEFINE_FUNCTION)
1830ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#undef DEFINE_FUNCTION
1831ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1832330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1833ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::LoadStoreMacro(const CPURegister& rt,
1834ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    const MemOperand& addr,
1835ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    LoadStoreOp op) {
1836c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is ldr/str pre/post index:
1837c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ldr/str
1838c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1839c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to update the base
1840c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1841c68cb64496485710cdb5b8480f8fee287058c93farmvixl
184288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t offset = addr.GetOffset();
18435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned access_size = CalcLSDataSize(op);
1844ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1845ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check if an immediate offset fits in the immediate field of the
1846ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // appropriate instruction. If not, emit two instructions to perform
1847ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the operation.
18485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (addr.IsImmediateOffset() && !IsImmLSScaled(offset, access_size) &&
1849ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      !IsImmLSUnscaled(offset)) {
1850ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Immediate offset that can't be encoded using unsigned or unscaled
1851ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // addressing modes.
1852b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
185388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register temp = temps.AcquireSameSizeAs(addr.GetBaseRegister());
185488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(temp, addr.GetOffset());
185588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister(), temp), op);
1856ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPostIndex() && !IsImmLSUnscaled(offset)) {
1857ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Post-index beyond unscaled addressing range.
185888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister()), op);
185988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(addr.GetBaseRegister(), addr.GetBaseRegister(), Operand(offset));
1860ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPreIndex() && !IsImmLSUnscaled(offset)) {
1861ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Pre-index beyond unscaled addressing range.
186288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(addr.GetBaseRegister(), addr.GetBaseRegister(), Operand(offset));
186388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister()), op);
1864ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1865ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Encodable in one load/store instruction.
1866ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LoadStore(rt, addr, op);
1867ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1868ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1869ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
18710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl#define DEFINE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \
18720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  void MacroAssembler::FN(const REGTYPE REG,        \
18730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const REGTYPE REG2,       \
18740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const MemOperand& addr) { \
18750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(allow_macro_instructions_);         \
18760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    LoadStorePairMacro(REG, REG2, addr, OP);        \
18770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1878c68cb64496485710cdb5b8480f8fee287058c93farmvixlLSPAIR_MACRO_LIST(DEFINE_FUNCTION)
1879c68cb64496485710cdb5b8480f8fee287058c93farmvixl#undef DEFINE_FUNCTION
1880c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1881c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid MacroAssembler::LoadStorePairMacro(const CPURegister& rt,
1882c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        const CPURegister& rt2,
1883c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        const MemOperand& addr,
1884c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        LoadStorePairOp op) {
1885c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we support register offset for load-store-pair?
1886c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!addr.IsRegisterOffset());
1887c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is ldp/stp immediate:
1888c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ldp/stp
1889c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1890c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to update the base
1891c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1892c68cb64496485710cdb5b8480f8fee287058c93farmvixl
189388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t offset = addr.GetOffset();
18945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned access_size = CalcLSPairDataSize(op);
1895c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1896c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Check if the offset fits in the immediate field of the appropriate
1897c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // instruction. If not, emit two instructions to perform the operation.
18985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsImmLSPair(offset, access_size)) {
1899c68cb64496485710cdb5b8480f8fee287058c93farmvixl    // Encodable in one load/store pair instruction.
1900c68cb64496485710cdb5b8480f8fee287058c93farmvixl    LoadStorePair(rt, rt2, addr, op);
1901c68cb64496485710cdb5b8480f8fee287058c93farmvixl  } else {
190288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register base = addr.GetBaseRegister();
1903c68cb64496485710cdb5b8480f8fee287058c93farmvixl    if (addr.IsImmediateOffset()) {
1904c68cb64496485710cdb5b8480f8fee287058c93farmvixl      UseScratchRegisterScope temps(this);
1905c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Register temp = temps.AcquireSameSizeAs(base);
1906c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(temp, base, offset);
1907c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(temp), op);
1908c68cb64496485710cdb5b8480f8fee287058c93farmvixl    } else if (addr.IsPostIndex()) {
1909c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(base), op);
1910c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(base, base, offset);
1911c68cb64496485710cdb5b8480f8fee287058c93farmvixl    } else {
1912c68cb64496485710cdb5b8480f8fee287058c93farmvixl      VIXL_ASSERT(addr.IsPreIndex());
1913c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(base, base, offset);
1914c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(base), op);
1915c68cb64496485710cdb5b8480f8fee287058c93farmvixl    }
1916c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
1917c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
1918c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1919330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1920330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid MacroAssembler::Prfm(PrefetchOperation op, const MemOperand& addr) {
1921330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MacroEmissionCheckScope guard(this);
1922330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1923330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // There are no pre- or post-index modes for prfm.
1924330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(addr.IsImmediateOffset() || addr.IsRegisterOffset());
1925330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1926330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The access size is implicitly 8 bytes for all prefetch operations.
19275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned size = kXRegSizeInBytesLog2;
1928330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1929330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Check if an immediate offset fits in the immediate field of the
1930330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // appropriate instruction. If not, emit two instructions to perform
1931330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // the operation.
193288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (addr.IsImmediateOffset() && !IsImmLSScaled(addr.GetOffset(), size) &&
193388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      !IsImmLSUnscaled(addr.GetOffset())) {
1934330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate offset that can't be encoded using unsigned or unscaled
1935330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // addressing modes.
1936330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    UseScratchRegisterScope temps(this);
193788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register temp = temps.AcquireSameSizeAs(addr.GetBaseRegister());
193888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(temp, addr.GetOffset());
193988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Prefetch(op, MemOperand(addr.GetBaseRegister(), temp));
1940330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else {
1941330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Simple register-offsets are encodable in one instruction.
1942330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    Prefetch(op, addr);
1943330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
1944330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
1945330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1946330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
19470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Push(const CPURegister& src0,
19480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src1,
19490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src2,
19500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src3) {
1951b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1952b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
1953b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(src0.IsValid());
1954ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1955ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid();
195688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = src0.GetSizeInBytes();
1957ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1958ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
1959ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushHelper(count, size, src0, src1, src2, src3);
1960ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1961ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1962ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
19630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Pop(const CPURegister& dst0,
19640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst1,
19650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst2,
19660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst3) {
1967ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // It is not valid to pop into the same register more than once in one
1968ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // instruction, not even into the zero register.
1969b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1970b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(dst0, dst1, dst2, dst3));
1971b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
1972b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(dst0.IsValid());
1973ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1974ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid();
197588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = dst0.GetSizeInBytes();
1976ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1977ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPop(count, size);
1978ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopHelper(count, size, dst0, dst1, dst2, dst3);
1979ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1980ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1981ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1982ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCPURegList(CPURegList registers) {
198388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchRegisterList()));
198488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchFPRegisterList()));
1985b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
19866e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
198788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = registers.GetRegisterSizeInBytes();
198888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  PrepareForPush(registers.GetCount(), reg_size);
19896e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
19906e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // Bump the stack pointer and store two registers at the bottom.
199188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = registers.GetTotalSizeInBytes();
19926e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_0 = registers.PopLowestIndex();
19936e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_1 = registers.PopLowestIndex();
19946e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (bottom_0.IsValid() && bottom_1.IsValid()) {
19956e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Stp(bottom_0, bottom_1, MemOperand(StackPointer(), -size, PreIndex));
19966e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (bottom_0.IsValid()) {
19976e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Str(bottom_0, MemOperand(StackPointer(), -size, PreIndex));
19986e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
19996e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20006e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  int offset = 2 * reg_size;
2001ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
20026e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& src0 = registers.PopLowestIndex();
20036e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& src1 = registers.PopLowestIndex();
20046e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (src1.IsValid()) {
20056e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Stp(src0, src1, MemOperand(StackPointer(), offset));
20066e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
20076e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Str(src0, MemOperand(StackPointer(), offset));
20086e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
20096e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    offset += 2 * reg_size;
2010ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2011ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2012ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2013ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2014ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCPURegList(CPURegList registers) {
201588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchRegisterList()));
201688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchFPRegisterList()));
2017b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
20186e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
201988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = registers.GetRegisterSizeInBytes();
202088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  PrepareForPop(registers.GetCount(), reg_size);
20216e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20226e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
202388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = registers.GetTotalSizeInBytes();
20246e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_0 = registers.PopLowestIndex();
20256e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_1 = registers.PopLowestIndex();
20266e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20276e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  int offset = 2 * reg_size;
2028ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
2029ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst0 = registers.PopLowestIndex();
2030ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst1 = registers.PopLowestIndex();
20316e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (dst1.IsValid()) {
20326e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldp(dst0, dst1, MemOperand(StackPointer(), offset));
20336e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
20346e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldr(dst0, MemOperand(StackPointer(), offset));
20356e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
20366e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    offset += 2 * reg_size;
20376e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
20386e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20396e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // Load the two registers at the bottom and drop the stack pointer.
20406e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (bottom_0.IsValid() && bottom_1.IsValid()) {
20416e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Ldp(bottom_0, bottom_1, MemOperand(StackPointer(), size, PostIndex));
20426e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (bottom_0.IsValid()) {
20436e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Ldr(bottom_0, MemOperand(StackPointer(), size, PostIndex));
2044ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2045ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2046ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2047ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2048ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushMultipleTimes(int count, Register src) {
2049b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
205088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = src.GetSizeInBytes();
2051ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2052ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
2053ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push up to four registers at a time if possible because if the current
2054ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer is sp and the register size is 32, registers must be pushed
2055ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in blocks of four in order to maintain the 16-byte alignment for sp.
2056ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (count >= 4) {
2057ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(4, size, src, src, src, src);
2058ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 4;
2059ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2060ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count >= 2) {
2061ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(2, size, src, src, NoReg, NoReg);
2062ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 2;
2063ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2064ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count == 1) {
2065ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(1, size, src, NoReg, NoReg, NoReg);
2066ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 1;
2067ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2068b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(count == 0);
2069ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2070ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2071ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
20720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PushHelper(int count,
20730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                int size,
2074ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src0,
2075ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src1,
2076ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src2,
2077ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src3) {
2078ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
2079c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case for size is 2 stp.
20800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  InstructionAccurateScope scope(this,
20810f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2,
2082c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                 InstructionAccurateScope::kMaximumSize);
2083ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2084b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
208588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(size == src0.GetSizeInBytes());
2086ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2087ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When pushing multiple registers, the store order is chosen such that
2088ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push(a, b) is equivalent to Push(a) followed by Push(b).
2089ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
2090ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
2091b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src1.IsNone() && src2.IsNone() && src3.IsNone());
2092ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), -1 * size, PreIndex));
2093ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2094ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
2095b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src2.IsNone() && src3.IsNone());
2096ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), -2 * size, PreIndex));
2097ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2098ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
2099b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src3.IsNone());
2100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src2, src1, MemOperand(StackPointer(), -3 * size, PreIndex));
2101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), 2 * size));
2102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
2104ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Skip over 4 * size, then fill in the gap. This allows four W registers
2105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be pushed using sp, whilst maintaining 16-byte alignment for sp at
2106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
2107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src3, src2, MemOperand(StackPointer(), -4 * size, PreIndex));
2108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), 2 * size));
2109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
2111b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_UNREACHABLE();
2112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
21160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PopHelper(int count,
21170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                               int size,
2118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst0,
2119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst1,
2120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst2,
2121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst3) {
2122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
2123c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case for size is 2 ldp.
21240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  InstructionAccurateScope scope(this,
21250f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2,
2126c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                 InstructionAccurateScope::kMaximumSize);
2127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2128b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
212988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(size == dst0.GetSizeInBytes());
2130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When popping multiple registers, the load order is chosen such that
2132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Pop(a, b) is equivalent to Pop(a) followed by Pop(b).
2133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
2134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
2135b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst1.IsNone() && dst2.IsNone() && dst3.IsNone());
2136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst0, MemOperand(StackPointer(), 1 * size, PostIndex));
2137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
2139b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst2.IsNone() && dst3.IsNone());
2140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 2 * size, PostIndex));
2141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
2143b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst3.IsNone());
2144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst2, MemOperand(StackPointer(), 2 * size));
2145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 3 * size, PostIndex));
2146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
2148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Load the higher addresses first, then load the lower addresses and skip
2149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // the whole block in the second instruction. This allows four W registers
2150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be popped using sp, whilst maintaining 16-byte alignment for sp at
2151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
2152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size));
2153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex));
2154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
2156b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_UNREACHABLE();
2157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPush(int count, int size) {
2162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
2163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
2164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
2165ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
2166b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT((count * size) % 16 == 0);
2167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
2168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Even if the current stack pointer is not the system stack pointer (sp),
2169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the system stack pointer will still be modified in order to comply with
2170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // ABI rules about accessing memory below the system stack pointer.
2171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(count * size);
2172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPop(int count, int size) {
2177db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  USE(count, size);
2178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
2179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
2180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
2181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
2182b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT((count * size) % 16 == 0);
2183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Poke(const Register& src, const Operand& offset) {
2187b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
218988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(offset.GetImmediate() >= 0);
2190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Str(src, MemOperand(StackPointer(), offset));
2193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2194ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2195ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2196ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Peek(const Register& dst, const Operand& offset) {
2197b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2198ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
219988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(offset.GetImmediate() >= 0);
2200ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2202ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Ldr(dst, MemOperand(StackPointer(), offset));
2203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2205ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2206ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Claim(const Operand& size) {
2207b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2208f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2209f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
2210f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
2211f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
2212f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2213ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
221488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(size.GetImmediate() > 0);
2215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
221688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      VIXL_ASSERT((size.GetImmediate() % 16) == 0);
2217ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2218ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2219ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2220ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
2221ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(size);
2222ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2224ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Sub(StackPointer(), StackPointer(), size);
2225ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2226ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2227ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2228ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Drop(const Operand& size) {
2229b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2230f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2231f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
2232f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
2233f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
2234f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2235ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
223688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(size.GetImmediate() > 0);
2237ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
223888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      VIXL_ASSERT((size.GetImmediate() % 16) == 0);
2239ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2241ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2242ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Add(StackPointer(), StackPointer(), size);
2243ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCalleeSavedRegisters() {
2247ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
2248c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // 10 stp will be emitted.
2249c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we use GetCalleeSaved and SavedFP.
2250c68cb64496485710cdb5b8480f8fee287058c93farmvixl  InstructionAccurateScope scope(this, 10);
2251ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2252ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
2253b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
2254ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2255db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  MemOperand tos(sp, -2 * static_cast<int>(kXRegSizeInBytes), PreIndex);
2256ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x29, x30, tos);
2258ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x27, x28, tos);
2259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x25, x26, tos);
2260ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x23, x24, tos);
2261ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x21, x22, tos);
2262ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x19, x20, tos);
22635799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
22645799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d14, d15, tos);
22655799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d12, d13, tos);
22665799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d10, d11, tos);
22675799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d8, d9, tos);
2268ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2269ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2270ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2271ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCalleeSavedRegisters() {
2272ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
2273c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // 10 ldp will be emitted.
2274c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we use GetCalleeSaved and SavedFP.
2275c68cb64496485710cdb5b8480f8fee287058c93farmvixl  InstructionAccurateScope scope(this, 10);
2276ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2277ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
2278b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
2279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemOperand tos(sp, 2 * kXRegSizeInBytes, PostIndex);
2281ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
22825799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d8, d9, tos);
22835799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d10, d11, tos);
22845799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d12, d13, tos);
22855799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d14, d15, tos);
22865799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2287ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x19, x20, tos);
2288ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x21, x22, tos);
2289ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x23, x24, tos);
2290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x25, x26, tos);
2291ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x27, x28, tos);
2292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x29, x30, tos);
2293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
22956e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::LoadCPURegList(CPURegList registers,
22966e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                    const MemOperand& src) {
22976e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  LoadStoreCPURegListHelper(kLoad, registers, src);
22986e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
22996e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23006e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::StoreCPURegList(CPURegList registers,
23016e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                     const MemOperand& dst) {
23026e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  LoadStoreCPURegListHelper(kStore, registers, dst);
23036e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
23046e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23056e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23066e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::LoadStoreCPURegListHelper(LoadStoreCPURegListAction op,
23076e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                               CPURegList registers,
23086e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                               const MemOperand& mem) {
23096e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // We do not handle pre-indexing or post-indexing.
23106e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!(mem.IsPreIndex() || mem.IsPostIndex()));
23116e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.Overlaps(tmp_list_));
23126e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.Overlaps(fptmp_list_));
23136e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.IncludesAliasOf(sp));
23146e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23156e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  UseScratchRegisterScope temps(this);
23166e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  MemOperand loc = BaseMemOperandForLoadStoreCPURegList(registers, mem, &temps);
23186a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  const int reg_size = registers.GetRegisterSizeInBytes();
23196e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23206a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  VIXL_ASSERT(IsPowerOf2(reg_size));
23216a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov
23226a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // Since we are operating on register pairs, we would like to align on double
23236a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // the standard size; on the other hand, we don't want to insert an extra
23246a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // operation, which will happen if the number of registers is even. Note that
23256a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // the alignment of the base pointer is unknown here, but we assume that it
23266a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // is more likely to be aligned.
23276a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  if (((loc.GetOffset() & (2 * reg_size - 1)) != 0) &&
23286a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      ((registers.GetCount() % 2) != 0)) {
23296a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    if (op == kStore) {
23306a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      Str(registers.PopLowestIndex(), loc);
23316a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    } else {
23326a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      VIXL_ASSERT(op == kLoad);
23336a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      Ldr(registers.PopLowestIndex(), loc);
23346a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    }
23356a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    loc.AddOffset(reg_size);
23366a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  }
233788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  while (registers.GetCount() >= 2) {
23386e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& dst0 = registers.PopLowestIndex();
23396e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& dst1 = registers.PopLowestIndex();
23406e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (op == kStore) {
23416e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Stp(dst0, dst1, loc);
23426e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
23436e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      VIXL_ASSERT(op == kLoad);
23446e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldp(dst0, dst1, loc);
23456e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
23466a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    loc.AddOffset(2 * reg_size);
23476e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
23486e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (!registers.IsEmpty()) {
23496e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (op == kStore) {
23506e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Str(registers.PopLowestIndex(), loc);
23516e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
23526e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      VIXL_ASSERT(op == kLoad);
23536e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldr(registers.PopLowestIndex(), loc);
23546e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
23556e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
23566e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
23576e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23586e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlMemOperand MacroAssembler::BaseMemOperandForLoadStoreCPURegList(
23596e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegList& registers,
23606e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const MemOperand& mem,
23616e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    UseScratchRegisterScope* scratch_scope) {
23626e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // If necessary, pre-compute the base address for the accesses.
23636e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (mem.IsRegisterOffset()) {
23646e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Register reg_base = scratch_scope->AcquireX();
23656e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    ComputeAddress(reg_base, mem);
23666e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    return MemOperand(reg_base);
23676e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23686e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (mem.IsImmediateOffset()) {
236988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int reg_size = registers.GetRegisterSizeInBytes();
237088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int total_size = registers.GetTotalSizeInBytes();
237188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t min_offset = mem.GetOffset();
237288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t max_offset =
237388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        mem.GetOffset() + std::max(0, total_size - 2 * reg_size);
237488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if ((registers.GetCount() >= 2) &&
23756e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        (!Assembler::IsImmLSPair(min_offset, WhichPowerOf2(reg_size)) ||
23766e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl         !Assembler::IsImmLSPair(max_offset, WhichPowerOf2(reg_size)))) {
23776e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Register reg_base = scratch_scope->AcquireX();
23786e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      ComputeAddress(reg_base, mem);
23796e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      return MemOperand(reg_base);
23806e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
23816e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
23826e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23836e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  return mem;
23846e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
23856e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
2386ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::BumpSystemStackPointer(const Operand& space) {
2387b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!sp.Is(StackPointer()));
2388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // TODO: Several callers rely on this not using scratch registers, so we use
2389ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the assembler directly here. However, this means that large immediate
2390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // values of 'space' cannot be handled.
2391c68cb64496485710cdb5b8480f8fee287058c93farmvixl  InstructionAccurateScope scope(this, 1);
2392ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  sub(sp, StackPointer(), space);
2393ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2394ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2395ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
23965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// TODO(all): Fix printf for NEON registers, and resolve whether we should be
23975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// using FPRegister or VRegister here.
23985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// This is the main Printf implementation. All callee-saved registers are
2400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// preserved, but NZCV and the caller-saved registers may be clobbered.
24010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PrintfNoPreserve(const char* format,
2402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg0,
2403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg1,
2404ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg2,
2405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg3) {
2406ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We cannot handle a caller-saved stack pointer. It doesn't make much sense
2407ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in most cases anyway, so this restriction shouldn't be too serious.
2408b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!kCallerSaved.IncludesAliasOf(StackPointer()));
2409b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
24105799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // The provided arguments, and their proper PCS registers.
24115799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegister args[kPrintfMaxArgCount] = {arg0, arg1, arg2, arg3};
24125799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegister pcs[kPrintfMaxArgCount];
24135799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24145799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  int arg_count = kPrintfMaxArgCount;
24155799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24165799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // The PCS varargs registers for printf. Note that x0 is used for the printf
24175799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // format string.
24185799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  static const CPURegList kPCSVarargs =
24195799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      CPURegList(CPURegister::kRegister, kXRegSize, 1, arg_count);
24205799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  static const CPURegList kPCSVarargsFP =
24215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      CPURegList(CPURegister::kVRegister, kDRegSize, 0, arg_count - 1);
24225799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24235799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // We can use caller-saved registers as scratch values, except for the
24245799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // arguments and the PCS registers where they might need to go.
2425b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
24265799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Include(kCallerSaved);
24275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  temps.Include(kCallerSavedV);
24285799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(kPCSVarargs);
24295799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(kPCSVarargsFP);
2430b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  temps.Exclude(arg0, arg1, arg2, arg3);
2431ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24325799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Copies of the arg lists that we can iterate through.
24335799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegList pcs_varargs = kPCSVarargs;
24345799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegList pcs_varargs_fp = kPCSVarargsFP;
24355799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24365799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Place the arguments. There are lots of clever tricks and optimizations we
24375799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // could use here, but Printf is a debug tool so instead we just try to keep
24385799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // it simple: Move each input that isn't already in the right place to a
24395799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // scratch register, then move everything back.
24405799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  for (unsigned i = 0; i < kPrintfMaxArgCount; i++) {
24415799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Work out the proper PCS register for this argument.
2442ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (args[i].IsRegister()) {
24435799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      pcs[i] = pcs_varargs.PopLowestIndex().X();
24445799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // We might only need a W register here. We need to know the size of the
24455799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // argument so we can properly encode it for the simulator call.
24465799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (args[i].Is32Bits()) pcs[i] = pcs[i].W();
24475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else if (args[i].IsVRegister()) {
24485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // In C, floats are always cast to doubles for varargs calls.
24495799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      pcs[i] = pcs_varargs_fp.PopLowestIndex().D();
2450ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
24515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      VIXL_ASSERT(args[i].IsNone());
2452ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      arg_count = i;
2453ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2454ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2455ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24565799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // If the argument is already in the right place, leave it where it is.
24575799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (args[i].Aliases(pcs[i])) continue;
24585799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24595799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Otherwise, if the argument is in a PCS argument register, allocate an
24605799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // appropriate scratch register and then move it out of the way.
24615799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (kPCSVarargs.IncludesAliasOf(args[i]) ||
24625799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        kPCSVarargsFP.IncludesAliasOf(args[i])) {
24635799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (args[i].IsRegister()) {
24645799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Register old_arg = Register(args[i]);
24655799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Register new_arg = temps.AcquireSameSizeAs(old_arg);
24665799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Mov(new_arg, old_arg);
24675799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        args[i] = new_arg;
24685799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
24695799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        FPRegister old_arg = FPRegister(args[i]);
24705799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        FPRegister new_arg = temps.AcquireSameSizeAs(old_arg);
24715799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fmov(new_arg, old_arg);
24725799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        args[i] = new_arg;
24735799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
24745799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
2475ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2476ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24775799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Do a second pass to move values into their final positions and perform any
24785799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // conversions that may be required.
24795799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  for (int i = 0; i < arg_count; i++) {
248088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(pcs[i].GetType() == args[i].GetType());
24815799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (pcs[i].IsRegister()) {
24825799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      Mov(Register(pcs[i]), Register(args[i]), kDiscardForSameWReg);
2483ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
24845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(pcs[i].IsVRegister());
248588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (pcs[i].GetSizeInBits() == args[i].GetSizeInBits()) {
24865799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fmov(FPRegister(pcs[i]), FPRegister(args[i]));
24875799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
24885799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fcvt(FPRegister(pcs[i]), FPRegister(args[i]));
24895799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
2490ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2491ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2492ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2493ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Load the format string into x0, as per the procedure-call standard.
2494ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //
2495ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // To make the code as portable as possible, the format string is encoded
2496ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // directly in the instruction stream. It might be cleaner to encode it in a
2497ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // literal pool, but since Printf is usually used for debugging, it is
2498ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // beneficial for it to be minimally dependent on other features.
24995799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(x0);
2500ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Label format_address;
2501ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Adr(x0, &format_address);
2502ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2503ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Emit the format string directly in the instruction stream.
2504c68cb64496485710cdb5b8480f8fee287058c93farmvixl  {
25055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    BlockPoolsScope scope(this);
2506c68cb64496485710cdb5b8480f8fee287058c93farmvixl    // Data emitted:
2507c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   branch
2508c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   strlen(format) + 1 (includes null termination)
2509c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   padding to next instruction
2510c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   unreachable
25110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmissionCheckScope guard(this,
25120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             AlignUp(strlen(format) + 1, kInstructionSize) +
25130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2 * kInstructionSize);
2514ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Label after_data;
2515ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    B(&after_data);
2516ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&format_address);
2517c68cb64496485710cdb5b8480f8fee287058c93farmvixl    EmitString(format);
2518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Unreachable();
2519ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&after_data);
2520ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2521ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2522ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We don't pass any arguments on the stack, but we still need to align the C
2523ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer to a 16-byte boundary for PCS compliance.
2524ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
2525ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bic(sp, StackPointer(), 0xf);
2526ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2527ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2528ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Actually call printf. This part needs special handling for the simulator,
2529ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // since the system printf function will use a different instruction set and
2530ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the procedure-call standard will not be compatible.
2531703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2532c68cb64496485710cdb5b8480f8fee287058c93farmvixl    InstructionAccurateScope scope(this, kPrintfLength / kInstructionSize);
2533ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    hlt(kPrintfOpcode);
25340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    dc32(arg_count);  // kPrintfArgCountOffset
25355799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
25365799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Determine the argument pattern.
25375799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    uint32_t arg_pattern_list = 0;
25385799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    for (int i = 0; i < arg_count; i++) {
25395799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      uint32_t arg_pattern;
25405799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (pcs[i].IsRegister()) {
25415799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        arg_pattern = pcs[i].Is32Bits() ? kPrintfArgW : kPrintfArgX;
25425799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
25435799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        VIXL_ASSERT(pcs[i].Is64Bits());
25445799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        arg_pattern = kPrintfArgD;
25455799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
25465799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      VIXL_ASSERT(arg_pattern < (1 << kPrintfArgPatternBits));
25475799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i));
25485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
25490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    dc32(arg_pattern_list);  // kPrintfArgPatternListOffset
2550684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2551684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Register tmp = temps.AcquireX();
2552684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Mov(tmp, reinterpret_cast<uintptr_t>(printf));
2553684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Blr(tmp);
2554ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2555ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2556ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2557ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
25580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Printf(const char* format,
25595799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg0,
25605799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg1,
25615799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg2,
25625799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg3) {
25635799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // We can only print sp if it is the current stack pointer.
25645799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  if (!sp.Is(StackPointer())) {
25655799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg0));
25665799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg1));
25675799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg2));
25685799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg3));
25695799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
25705799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2571b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // Make sure that the macro assembler doesn't try to use any of our arguments
2572b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // as scratch registers.
2573b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope exclude_all(this);
2574b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  exclude_all.ExcludeAll();
2575b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2576ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Preserve all caller-saved registers as well as NZCV.
2577ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // If sp is the stack pointer, PushCPURegList asserts that the size of each
2578ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // list is a multiple of 16 bytes.
2579ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushCPURegList(kCallerSaved);
25805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  PushCPURegList(kCallerSavedV);
2581ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
25820f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  {
25830f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    UseScratchRegisterScope temps(this);
2584b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    // We can use caller-saved registers as scratch values (except for argN).
25855799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Include(kCallerSaved);
25865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    temps.Include(kCallerSavedV);
2587b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    temps.Exclude(arg0, arg1, arg2, arg3);
2588b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
25895799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // If any of the arguments are the current stack pointer, allocate a new
25905799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // register for them, and adjust the value to compensate for pushing the
25915799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // caller-saved registers.
25925799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg0_sp = StackPointer().Aliases(arg0);
25935799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg1_sp = StackPointer().Aliases(arg1);
25945799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg2_sp = StackPointer().Aliases(arg2);
25955799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg3_sp = StackPointer().Aliases(arg3);
25965799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (arg0_sp || arg1_sp || arg2_sp || arg3_sp) {
25975799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // Allocate a register to hold the original stack pointer value, to pass
25985799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // to PrintfNoPreserve as an argument.
25995799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      Register arg_sp = temps.AcquireX();
26000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Add(arg_sp,
26010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl          StackPointer(),
260288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          kCallerSaved.GetTotalSizeInBytes() +
260388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              kCallerSavedV.GetTotalSizeInBytes());
260488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg0_sp) arg0 = Register(arg_sp.GetCode(), arg0.GetSizeInBits());
260588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg1_sp) arg1 = Register(arg_sp.GetCode(), arg1.GetSizeInBits());
260688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg2_sp) arg2 = Register(arg_sp.GetCode(), arg2.GetSizeInBits());
260788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg3_sp) arg3 = Register(arg_sp.GetCode(), arg3.GetSizeInBits());
26085799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
26095799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2610b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    // Preserve NZCV.
2611b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register tmp = temps.AcquireX();
2612b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Mrs(tmp, NZCV);
2613b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Push(tmp, xzr);
26145799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Release(tmp);
2615b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2616b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    PrintfNoPreserve(format, arg0, arg1, arg2, arg3);
2617b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
26185799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Restore NZCV.
26195799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    tmp = temps.AcquireX();
2620b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Pop(xzr, tmp);
2621b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Msr(NZCV, tmp);
26225799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Release(tmp);
2623b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2624ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
26255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  PopCPURegList(kCallerSavedV);
2626ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopCPURegList(kCallerSaved);
2627ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2628ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2629ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Trace(TraceParameters parameters, TraceCommand command) {
2630b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2631ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2632703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2633684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // The arguments to the trace pseudo instruction need to be contiguous in
2634684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // memory, so make sure we don't try to emit a literal pool.
2635684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    InstructionAccurateScope scope(this, kTraceLength / kInstructionSize);
2636ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2637684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Label start;
2638684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    bind(&start);
2639ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2640d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames    // Refer to simulator-aarch64.h for a description of the marker and its
2641684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // arguments.
2642684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    hlt(kTraceOpcode);
2643ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
264488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kTraceParamsOffset);
2645684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(parameters);
2646ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
264788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kTraceCommandOffset);
2648684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(command);
2649684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2650684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // Emit nothing on real hardware.
2651684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    USE(parameters, command);
2652684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  }
2653ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2654ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2655ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2656ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Log(TraceParameters parameters) {
2657b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2658ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2659703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2660684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // The arguments to the log pseudo instruction need to be contiguous in
2661684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // memory, so make sure we don't try to emit a literal pool.
2662684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    InstructionAccurateScope scope(this, kLogLength / kInstructionSize);
2663ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2664684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Label start;
2665684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    bind(&start);
2666ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2667d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames    // Refer to simulator-aarch64.h for a description of the marker and its
2668684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // arguments.
2669684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    hlt(kLogOpcode);
2670ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
267188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kLogParamsOffset);
2672684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(parameters);
2673684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2674684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // Emit nothing on real hardware.
2675684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    USE(parameters);
2676684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  }
2677ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2678ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2679578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2680578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::EnableInstrumentation() {
2681b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!isprint(InstrumentStateEnable));
2682578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
2683578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateEnable);
2684578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2685578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2686578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2687578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::DisableInstrumentation() {
2688b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!isprint(InstrumentStateDisable));
2689578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
2690578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateDisable);
2691578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2692578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2693578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2694578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
2695b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(strlen(marker_name) == 2);
2696578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2697578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // We allow only printable characters in the marker names. Unprintable
2698578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // characters are reserved for controlling features of the instrumentation.
2699b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(isprint(marker_name[0]) && isprint(marker_name[1]));
2700578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2701578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
2702578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, (marker_name[1] << 8) | marker_name[0]);
2703578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2704578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2705b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2706330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid UseScratchRegisterScope::Open(MacroAssembler* masm) {
2707330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(!initialised_);
27080f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(masm != NULL);
270988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available_ = masm->GetScratchRegisterList();
271088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  availablefp_ = masm->GetScratchFPRegisterList();
271188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  old_available_ = available_->GetList();
271288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  old_availablefp_ = availablefp_->GetList();
271388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(available_->GetType() == CPURegister::kRegister);
271488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(availablefp_->GetType() == CPURegister::kVRegister);
2715330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2716330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = true;
2717330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2718330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2719330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2720330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2721330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid UseScratchRegisterScope::Close() {
2722330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (available_) {
272388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    available_->SetList(old_available_);
2724330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    available_ = NULL;
2725330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
2726330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (availablefp_) {
272788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    availablefp_->SetList(old_availablefp_);
2728330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    availablefp_ = NULL;
2729330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
2730330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2731330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = false;
2732330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2733330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2734330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2735330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2736330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlUseScratchRegisterScope::UseScratchRegisterScope(MacroAssembler* masm) {
2737330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2738330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = false;
2739fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames#else
2740fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames  USE(initialised_);
2741330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2742330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  Open(masm);
2743330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2744330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2745330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl// This allows deferred (and optional) initialisation of the scope.
2746330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlUseScratchRegisterScope::UseScratchRegisterScope()
27470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    : available_(NULL),
27480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      availablefp_(NULL),
27490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      old_available_(0),
27500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      old_availablefp_(0) {
2751330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2752330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = false;
2753330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2754330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2755330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
27560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlUseScratchRegisterScope::~UseScratchRegisterScope() { Close(); }
2757b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2758b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27595799d6c5d10729eaade85ad608109c83ed1ae63barmvixlbool UseScratchRegisterScope::IsAvailable(const CPURegister& reg) const {
27605799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  return available_->IncludesAliasOf(reg) || availablefp_->IncludesAliasOf(reg);
27615799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
27625799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
27635799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
27644e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre RamesRegister UseScratchRegisterScope::AcquireRegisterOfSize(int size_in_bits) {
276588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int code = AcquireNextAvailable(available_).GetCode();
27664e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  return Register(code, size_in_bits);
2767b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2768b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2769b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27704e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre RamesFPRegister UseScratchRegisterScope::AcquireVRegisterOfSize(int size_in_bits) {
277188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int code = AcquireNextAvailable(availablefp_).GetCode();
27724e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  return FPRegister(code, size_in_bits);
2773b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2774b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2775b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2776b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Release(const CPURegister& reg) {
2777330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(initialised_);
2778b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (reg.IsRegister()) {
277988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ReleaseByCode(available_, reg.GetCode());
2780b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else if (reg.IsFPRegister()) {
278188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ReleaseByCode(availablefp_, reg.GetCode());
2782b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
2783b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT(reg.IsNone());
2784b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2785b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2786b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2787b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27885799d6c5d10729eaade85ad608109c83ed1ae63barmvixlvoid UseScratchRegisterScope::Include(const CPURegList& list) {
2789330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(initialised_);
279088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (list.GetType() == CPURegister::kRegister) {
27915799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Make sure that neither sp nor xzr are included the list.
279288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    IncludeByRegList(available_,
279388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                     list.GetList() & ~(xzr.GetBit() | sp.GetBit()));
27945799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  } else {
279588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(list.GetType() == CPURegister::kVRegister);
279688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    IncludeByRegList(availablefp_, list.GetList());
27975799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
27985799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
27995799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
28005799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2801b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Include(const Register& reg1,
2802b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg2,
2803b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg3,
2804b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg4) {
2805330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(initialised_);
280688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList include =
280788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2808b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // Make sure that neither sp nor xzr are included the list.
280988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  include &= ~(xzr.GetBit() | sp.GetBit());
2810b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2811b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  IncludeByRegList(available_, include);
2812b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2813b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2814b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2815b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Include(const FPRegister& reg1,
2816b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg2,
2817b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg3,
2818b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg4) {
281988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList include =
282088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2821b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  IncludeByRegList(availablefp_, include);
2822b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2823b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2824b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
28255799d6c5d10729eaade85ad608109c83ed1ae63barmvixlvoid UseScratchRegisterScope::Exclude(const CPURegList& list) {
282688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (list.GetType() == CPURegister::kRegister) {
282788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ExcludeByRegList(available_, list.GetList());
28285799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  } else {
282988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(list.GetType() == CPURegister::kVRegister);
283088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ExcludeByRegList(availablefp_, list.GetList());
28315799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
28325799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
28335799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
28345799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2835b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const Register& reg1,
2836b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg2,
2837b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg3,
2838b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg4) {
283988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList exclude =
284088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2841b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(available_, exclude);
2842b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2843b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2844b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2845b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const FPRegister& reg1,
2846b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg2,
2847b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg3,
2848b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg4) {
284988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList excludefp =
285088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2851b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(availablefp_, excludefp);
2852b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2853b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2854b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2855b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const CPURegister& reg1,
2856b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg2,
2857b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg3,
2858b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg4) {
2859b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  RegList exclude = 0;
2860b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  RegList excludefp = 0;
2861b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2862b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  const CPURegister regs[] = {reg1, reg2, reg3, reg4};
2863b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2864b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  for (unsigned i = 0; i < (sizeof(regs) / sizeof(regs[0])); i++) {
2865b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (regs[i].IsRegister()) {
286688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      exclude |= regs[i].GetBit();
2867b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else if (regs[i].IsFPRegister()) {
286888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      excludefp |= regs[i].GetBit();
2869b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else {
2870b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(regs[i].IsNone());
2871b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    }
2872b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2873b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2874b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(available_, exclude);
2875b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(availablefp_, excludefp);
2876b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2877b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2878b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2879b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ExcludeAll() {
288088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ExcludeByRegList(available_, available_->GetList());
288188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ExcludeByRegList(availablefp_, availablefp_->GetList());
2882b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2883b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2884b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2885b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlCPURegister UseScratchRegisterScope::AcquireNextAvailable(
2886b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    CPURegList* available) {
2887b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_CHECK(!available->IsEmpty());
2888b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  CPURegister result = available->PopLowestIndex();
2889b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(result, xzr, sp));
2890b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  return result;
2891b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2892b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2893b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2894b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ReleaseByCode(CPURegList* available, int code) {
2895b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ReleaseByRegList(available, static_cast<RegList>(1) << code);
2896b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2897b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2898b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2899b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ReleaseByRegList(CPURegList* available,
2900b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList regs) {
290188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() | regs);
2902b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2903b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2904b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2905b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::IncludeByRegList(CPURegList* available,
2906b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList regs) {
290788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() | regs);
2908b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2909b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2910b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2911b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ExcludeByRegList(CPURegList* available,
2912b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList exclude) {
291388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() & ~exclude);
2914b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2915b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
291688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch64
2917ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
2918