macro-assembler-aarch64.cc revision 1c78c34397f2c08c012733cc661076e8bd029eab
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
3621e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois      generate_simulator_code_(VIXL_AARCH64_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
3821e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois      generate_simulator_code_(VIXL_AARCH64_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
4001e85b7f2e8ad2bfb233de29405aade635ed207cePierre Langlois      generate_simulator_code_(VIXL_AARCH64_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 {
9481c78c34397f2c08c012733cc661076e8bd029eabAlexandre Rames    Mov(rd, operand.GetRegister(), discard_mode);
949ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
950ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
951ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
952ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
9535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi16bitHelper(const VRegister& vd, uint64_t imm) {
95488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint16(imm));
9555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  int byte1 = (imm & 0xff);
9565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  int byte2 = ((imm >> 8) & 0xff);
9575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (byte1 == byte2) {
9585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd.Is64Bits() ? vd.V8B() : vd.V16B(), byte1);
9595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte1 == 0) {
9605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, byte2, LSL, 8);
9615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte2 == 0) {
9625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, byte1);
9635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte1 == 0xff) {
9645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~byte2 & 0xff, LSL, 8);
9655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte2 == 0xff) {
9665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~byte1 & 0xff);
9675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
9685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
9695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireW();
9705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movz(temp, imm);
9715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    dup(vd, temp);
9725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
9745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi32bitHelper(const VRegister& vd, uint64_t imm) {
97788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint32(imm));
9785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  uint8_t bytes[sizeof(imm)];
9805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  memcpy(bytes, &imm, sizeof(imm));
9815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // All bytes are either 0x00 or 0xff.
9835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
9845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bool all0orff = true;
9855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (int i = 0; i < 4; ++i) {
9865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if ((bytes[i] != 0) && (bytes[i] != 0xff)) {
9875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        all0orff = false;
9885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        break;
9895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
9905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
9915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (all0orff == true) {
9935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd.Is64Bits() ? vd.V1D() : vd.V2D(), ((imm << 32) | imm));
9945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
9955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
9965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Of the 4 bytes, only one byte is non-zero.
9995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (int i = 0; i < 4; i++) {
10005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if ((imm & (0xff << (i * 8))) == imm) {
10015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd, bytes[i], LSL, i * 8);
10025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Of the 4 bytes, only one byte is not 0xff.
10075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (int i = 0; i < 4; i++) {
10085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    uint32_t mask = ~(0xff << (i * 8));
10095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if ((imm & mask) == mask) {
10105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      mvni(vd, ~bytes[i] & 0xff, LSL, i * 8);
10115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0x00MMFFFF.
10165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xff00ffff) == 0x0000ffff) {
10175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, bytes[2], MSL, 16);
10185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0x0000MMFF.
10225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xffff00ff) == 0x000000ff) {
10235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, bytes[1], MSL, 8);
10245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0xFFMM0000.
10285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xff00ffff) == 0xff000000) {
10295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~bytes[2] & 0xff, MSL, 16);
10305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0xFFFFMM00.
10335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xffff00ff) == 0xffff0000) {
10345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~bytes[1] & 0xff, MSL, 8);
10355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Top and bottom 16-bits are equal.
10395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (((imm >> 16) & 0xffff) == (imm & 0xffff)) {
10405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi16bitHelper(vd.Is64Bits() ? vd.V4H() : vd.V8H(), imm & 0xffff);
10415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Default case.
10455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
10475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireW();
10485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Mov(temp, imm);
10495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    dup(vd, temp);
10505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
10525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi64bitHelper(const VRegister& vd, uint64_t imm) {
10555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // All bytes are either 0x00 or 0xff.
10565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bool all0orff = true;
10585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (int i = 0; i < 8; ++i) {
10595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      int byteval = (imm >> (i * 8)) & 0xff;
10605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (byteval != 0 && byteval != 0xff) {
10615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        all0orff = false;
10625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        break;
10635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
10645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (all0orff == true) {
10665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd, imm);
10675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Top and bottom 32-bits are equal.
10725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (((imm >> 32) & 0xffffffff) == (imm & 0xffffffff)) {
10735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi32bitHelper(vd.Is64Bits() ? vd.V2S() : vd.V4S(), imm & 0xffffffff);
10745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Default case.
10785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
10805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireX();
10815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Mov(temp, imm);
10825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.Is1D()) {
10835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      mov(vd.D(), 0, temp);
10845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
10855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      dup(vd.V2D(), temp);
10865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
10895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi(const VRegister& vd,
10925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          uint64_t imm,
10935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          Shift shift,
10945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          int shift_amount) {
10955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
10965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  MacroEmissionCheckScope guard(this);
10975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (shift_amount != 0 || shift != LSL) {
10985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, imm, shift, shift_amount);
10995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is8B() || vd.Is16B()) {
11005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 8-bit immediate.
110188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsUint8(imm));
11025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, imm);
11035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is4H() || vd.Is8H()) {
11045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 16-bit immediate.
11055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi16bitHelper(vd, imm);
11065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is2S() || vd.Is4S()) {
11075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 32-bit immediate.
11085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi32bitHelper(vd, imm);
11095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
11105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 64-bit immediate.
11115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi64bitHelper(vd, imm);
11125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
11135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
11145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Movi(const VRegister& vd, uint64_t hi, uint64_t lo) {
11175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // TODO: Move 128-bit values in a more efficient way.
11185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is128Bits());
11195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UseScratchRegisterScope temps(this);
11205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Movi(vd.V2D(), lo);
11215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Register temp = temps.AcquireX();
11225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Mov(temp, hi);
11235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Ins(vd.V2D(), 1, temp);
11245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
11255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
11265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
1128b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1129c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is mvn immediate with up to 4 instructions.
1130c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1131c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
1133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Call the macro assembler for generic immediates.
113488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mvn(rd, operand.GetImmediate());
1135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
1136b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
113788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1138b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit two instructions for the extend case. This differs from Mov, as
1140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the extend and invert can't be achieved in one instruction.
1141b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rd);
11420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
114388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
114488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
114588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
1146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, Operand(temp));
1147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Otherwise, register and shifted register cases can be handled by the
1149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // assembler directly, using orn.
1150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, operand);
1151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mov(const Register& rd, uint64_t imm) {
1156b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1157330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MoveImmediateHelper(this, rd, imm);
1158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmp(const Register& rn,
1162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
1163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
1164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
1165b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
116688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0)) {
116788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ConditionalCompareMacro(rn, -operand.GetImmediate(), nzcv, cond, CCMN);
1168f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
1169f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
1170f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmn(const Register& rn,
1175ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
1176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
1177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
1178b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
117988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0)) {
118088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ConditionalCompareMacro(rn, -operand.GetImmediate(), nzcv, cond, CCMP);
1181f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
1182f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
1183f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1185ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1187ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::ConditionalCompareMacro(const Register& rn,
1188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             const Operand& operand,
1189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             StatusFlags nzcv,
1190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             Condition cond,
1191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             ConditionalCompareOp op) {
1192b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
1193c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is ccmp immediate:
1194c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1195c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ccmp
1196c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1197c68cb64496485710cdb5b8480f8fee287058c93farmvixl
119888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((operand.IsShiftedRegister() && (operand.GetShiftAmount() == 0)) ||
119988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsImmediate() &&
120088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois       IsImmConditionalCompare(operand.GetImmediate()))) {
1201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The immediate can be encoded in the instruction, or the operand is an
1202ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // unshifted register: call the assembler.
1203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    ConditionalCompare(rn, operand, nzcv, cond, op);
1204ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1205b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1206ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The operand isn't directly supported by the instruction: perform the
1207ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // operation on a temporary register.
1208b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
1209f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Mov(temp, operand);
1210f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompare(rn, temp, nzcv, cond, op);
1211f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1212f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1213f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1214f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
12150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::CselHelper(MacroAssembler* masm,
12160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                const Register& rd,
12170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Operand left,
12180f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Operand right,
12190f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Condition cond,
12200f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                bool* should_synthesise_left,
12210f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                bool* should_synthesise_right) {
12220f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
12230f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(!emit_code || masm->allow_macro_instructions_);
1225b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
12260f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(!rd.IsZero() && !rd.IsSP());
122788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(left.IsImmediate() || !left.GetRegister().IsSP());
122888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(right.IsImmediate() || !right.GetRegister().IsSP());
12290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_left != NULL) *should_synthesise_left = false;
12310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_right != NULL) *should_synthesise_right = false;
12320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // The worst case for size occurs when the inputs are two non encodable
12340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // constants:
12350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  //  * up to 4 instructions to materialise the left constant
12360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  //  * up to 4 instructions to materialise the right constant
1237c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for csel
12380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  EmissionCheckScope guard(masm, 9 * kInstructionSize);
12390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  UseScratchRegisterScope temps;
12400f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (masm != NULL) {
12410f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    temps.Open(masm);
12420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Try to handle cases where both inputs are immediates.
12450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool left_is_immediate = left.IsImmediate() || left.IsZero();
12460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool right_is_immediate = right.IsImmediate() || right.IsZero();
12470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left_is_immediate && right_is_immediate &&
12480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      CselSubHelperTwoImmediates(masm,
12490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 rd,
12500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 left.GetEquivalentImmediate(),
12510f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 right.GetEquivalentImmediate(),
12520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 cond,
12530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 should_synthesise_left,
12540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 should_synthesise_right)) {
12550f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
12560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1257c68cb64496485710cdb5b8480f8fee287058c93farmvixl
12580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Handle cases where one of the two inputs is -1, 0, or 1.
12590f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool left_is_small_immediate =
12600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left_is_immediate && ((-1 <= left.GetEquivalentImmediate()) &&
12610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                            (left.GetEquivalentImmediate() <= 1));
12620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool right_is_small_immediate =
12630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      right_is_immediate && ((-1 <= right.GetEquivalentImmediate()) &&
12640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             (right.GetEquivalentImmediate() <= 1));
12650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (right_is_small_immediate || left_is_small_immediate) {
12660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    bool swapped_inputs = false;
12670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (!right_is_small_immediate) {
12680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      std::swap(left, right);
12690f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      cond = InvertCondition(cond);
12700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      swapped_inputs = true;
12710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    CselSubHelperRightSmallImmediate(masm,
12730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     &temps,
12740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     rd,
12750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     left,
12760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     right,
12770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     cond,
12780f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     swapped_inputs ? should_synthesise_right
12790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                    : should_synthesise_left);
12800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
12810f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12820f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12830f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Otherwise both inputs need to be available in registers. Synthesise them
12840f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // if necessary and emit the `csel`.
12850f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (!left.IsPlainRegister()) {
12860f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
12870f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Register temp = temps.AcquireSameSizeAs(rd);
12880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(temp, left);
12890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left = temp;
12900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_left != NULL) *should_synthesise_left = true;
12920f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (!right.IsPlainRegister()) {
12940f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
12950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Register temp = temps.AcquireSameSizeAs(rd);
12960f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(temp, right);
12970f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      right = temp;
12980f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12990f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_right != NULL) *should_synthesise_right = true;
13000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (emit_code) {
13020f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(left.IsPlainRegister() && right.IsPlainRegister());
130388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (left.GetRegister().Is(right.GetRegister())) {
130488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      masm->Mov(rd, left.GetRegister());
13050f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    } else {
130688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      masm->csel(rd, left.GetRegister(), right.GetRegister(), cond);
13070f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13080f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13090f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13100f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlbool MacroAssembler::CselSubHelperTwoImmediates(MacroAssembler* masm,
13130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                const Register& rd,
13140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                int64_t left,
13150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                int64_t right,
13160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                Condition cond,
13170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                bool* should_synthesise_left,
13180f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                bool* should_synthesise_right) {
13190f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13200f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_left != NULL) *should_synthesise_left = false;
13210f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_right != NULL) *should_synthesise_right = false;
13220f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13230f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left == right) {
13240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) masm->Mov(rd, left);
13250f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13260f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else if (left == -right) {
13270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_right != NULL) *should_synthesise_right = true;
13280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
13290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(rd, right);
13300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Cneg(rd, rd, cond);
13310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (CselSubHelperTwoOrderedImmediates(masm, rd, left, right, cond)) {
13360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else {
13380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    std::swap(left, right);
13390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (CselSubHelperTwoOrderedImmediates(masm,
13400f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          rd,
13410f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          left,
13420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          right,
13430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          InvertCondition(cond))) {
13440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      return true;
13450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // TODO: Handle more situations. For example handle `csel rd, #5, #6, cond`
13490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // with `cinc`.
13500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  return false;
13510f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlbool MacroAssembler::CselSubHelperTwoOrderedImmediates(MacroAssembler* masm,
13550f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       const Register& rd,
13560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       int64_t left,
13570f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       int64_t right,
13580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       Condition cond) {
13590f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
1361dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames  if ((left == 1) && (right == 0)) {
13620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) masm->cset(rd, cond);
13630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
1364dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames  } else if ((left == -1) && (right == 0)) {
1365dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames    if (emit_code) masm->csetm(rd, cond);
13660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  return false;
13690f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::CselSubHelperRightSmallImmediate(
13730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    MacroAssembler* masm,
13740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    UseScratchRegisterScope* temps,
13750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Register& rd,
13760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Operand& left,
13770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Operand& right,
13780f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    Condition cond,
13790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    bool* should_synthesise_left) {
13800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13810f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT((right.IsImmediate() || right.IsZero()) &&
13820f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl              (-1 <= right.GetEquivalentImmediate()) &&
13830f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl              (right.GetEquivalentImmediate() <= 1));
13840f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  Register left_register;
13850f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13860f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left.IsPlainRegister()) {
138788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    left_register = left.GetRegister();
13880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else {
13890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
13900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left_register = temps->AcquireSameSizeAs(rd);
13910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(left_register, left);
13920f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_left != NULL) *should_synthesise_left = true;
13940f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (emit_code) {
13960f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    int64_t imm = right.GetEquivalentImmediate();
13970f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    Register zr = AppropriateZeroRegFor(rd);
1398f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if (imm == 0) {
13990f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csel(rd, left_register, zr, cond);
1400f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    } else if (imm == 1) {
14010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csinc(rd, left_register, zr, cond);
1402ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
14030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      VIXL_ASSERT(imm == -1);
14040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csinv(rd, left_register, zr, cond);
1405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1406ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1407ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1408ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Add(const Register& rd,
1411ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
14126e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         const Operand& operand,
14136e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         FlagsUpdate S) {
1414b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
141588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0) &&
141688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      IsImmAddSub(-operand.GetImmediate())) {
141788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    AddSubMacro(rd, rn, -operand.GetImmediate(), S, SUB);
1418ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
14196e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    AddSubMacro(rd, rn, operand, S, ADD);
1420f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1421f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1422f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1423f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1424f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adds(const Register& rd,
1425f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1426f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
14276e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Add(rd, rn, operand, SetFlags);
1428ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1429ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1430ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1431ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sub(const Register& rd,
1432ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
14336e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         const Operand& operand,
14346e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         FlagsUpdate S) {
1435b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
143688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0) &&
143788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      IsImmAddSub(-operand.GetImmediate())) {
143888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    AddSubMacro(rd, rn, -operand.GetImmediate(), S, ADD);
1439f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
14406e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    AddSubMacro(rd, rn, operand, S, SUB);
1441f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1442f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1443f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1444f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1445f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Subs(const Register& rd,
1446f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1447f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
14486e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Sub(rd, rn, operand, SetFlags);
1449ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1450ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1451ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1452ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
1453b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1454f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Adds(AppropriateZeroRegFor(rn), rn, operand);
1455ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1456ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1457ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1458ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
1459b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1460f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(AppropriateZeroRegFor(rn), rn, operand);
1461ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1462ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1463ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
14640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Fcmp(const FPRegister& fn,
14650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          double value,
14666e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                          FPTrapFlags trap) {
1467b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1468c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is:
1469c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 to materialise the constant, using literal pool if necessary
14706e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  //  * 1 instruction for fcmp{e}
1471c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1472b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (value != 0.0) {
1473b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1474b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    FPRegister tmp = temps.AcquireSameSizeAs(fn);
1475b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Fmov(tmp, value);
14766e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    FPCompareMacro(fn, tmp, trap);
1477b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
14786e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    FPCompareMacro(fn, value, trap);
1479b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1480b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1481b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1482b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
14836e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::Fcmpe(const FPRegister& fn, double value) {
14846e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Fcmp(fn, value, EnableTrap);
14856e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
14866e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
14876e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
14885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Fmov(VRegister vd, double imm) {
1489b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1490c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Floating point immediates are loaded through the literal pool.
1491c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1492c68cb64496485710cdb5b8480f8fee287058c93farmvixl
14935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (vd.Is1S() || vd.Is2S() || vd.Is4S()) {
14945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Fmov(vd, static_cast<float>(imm));
1495b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    return;
1496b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1497b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
14985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is1D() || vd.Is2D());
1499b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (IsImmFP64(imm)) {
15005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    fmov(vd, imm);
1501b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
150288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint64_t rawbits = DoubleToRawbits(imm);
15035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.IsScalar()) {
15045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (rawbits == 0) {
15055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        fmov(vd, xzr);
15065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      } else {
1507db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl        ldr(vd,
1508db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl            new Literal<double>(imm,
1509db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                                &literal_pool_,
1510db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                                RawLiteral::kDeletedOnPlacementByPool));
15115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
15125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
15135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // TODO: consider NEON support for load literal.
15145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Movi(vd, rawbits);
15155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
1516b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1517b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1518b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1519b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Fmov(VRegister vd, float imm) {
1521b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1522c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Floating point immediates are loaded through the literal pool.
1523c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1524c68cb64496485710cdb5b8480f8fee287058c93farmvixl
15255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (vd.Is1D() || vd.Is2D()) {
15265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Fmov(vd, static_cast<double>(imm));
1527b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    return;
1528b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1529b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is1S() || vd.Is2S() || vd.Is4S());
1531b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (IsImmFP32(imm)) {
15325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    fmov(vd, imm);
1533b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
153488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint32_t rawbits = FloatToRawbits(imm);
15355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.IsScalar()) {
15365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (rawbits == 0) {
15375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        fmov(vd, wzr);
15385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      } else {
1539db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl        ldr(vd,
1540db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl            new Literal<float>(imm,
1541db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                               &literal_pool_,
1542db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                               RawLiteral::kDeletedOnPlacementByPool));
15435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
15445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
15455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // TODO: consider NEON support for load literal.
15465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Movi(vd, rawbits);
15475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
1548b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1549b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1550b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1551b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Neg(const Register& rd, const Operand& operand) {
1553b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1554ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
155588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(rd, -operand.GetImmediate());
1556ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1557f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Sub(rd, AppropriateZeroRegFor(rd), operand);
1558ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1559ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1560ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1561ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
15620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Negs(const Register& rd, const Operand& operand) {
1563b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1564f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(rd, AppropriateZeroRegFor(rd), operand);
1565f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1566f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1567f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
15684a102baf640077d6794c0b33bb976f94b86c532barmvixlbool MacroAssembler::TryOneInstrMoveImmediate(const Register& dst,
15694a102baf640077d6794c0b33bb976f94b86c532barmvixl                                              int64_t imm) {
1570330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  return OneInstrMoveImmediateHelper(this, dst, imm);
15714a102baf640077d6794c0b33bb976f94b86c532barmvixl}
15724a102baf640077d6794c0b33bb976f94b86c532barmvixl
15734a102baf640077d6794c0b33bb976f94b86c532barmvixl
15744a102baf640077d6794c0b33bb976f94b86c532barmvixlOperand MacroAssembler::MoveImmediateForShiftedOp(const Register& dst,
15754a102baf640077d6794c0b33bb976f94b86c532barmvixl                                                  int64_t imm) {
157688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = dst.GetSizeInBits();
15774a102baf640077d6794c0b33bb976f94b86c532barmvixl
15784a102baf640077d6794c0b33bb976f94b86c532barmvixl  // Encode the immediate in a single move instruction, if possible.
15794a102baf640077d6794c0b33bb976f94b86c532barmvixl  if (TryOneInstrMoveImmediate(dst, imm)) {
15804a102baf640077d6794c0b33bb976f94b86c532barmvixl    // The move was successful; nothing to do here.
15814a102baf640077d6794c0b33bb976f94b86c532barmvixl  } else {
15824a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Pre-shift the immediate to the least-significant bits of the register.
15834a102baf640077d6794c0b33bb976f94b86c532barmvixl    int shift_low = CountTrailingZeros(imm, reg_size);
15844a102baf640077d6794c0b33bb976f94b86c532barmvixl    int64_t imm_low = imm >> shift_low;
15854a102baf640077d6794c0b33bb976f94b86c532barmvixl
15864a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Pre-shift the immediate to the most-significant bits of the register,
15874a102baf640077d6794c0b33bb976f94b86c532barmvixl    // inserting set bits in the least-significant bits.
15884a102baf640077d6794c0b33bb976f94b86c532barmvixl    int shift_high = CountLeadingZeros(imm, reg_size);
15895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    int64_t imm_high = (imm << shift_high) | ((INT64_C(1) << shift_high) - 1);
15904a102baf640077d6794c0b33bb976f94b86c532barmvixl
15914a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (TryOneInstrMoveImmediate(dst, imm_low)) {
15924a102baf640077d6794c0b33bb976f94b86c532barmvixl      // The new immediate has been moved into the destination's low bits:
15934a102baf640077d6794c0b33bb976f94b86c532barmvixl      // return a new leftward-shifting operand.
15944a102baf640077d6794c0b33bb976f94b86c532barmvixl      return Operand(dst, LSL, shift_low);
15954a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else if (TryOneInstrMoveImmediate(dst, imm_high)) {
15964a102baf640077d6794c0b33bb976f94b86c532barmvixl      // The new immediate has been moved into the destination's high bits:
15974a102baf640077d6794c0b33bb976f94b86c532barmvixl      // return a new rightward-shifting operand.
15984a102baf640077d6794c0b33bb976f94b86c532barmvixl      return Operand(dst, LSR, shift_high);
15994a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else {
16004a102baf640077d6794c0b33bb976f94b86c532barmvixl      Mov(dst, imm);
16014a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
16024a102baf640077d6794c0b33bb976f94b86c532barmvixl  }
16034a102baf640077d6794c0b33bb976f94b86c532barmvixl  return Operand(dst);
16044a102baf640077d6794c0b33bb976f94b86c532barmvixl}
16054a102baf640077d6794c0b33bb976f94b86c532barmvixl
16064a102baf640077d6794c0b33bb976f94b86c532barmvixl
16074e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Ramesvoid MacroAssembler::Move(const GenericOperand& dst,
16084e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames                          const GenericOperand& src) {
16094e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.Equals(src)) {
16104e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    return;
16114e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16124e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16134e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  VIXL_ASSERT(dst.IsValid() && src.IsValid());
16144e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16154e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  // The sizes of the operands must match exactly.
16164e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  VIXL_ASSERT(dst.GetSizeInBits() == src.GetSizeInBits());
16174e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  size_t operand_size = dst.GetSizeInBits();
16184e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  VIXL_ASSERT(operand_size <= kXRegSize);
16194e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16204e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.IsCPURegister() && src.IsCPURegister()) {
16214e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    CPURegister dst_reg = dst.GetCPURegister();
16224e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    CPURegister src_reg = src.GetCPURegister();
16234e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    if (dst_reg.IsRegister() && src_reg.IsRegister()) {
16244e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      Mov(Register(dst_reg), Register(src_reg));
16254e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    } else if (dst_reg.IsVRegister() && src_reg.IsVRegister()) {
16264e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      Fmov(VRegister(dst_reg), VRegister(src_reg));
16274e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    } else {
16284e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      if (dst_reg.IsRegister()) {
16294e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames        Fmov(Register(dst_reg), VRegister(src_reg));
16304e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      } else {
16314e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames        Fmov(VRegister(dst_reg), Register(src_reg));
16324e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames      }
16334e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    }
16344e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    return;
16354e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16364e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16374e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.IsMemOperand() && src.IsMemOperand()) {
16384e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    UseScratchRegisterScope temps(this);
16394e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    CPURegister temp = temps.AcquireCPURegisterOfSize(operand_size);
16404e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Ldr(temp, src.GetMemOperand());
16414e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Str(temp, dst.GetMemOperand());
16424e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    return;
16434e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16444e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16454e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  if (dst.IsCPURegister()) {
16464e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Ldr(dst.GetCPURegister(), src.GetMemOperand());
16474e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  } else {
16484e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames    Str(src.GetCPURegister(), dst.GetMemOperand());
16494e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  }
16504e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames}
16514e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16524e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames
16535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::ComputeAddress(const Register& dst,
16545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                    const MemOperand& mem_op) {
16555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // We cannot handle pre-indexing or post-indexing.
165688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(mem_op.GetAddrMode() == Offset);
165788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register base = mem_op.GetBaseRegister();
16585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (mem_op.IsImmediateOffset()) {
165988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(dst, base, mem_op.GetOffset());
16605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
16615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(mem_op.IsRegisterOffset());
166288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register reg_offset = mem_op.GetRegisterOffset();
166388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Shift shift = mem_op.GetShift();
166488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Extend extend = mem_op.GetExtend();
16655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (shift == NO_SHIFT) {
16665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(extend != NO_EXTEND);
166788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Add(dst, base, Operand(reg_offset, extend, mem_op.GetShiftAmount()));
16685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
16695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(extend == NO_EXTEND);
167088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Add(dst, base, Operand(reg_offset, shift, mem_op.GetShiftAmount()));
16715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
16725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
16735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
16745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
16755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1676ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubMacro(const Register& rd,
1677ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Register& rn,
1678ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Operand& operand,
1679ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 FlagsUpdate S,
1680ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 AddSubOp op) {
1681c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is add/sub immediate:
1682c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1683c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for add/sub
1684c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1685c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1686f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsZero() && rd.Is(rn) && rd.Is64Bits() && rn.Is64Bits() &&
1687f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      (S == LeaveFlags)) {
1688f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // The instruction would be a nop. Avoid generating useless code.
1689f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
1690f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1691f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
169288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((operand.IsImmediate() && !IsImmAddSub(operand.GetImmediate())) ||
16930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      (rn.IsZero() && !operand.IsShiftedRegister()) ||
169488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsShiftedRegister() && (operand.GetShift() == ROR))) {
1695b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1696b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
16974a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (operand.IsImmediate()) {
16984a102baf640077d6794c0b33bb976f94b86c532barmvixl      Operand imm_operand =
169988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          MoveImmediateForShiftedOp(temp, operand.GetImmediate());
17004a102baf640077d6794c0b33bb976f94b86c532barmvixl      AddSub(rd, rn, imm_operand, S, op);
17014a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else {
17024a102baf640077d6794c0b33bb976f94b86c532barmvixl      Mov(temp, operand);
17034a102baf640077d6794c0b33bb976f94b86c532barmvixl      AddSub(rd, rn, temp, S, op);
17044a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
1705ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1706ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSub(rd, rn, operand, S, op);
1707ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1708ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1709ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1710ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1711ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Adc(const Register& rd,
1712ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
1713f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
1714b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1715f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, ADC);
1716f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1717f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1718f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1719f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adcs(const Register& rd,
1720f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1721f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
1722b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1723f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, ADC);
1724ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1725ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1726ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1727ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sbc(const Register& rd,
1728ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
1729f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
1730b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1731f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, SBC);
1732f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1733f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1734f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1735f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Sbcs(const Register& rd,
1736f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1737f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
1738b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1739f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, SBC);
1740ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1741ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1742ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
17430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Ngc(const Register& rd, const Operand& operand) {
1744b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1745ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register zr = AppropriateZeroRegFor(rd);
1746f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbc(rd, zr, operand);
1747f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1748f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1749f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
17500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Ngcs(const Register& rd, const Operand& operand) {
1751b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1752f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Register zr = AppropriateZeroRegFor(rd);
1753f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbcs(rd, zr, operand);
1754ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1755ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1756ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1757ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubWithCarryMacro(const Register& rd,
1758ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Register& rn,
1759ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Operand& operand,
1760ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          FlagsUpdate S,
1761ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          AddSubWithCarryOp op) {
176288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(rd.GetSizeInBits() == rn.GetSizeInBits());
1763c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is addc/subc immediate:
1764c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1765c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for add/sub
1766c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1767b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
1768ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1769ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate() ||
177088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsShiftedRegister() && (operand.GetShift() == ROR))) {
1771ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (immediate or ROR shifted register.)
1772b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
1773ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mov(temp, operand);
1774ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
177588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } else if (operand.IsShiftedRegister() && (operand.GetShiftAmount() != 0)) {
1776ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (shifted register).
177788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() == rd.GetSizeInBits());
177888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShift() != ROR);
177988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
178088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        IsUintN(rd.GetSizeInBits() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
178188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                operand.GetShiftAmount()));
178288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1783b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
178488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    EmitShift(temp,
178588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetRegister(),
178688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShift(),
178788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShiftAmount());
1788ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
1789ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
1790ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (extended register).
179188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() <= rd.GetSizeInBits());
1792ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub extended supports a shift <= 4. We want to support exactly the
1793ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // same modes.
179488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShiftAmount() <= 4);
179588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
179688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        operand.GetRegister().Is64Bits() ||
179788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        ((operand.GetExtend() != UXTX) && (operand.GetExtend() != SXTX)));
179888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1799b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
18000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
180188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
180288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
180388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
1804ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
1805ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1806ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The addressing mode is directly supported by the instruction.
1807ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, operand, S, op);
1808ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1809ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1810ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1811ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
18120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl#define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                          \
18130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) { \
18140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(allow_macro_instructions_);                            \
18150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    LoadStoreMacro(REG, addr, OP);                                     \
18160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1817ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlLS_MACRO_LIST(DEFINE_FUNCTION)
1818ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#undef DEFINE_FUNCTION
1819ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1820330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1821ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::LoadStoreMacro(const CPURegister& rt,
1822ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    const MemOperand& addr,
1823ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    LoadStoreOp op) {
1824c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is ldr/str pre/post index:
1825c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ldr/str
1826c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1827c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to update the base
1828c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1829c68cb64496485710cdb5b8480f8fee287058c93farmvixl
183088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t offset = addr.GetOffset();
18315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned access_size = CalcLSDataSize(op);
1832ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1833ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check if an immediate offset fits in the immediate field of the
1834ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // appropriate instruction. If not, emit two instructions to perform
1835ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the operation.
18365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (addr.IsImmediateOffset() && !IsImmLSScaled(offset, access_size) &&
1837ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      !IsImmLSUnscaled(offset)) {
1838ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Immediate offset that can't be encoded using unsigned or unscaled
1839ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // addressing modes.
1840b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
184188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register temp = temps.AcquireSameSizeAs(addr.GetBaseRegister());
184288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(temp, addr.GetOffset());
184388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister(), temp), op);
1844ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPostIndex() && !IsImmLSUnscaled(offset)) {
1845ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Post-index beyond unscaled addressing range.
184688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister()), op);
184788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(addr.GetBaseRegister(), addr.GetBaseRegister(), Operand(offset));
1848ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPreIndex() && !IsImmLSUnscaled(offset)) {
1849ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Pre-index beyond unscaled addressing range.
185088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(addr.GetBaseRegister(), addr.GetBaseRegister(), Operand(offset));
185188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister()), op);
1852ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1853ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Encodable in one load/store instruction.
1854ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LoadStore(rt, addr, op);
1855ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1856ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1857ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1858ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
18590f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl#define DEFINE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \
18600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  void MacroAssembler::FN(const REGTYPE REG,        \
18610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const REGTYPE REG2,       \
18620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const MemOperand& addr) { \
18630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(allow_macro_instructions_);         \
18640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    LoadStorePairMacro(REG, REG2, addr, OP);        \
18650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1866c68cb64496485710cdb5b8480f8fee287058c93farmvixlLSPAIR_MACRO_LIST(DEFINE_FUNCTION)
1867c68cb64496485710cdb5b8480f8fee287058c93farmvixl#undef DEFINE_FUNCTION
1868c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1869c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid MacroAssembler::LoadStorePairMacro(const CPURegister& rt,
1870c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        const CPURegister& rt2,
1871c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        const MemOperand& addr,
1872c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        LoadStorePairOp op) {
1873c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we support register offset for load-store-pair?
1874c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!addr.IsRegisterOffset());
1875c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is ldp/stp immediate:
1876c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ldp/stp
1877c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1878c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to update the base
1879c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1880c68cb64496485710cdb5b8480f8fee287058c93farmvixl
188188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t offset = addr.GetOffset();
18825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned access_size = CalcLSPairDataSize(op);
1883c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1884c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Check if the offset fits in the immediate field of the appropriate
1885c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // instruction. If not, emit two instructions to perform the operation.
18865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsImmLSPair(offset, access_size)) {
1887c68cb64496485710cdb5b8480f8fee287058c93farmvixl    // Encodable in one load/store pair instruction.
1888c68cb64496485710cdb5b8480f8fee287058c93farmvixl    LoadStorePair(rt, rt2, addr, op);
1889c68cb64496485710cdb5b8480f8fee287058c93farmvixl  } else {
189088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register base = addr.GetBaseRegister();
1891c68cb64496485710cdb5b8480f8fee287058c93farmvixl    if (addr.IsImmediateOffset()) {
1892c68cb64496485710cdb5b8480f8fee287058c93farmvixl      UseScratchRegisterScope temps(this);
1893c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Register temp = temps.AcquireSameSizeAs(base);
1894c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(temp, base, offset);
1895c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(temp), op);
1896c68cb64496485710cdb5b8480f8fee287058c93farmvixl    } else if (addr.IsPostIndex()) {
1897c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(base), op);
1898c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(base, base, offset);
1899c68cb64496485710cdb5b8480f8fee287058c93farmvixl    } else {
1900c68cb64496485710cdb5b8480f8fee287058c93farmvixl      VIXL_ASSERT(addr.IsPreIndex());
1901c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(base, base, offset);
1902c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(base), op);
1903c68cb64496485710cdb5b8480f8fee287058c93farmvixl    }
1904c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
1905c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
1906c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1907330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1908330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid MacroAssembler::Prfm(PrefetchOperation op, const MemOperand& addr) {
1909330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MacroEmissionCheckScope guard(this);
1910330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1911330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // There are no pre- or post-index modes for prfm.
1912330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(addr.IsImmediateOffset() || addr.IsRegisterOffset());
1913330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1914330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The access size is implicitly 8 bytes for all prefetch operations.
19155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned size = kXRegSizeInBytesLog2;
1916330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1917330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Check if an immediate offset fits in the immediate field of the
1918330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // appropriate instruction. If not, emit two instructions to perform
1919330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // the operation.
192088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (addr.IsImmediateOffset() && !IsImmLSScaled(addr.GetOffset(), size) &&
192188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      !IsImmLSUnscaled(addr.GetOffset())) {
1922330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate offset that can't be encoded using unsigned or unscaled
1923330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // addressing modes.
1924330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    UseScratchRegisterScope temps(this);
192588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register temp = temps.AcquireSameSizeAs(addr.GetBaseRegister());
192688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(temp, addr.GetOffset());
192788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Prefetch(op, MemOperand(addr.GetBaseRegister(), temp));
1928330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else {
1929330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Simple register-offsets are encodable in one instruction.
1930330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    Prefetch(op, addr);
1931330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
1932330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
1933330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1934330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
19350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Push(const CPURegister& src0,
19360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src1,
19370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src2,
19380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src3) {
1939b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1940b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
1941b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(src0.IsValid());
1942ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1943ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid();
194488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = src0.GetSizeInBytes();
1945ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1946ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
1947ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushHelper(count, size, src0, src1, src2, src3);
1948ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1949ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1950ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
19510f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Pop(const CPURegister& dst0,
19520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst1,
19530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst2,
19540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst3) {
1955ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // It is not valid to pop into the same register more than once in one
1956ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // instruction, not even into the zero register.
1957b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1958b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(dst0, dst1, dst2, dst3));
1959b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
1960b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(dst0.IsValid());
1961ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1962ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid();
196388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = dst0.GetSizeInBytes();
1964ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1965ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPop(count, size);
1966ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopHelper(count, size, dst0, dst1, dst2, dst3);
1967ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1968ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1969ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1970ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCPURegList(CPURegList registers) {
197188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchRegisterList()));
197288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchFPRegisterList()));
1973b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
19746e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
197588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = registers.GetRegisterSizeInBytes();
197688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  PrepareForPush(registers.GetCount(), reg_size);
19776e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
19786e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // Bump the stack pointer and store two registers at the bottom.
197988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = registers.GetTotalSizeInBytes();
19806e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_0 = registers.PopLowestIndex();
19816e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_1 = registers.PopLowestIndex();
19826e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (bottom_0.IsValid() && bottom_1.IsValid()) {
19836e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Stp(bottom_0, bottom_1, MemOperand(StackPointer(), -size, PreIndex));
19846e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (bottom_0.IsValid()) {
19856e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Str(bottom_0, MemOperand(StackPointer(), -size, PreIndex));
19866e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
19876e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
19886e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  int offset = 2 * reg_size;
1989ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
19906e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& src0 = registers.PopLowestIndex();
19916e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& src1 = registers.PopLowestIndex();
19926e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (src1.IsValid()) {
19936e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Stp(src0, src1, MemOperand(StackPointer(), offset));
19946e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
19956e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Str(src0, MemOperand(StackPointer(), offset));
19966e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
19976e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    offset += 2 * reg_size;
1998ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1999ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2000ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2001ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2002ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCPURegList(CPURegList registers) {
200388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchRegisterList()));
200488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchFPRegisterList()));
2005b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
20066e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
200788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = registers.GetRegisterSizeInBytes();
200888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  PrepareForPop(registers.GetCount(), reg_size);
20096e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20106e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
201188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = registers.GetTotalSizeInBytes();
20126e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_0 = registers.PopLowestIndex();
20136e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_1 = registers.PopLowestIndex();
20146e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20156e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  int offset = 2 * reg_size;
2016ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
2017ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst0 = registers.PopLowestIndex();
2018ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst1 = registers.PopLowestIndex();
20196e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (dst1.IsValid()) {
20206e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldp(dst0, dst1, MemOperand(StackPointer(), offset));
20216e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
20226e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldr(dst0, MemOperand(StackPointer(), offset));
20236e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
20246e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    offset += 2 * reg_size;
20256e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
20266e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
20276e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // Load the two registers at the bottom and drop the stack pointer.
20286e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (bottom_0.IsValid() && bottom_1.IsValid()) {
20296e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Ldp(bottom_0, bottom_1, MemOperand(StackPointer(), size, PostIndex));
20306e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (bottom_0.IsValid()) {
20316e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Ldr(bottom_0, MemOperand(StackPointer(), size, PostIndex));
2032ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2033ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2034ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2035ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2036ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushMultipleTimes(int count, Register src) {
2037b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
203888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = src.GetSizeInBytes();
2039ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2040ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
2041ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push up to four registers at a time if possible because if the current
2042ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer is sp and the register size is 32, registers must be pushed
2043ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in blocks of four in order to maintain the 16-byte alignment for sp.
2044ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (count >= 4) {
2045ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(4, size, src, src, src, src);
2046ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 4;
2047ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2048ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count >= 2) {
2049ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(2, size, src, src, NoReg, NoReg);
2050ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 2;
2051ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2052ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count == 1) {
2053ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(1, size, src, NoReg, NoReg, NoReg);
2054ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 1;
2055ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2056b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(count == 0);
2057ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2058ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2059ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
20600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PushHelper(int count,
20610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                int size,
2062ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src0,
2063ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src1,
2064ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src2,
2065ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src3) {
2066ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
2067c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case for size is 2 stp.
20680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  InstructionAccurateScope scope(this,
20690f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2,
2070c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                 InstructionAccurateScope::kMaximumSize);
2071ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2072b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
207388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(size == src0.GetSizeInBytes());
2074ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2075ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When pushing multiple registers, the store order is chosen such that
2076ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push(a, b) is equivalent to Push(a) followed by Push(b).
2077ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
2078ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
2079b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src1.IsNone() && src2.IsNone() && src3.IsNone());
2080ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), -1 * size, PreIndex));
2081ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2082ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
2083b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src2.IsNone() && src3.IsNone());
2084ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), -2 * size, PreIndex));
2085ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2086ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
2087b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src3.IsNone());
2088ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src2, src1, MemOperand(StackPointer(), -3 * size, PreIndex));
2089ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), 2 * size));
2090ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2091ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
2092ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Skip over 4 * size, then fill in the gap. This allows four W registers
2093ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be pushed using sp, whilst maintaining 16-byte alignment for sp at
2094ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
2095ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src3, src2, MemOperand(StackPointer(), -4 * size, PreIndex));
2096ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), 2 * size));
2097ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2098ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
2099b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_UNREACHABLE();
2100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
21040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PopHelper(int count,
21050f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                               int size,
2106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst0,
2107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst1,
2108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst2,
2109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst3) {
2110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
2111c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case for size is 2 ldp.
21120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  InstructionAccurateScope scope(this,
21130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2,
2114c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                 InstructionAccurateScope::kMaximumSize);
2115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2116b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
211788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(size == dst0.GetSizeInBytes());
2118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When popping multiple registers, the load order is chosen such that
2120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Pop(a, b) is equivalent to Pop(a) followed by Pop(b).
2121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
2122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
2123b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst1.IsNone() && dst2.IsNone() && dst3.IsNone());
2124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst0, MemOperand(StackPointer(), 1 * size, PostIndex));
2125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2126ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
2127b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst2.IsNone() && dst3.IsNone());
2128ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 2 * size, PostIndex));
2129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
2131b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst3.IsNone());
2132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst2, MemOperand(StackPointer(), 2 * size));
2133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 3 * size, PostIndex));
2134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
2136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Load the higher addresses first, then load the lower addresses and skip
2137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // the whole block in the second instruction. This allows four W registers
2138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be popped using sp, whilst maintaining 16-byte alignment for sp at
2139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
2140ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size));
2141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex));
2142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2143ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
2144b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_UNREACHABLE();
2145ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPush(int count, int size) {
2150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
2151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
2152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
2153ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
2154b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT((count * size) % 16 == 0);
2155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
2156ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Even if the current stack pointer is not the system stack pointer (sp),
2157ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the system stack pointer will still be modified in order to comply with
2158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // ABI rules about accessing memory below the system stack pointer.
2159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(count * size);
2160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2163ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2164ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPop(int count, int size) {
2165db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  USE(count, size);
2166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
2167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
2168ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
2169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
2170b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT((count * size) % 16 == 0);
2171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2172ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2173ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2174ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Poke(const Register& src, const Operand& offset) {
2175b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2176ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
217788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(offset.GetImmediate() >= 0);
2178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Str(src, MemOperand(StackPointer(), offset));
2181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Peek(const Register& dst, const Operand& offset) {
2185b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2186ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
218788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(offset.GetImmediate() >= 0);
2188ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2189ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2190ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Ldr(dst, MemOperand(StackPointer(), offset));
2191ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2192ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2193ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2194ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Claim(const Operand& size) {
2195b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2196f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2197f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
2198f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
2199f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
2200f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2201ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
220288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(size.GetImmediate() > 0);
2203ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
220488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      VIXL_ASSERT((size.GetImmediate() % 16) == 0);
2205ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2206ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2207ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2208ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
2209ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(size);
2210ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2211ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2212ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Sub(StackPointer(), StackPointer(), size);
2213ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2214ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2215ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2216ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Drop(const Operand& size) {
2217b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2218f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2219f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
2220f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
2221f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
2222f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2223ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
222488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(size.GetImmediate() > 0);
2225ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
222688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      VIXL_ASSERT((size.GetImmediate() % 16) == 0);
2227ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2228ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2229ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2230ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Add(StackPointer(), StackPointer(), size);
2231ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2232ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2233ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2234ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCalleeSavedRegisters() {
2235ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
2236c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // 10 stp will be emitted.
2237c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we use GetCalleeSaved and SavedFP.
2238c68cb64496485710cdb5b8480f8fee287058c93farmvixl  InstructionAccurateScope scope(this, 10);
2239ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2240ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
2241b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
2242ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2243db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  MemOperand tos(sp, -2 * static_cast<int>(kXRegSizeInBytes), PreIndex);
2244ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2245ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x29, x30, tos);
2246ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x27, x28, tos);
2247ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x25, x26, tos);
2248ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x23, x24, tos);
2249ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x21, x22, tos);
2250ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x19, x20, tos);
22515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
22525799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d14, d15, tos);
22535799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d12, d13, tos);
22545799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d10, d11, tos);
22555799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d8, d9, tos);
2256ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2257ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2258ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2259ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCalleeSavedRegisters() {
2260ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
2261c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // 10 ldp will be emitted.
2262c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we use GetCalleeSaved and SavedFP.
2263c68cb64496485710cdb5b8480f8fee287058c93farmvixl  InstructionAccurateScope scope(this, 10);
2264ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2265ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
2266b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
2267ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2268ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemOperand tos(sp, 2 * kXRegSizeInBytes, PostIndex);
2269ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
22705799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d8, d9, tos);
22715799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d10, d11, tos);
22725799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d12, d13, tos);
22735799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d14, d15, tos);
22745799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2275ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x19, x20, tos);
2276ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x21, x22, tos);
2277ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x23, x24, tos);
2278ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x25, x26, tos);
2279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x27, x28, tos);
2280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x29, x30, tos);
2281ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2282ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
22836e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::LoadCPURegList(CPURegList registers,
22846e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                    const MemOperand& src) {
22856e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  LoadStoreCPURegListHelper(kLoad, registers, src);
22866e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
22876e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
22886e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::StoreCPURegList(CPURegList registers,
22896e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                     const MemOperand& dst) {
22906e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  LoadStoreCPURegListHelper(kStore, registers, dst);
22916e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
22926e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
22936e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
22946e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::LoadStoreCPURegListHelper(LoadStoreCPURegListAction op,
22956e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                               CPURegList registers,
22966e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                               const MemOperand& mem) {
22976e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // We do not handle pre-indexing or post-indexing.
22986e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!(mem.IsPreIndex() || mem.IsPostIndex()));
22996e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.Overlaps(tmp_list_));
23006e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.Overlaps(fptmp_list_));
23016e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.IncludesAliasOf(sp));
23026e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23036e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  UseScratchRegisterScope temps(this);
23046e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23050f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  MemOperand loc = BaseMemOperandForLoadStoreCPURegList(registers, mem, &temps);
23066a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  const int reg_size = registers.GetRegisterSizeInBytes();
23076e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23086a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  VIXL_ASSERT(IsPowerOf2(reg_size));
23096a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov
23106a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // Since we are operating on register pairs, we would like to align on double
23116a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // the standard size; on the other hand, we don't want to insert an extra
23126a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // operation, which will happen if the number of registers is even. Note that
23136a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // the alignment of the base pointer is unknown here, but we assume that it
23146a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // is more likely to be aligned.
23156a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  if (((loc.GetOffset() & (2 * reg_size - 1)) != 0) &&
23166a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      ((registers.GetCount() % 2) != 0)) {
23176a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    if (op == kStore) {
23186a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      Str(registers.PopLowestIndex(), loc);
23196a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    } else {
23206a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      VIXL_ASSERT(op == kLoad);
23216a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      Ldr(registers.PopLowestIndex(), loc);
23226a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    }
23236a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    loc.AddOffset(reg_size);
23246a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  }
232588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  while (registers.GetCount() >= 2) {
23266e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& dst0 = registers.PopLowestIndex();
23276e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& dst1 = registers.PopLowestIndex();
23286e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (op == kStore) {
23296e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Stp(dst0, dst1, loc);
23306e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
23316e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      VIXL_ASSERT(op == kLoad);
23326e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldp(dst0, dst1, loc);
23336e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
23346a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    loc.AddOffset(2 * reg_size);
23356e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
23366e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (!registers.IsEmpty()) {
23376e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (op == kStore) {
23386e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Str(registers.PopLowestIndex(), loc);
23396e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
23406e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      VIXL_ASSERT(op == kLoad);
23416e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldr(registers.PopLowestIndex(), loc);
23426e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
23436e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
23446e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
23456e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23466e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlMemOperand MacroAssembler::BaseMemOperandForLoadStoreCPURegList(
23476e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegList& registers,
23486e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const MemOperand& mem,
23496e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    UseScratchRegisterScope* scratch_scope) {
23506e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // If necessary, pre-compute the base address for the accesses.
23516e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (mem.IsRegisterOffset()) {
23526e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Register reg_base = scratch_scope->AcquireX();
23536e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    ComputeAddress(reg_base, mem);
23546e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    return MemOperand(reg_base);
23556e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23566e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (mem.IsImmediateOffset()) {
235788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int reg_size = registers.GetRegisterSizeInBytes();
235888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int total_size = registers.GetTotalSizeInBytes();
235988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t min_offset = mem.GetOffset();
236088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t max_offset =
236188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        mem.GetOffset() + std::max(0, total_size - 2 * reg_size);
236288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if ((registers.GetCount() >= 2) &&
23636e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        (!Assembler::IsImmLSPair(min_offset, WhichPowerOf2(reg_size)) ||
23646e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl         !Assembler::IsImmLSPair(max_offset, WhichPowerOf2(reg_size)))) {
23656e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Register reg_base = scratch_scope->AcquireX();
23666e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      ComputeAddress(reg_base, mem);
23676e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      return MemOperand(reg_base);
23686e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
23696e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
23706e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
23716e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  return mem;
23726e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
23736e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
2374ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::BumpSystemStackPointer(const Operand& space) {
2375b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!sp.Is(StackPointer()));
2376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // TODO: Several callers rely on this not using scratch registers, so we use
2377ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the assembler directly here. However, this means that large immediate
2378ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // values of 'space' cannot be handled.
2379c68cb64496485710cdb5b8480f8fee287058c93farmvixl  InstructionAccurateScope scope(this, 1);
2380ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  sub(sp, StackPointer(), space);
2381ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2382ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2383ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
23845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// TODO(all): Fix printf for NEON registers, and resolve whether we should be
23855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// using FPRegister or VRegister here.
23865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// This is the main Printf implementation. All callee-saved registers are
2388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// preserved, but NZCV and the caller-saved registers may be clobbered.
23890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PrintfNoPreserve(const char* format,
2390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg0,
2391ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg1,
2392ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg2,
2393ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg3) {
2394ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We cannot handle a caller-saved stack pointer. It doesn't make much sense
2395ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in most cases anyway, so this restriction shouldn't be too serious.
2396b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!kCallerSaved.IncludesAliasOf(StackPointer()));
2397b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
23985799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // The provided arguments, and their proper PCS registers.
23995799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegister args[kPrintfMaxArgCount] = {arg0, arg1, arg2, arg3};
24005799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegister pcs[kPrintfMaxArgCount];
24015799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24025799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  int arg_count = kPrintfMaxArgCount;
24035799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24045799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // The PCS varargs registers for printf. Note that x0 is used for the printf
24055799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // format string.
24065799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  static const CPURegList kPCSVarargs =
24075799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      CPURegList(CPURegister::kRegister, kXRegSize, 1, arg_count);
24085799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  static const CPURegList kPCSVarargsFP =
24095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      CPURegList(CPURegister::kVRegister, kDRegSize, 0, arg_count - 1);
24105799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24115799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // We can use caller-saved registers as scratch values, except for the
24125799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // arguments and the PCS registers where they might need to go.
2413b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
24145799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Include(kCallerSaved);
24155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  temps.Include(kCallerSavedV);
24165799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(kPCSVarargs);
24175799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(kPCSVarargsFP);
2418b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  temps.Exclude(arg0, arg1, arg2, arg3);
2419ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24205799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Copies of the arg lists that we can iterate through.
24215799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegList pcs_varargs = kPCSVarargs;
24225799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegList pcs_varargs_fp = kPCSVarargsFP;
24235799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24245799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Place the arguments. There are lots of clever tricks and optimizations we
24255799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // could use here, but Printf is a debug tool so instead we just try to keep
24265799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // it simple: Move each input that isn't already in the right place to a
24275799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // scratch register, then move everything back.
24285799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  for (unsigned i = 0; i < kPrintfMaxArgCount; i++) {
24295799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Work out the proper PCS register for this argument.
2430ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (args[i].IsRegister()) {
24315799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      pcs[i] = pcs_varargs.PopLowestIndex().X();
24325799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // We might only need a W register here. We need to know the size of the
24335799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // argument so we can properly encode it for the simulator call.
24345799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (args[i].Is32Bits()) pcs[i] = pcs[i].W();
24355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else if (args[i].IsVRegister()) {
24365799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // In C, floats are always cast to doubles for varargs calls.
24375799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      pcs[i] = pcs_varargs_fp.PopLowestIndex().D();
2438ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
24395799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      VIXL_ASSERT(args[i].IsNone());
2440ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      arg_count = i;
2441ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2442ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2443ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24445799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // If the argument is already in the right place, leave it where it is.
24455799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (args[i].Aliases(pcs[i])) continue;
24465799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24475799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Otherwise, if the argument is in a PCS argument register, allocate an
24485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // appropriate scratch register and then move it out of the way.
24495799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (kPCSVarargs.IncludesAliasOf(args[i]) ||
24505799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        kPCSVarargsFP.IncludesAliasOf(args[i])) {
24515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (args[i].IsRegister()) {
24525799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Register old_arg = Register(args[i]);
24535799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Register new_arg = temps.AcquireSameSizeAs(old_arg);
24545799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Mov(new_arg, old_arg);
24555799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        args[i] = new_arg;
24565799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
24575799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        FPRegister old_arg = FPRegister(args[i]);
24585799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        FPRegister new_arg = temps.AcquireSameSizeAs(old_arg);
24595799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fmov(new_arg, old_arg);
24605799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        args[i] = new_arg;
24615799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
24625799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
2463ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2464ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24655799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Do a second pass to move values into their final positions and perform any
24665799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // conversions that may be required.
24675799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  for (int i = 0; i < arg_count; i++) {
246888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(pcs[i].GetType() == args[i].GetType());
24695799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (pcs[i].IsRegister()) {
24705799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      Mov(Register(pcs[i]), Register(args[i]), kDiscardForSameWReg);
2471ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
24725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(pcs[i].IsVRegister());
247388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (pcs[i].GetSizeInBits() == args[i].GetSizeInBits()) {
24745799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fmov(FPRegister(pcs[i]), FPRegister(args[i]));
24755799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
24765799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fcvt(FPRegister(pcs[i]), FPRegister(args[i]));
24775799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
2478ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2479ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2480ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2481ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Load the format string into x0, as per the procedure-call standard.
2482ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //
2483ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // To make the code as portable as possible, the format string is encoded
2484ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // directly in the instruction stream. It might be cleaner to encode it in a
2485ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // literal pool, but since Printf is usually used for debugging, it is
2486ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // beneficial for it to be minimally dependent on other features.
24875799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(x0);
2488ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Label format_address;
2489ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Adr(x0, &format_address);
2490ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2491ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Emit the format string directly in the instruction stream.
2492c68cb64496485710cdb5b8480f8fee287058c93farmvixl  {
24935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    BlockPoolsScope scope(this);
2494c68cb64496485710cdb5b8480f8fee287058c93farmvixl    // Data emitted:
2495c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   branch
2496c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   strlen(format) + 1 (includes null termination)
2497c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   padding to next instruction
2498c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   unreachable
24990f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmissionCheckScope guard(this,
25000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             AlignUp(strlen(format) + 1, kInstructionSize) +
25010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2 * kInstructionSize);
2502ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Label after_data;
2503ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    B(&after_data);
2504ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&format_address);
2505c68cb64496485710cdb5b8480f8fee287058c93farmvixl    EmitString(format);
2506ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Unreachable();
2507ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&after_data);
2508ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2509ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2510ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We don't pass any arguments on the stack, but we still need to align the C
2511ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer to a 16-byte boundary for PCS compliance.
2512ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
2513ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bic(sp, StackPointer(), 0xf);
2514ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2515ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2516ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Actually call printf. This part needs special handling for the simulator,
2517ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // since the system printf function will use a different instruction set and
2518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the procedure-call standard will not be compatible.
2519703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2520c68cb64496485710cdb5b8480f8fee287058c93farmvixl    InstructionAccurateScope scope(this, kPrintfLength / kInstructionSize);
2521ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    hlt(kPrintfOpcode);
25220f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    dc32(arg_count);  // kPrintfArgCountOffset
25235799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
25245799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Determine the argument pattern.
25255799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    uint32_t arg_pattern_list = 0;
25265799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    for (int i = 0; i < arg_count; i++) {
25275799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      uint32_t arg_pattern;
25285799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (pcs[i].IsRegister()) {
25295799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        arg_pattern = pcs[i].Is32Bits() ? kPrintfArgW : kPrintfArgX;
25305799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
25315799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        VIXL_ASSERT(pcs[i].Is64Bits());
25325799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        arg_pattern = kPrintfArgD;
25335799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
25345799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      VIXL_ASSERT(arg_pattern < (1 << kPrintfArgPatternBits));
25355799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i));
25365799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
25370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    dc32(arg_pattern_list);  // kPrintfArgPatternListOffset
2538684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2539684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Register tmp = temps.AcquireX();
2540684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Mov(tmp, reinterpret_cast<uintptr_t>(printf));
2541684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Blr(tmp);
2542ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2543ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2544ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2545ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
25460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Printf(const char* format,
25475799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg0,
25485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg1,
25495799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg2,
25505799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg3) {
25515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // We can only print sp if it is the current stack pointer.
25525799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  if (!sp.Is(StackPointer())) {
25535799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg0));
25545799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg1));
25555799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg2));
25565799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg3));
25575799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
25585799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2559b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // Make sure that the macro assembler doesn't try to use any of our arguments
2560b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // as scratch registers.
2561b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope exclude_all(this);
2562b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  exclude_all.ExcludeAll();
2563b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2564ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Preserve all caller-saved registers as well as NZCV.
2565ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // If sp is the stack pointer, PushCPURegList asserts that the size of each
2566ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // list is a multiple of 16 bytes.
2567ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushCPURegList(kCallerSaved);
25685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  PushCPURegList(kCallerSavedV);
2569ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
25700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  {
25710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    UseScratchRegisterScope temps(this);
2572b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    // We can use caller-saved registers as scratch values (except for argN).
25735799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Include(kCallerSaved);
25745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    temps.Include(kCallerSavedV);
2575b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    temps.Exclude(arg0, arg1, arg2, arg3);
2576b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
25775799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // If any of the arguments are the current stack pointer, allocate a new
25785799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // register for them, and adjust the value to compensate for pushing the
25795799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // caller-saved registers.
25805799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg0_sp = StackPointer().Aliases(arg0);
25815799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg1_sp = StackPointer().Aliases(arg1);
25825799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg2_sp = StackPointer().Aliases(arg2);
25835799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg3_sp = StackPointer().Aliases(arg3);
25845799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (arg0_sp || arg1_sp || arg2_sp || arg3_sp) {
25855799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // Allocate a register to hold the original stack pointer value, to pass
25865799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // to PrintfNoPreserve as an argument.
25875799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      Register arg_sp = temps.AcquireX();
25880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Add(arg_sp,
25890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl          StackPointer(),
259088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          kCallerSaved.GetTotalSizeInBytes() +
259188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              kCallerSavedV.GetTotalSizeInBytes());
259288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg0_sp) arg0 = Register(arg_sp.GetCode(), arg0.GetSizeInBits());
259388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg1_sp) arg1 = Register(arg_sp.GetCode(), arg1.GetSizeInBits());
259488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg2_sp) arg2 = Register(arg_sp.GetCode(), arg2.GetSizeInBits());
259588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg3_sp) arg3 = Register(arg_sp.GetCode(), arg3.GetSizeInBits());
25965799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
25975799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2598b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    // Preserve NZCV.
2599b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register tmp = temps.AcquireX();
2600b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Mrs(tmp, NZCV);
2601b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Push(tmp, xzr);
26025799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Release(tmp);
2603b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2604b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    PrintfNoPreserve(format, arg0, arg1, arg2, arg3);
2605b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
26065799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Restore NZCV.
26075799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    tmp = temps.AcquireX();
2608b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Pop(xzr, tmp);
2609b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Msr(NZCV, tmp);
26105799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Release(tmp);
2611b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2612ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
26135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  PopCPURegList(kCallerSavedV);
2614ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopCPURegList(kCallerSaved);
2615ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2616ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2617ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Trace(TraceParameters parameters, TraceCommand command) {
2618b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2619ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2620703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2621684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // The arguments to the trace pseudo instruction need to be contiguous in
2622684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // memory, so make sure we don't try to emit a literal pool.
2623684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    InstructionAccurateScope scope(this, kTraceLength / kInstructionSize);
2624ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2625684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Label start;
2626684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    bind(&start);
2627ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2628d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames    // Refer to simulator-aarch64.h for a description of the marker and its
2629684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // arguments.
2630684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    hlt(kTraceOpcode);
2631ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
263288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kTraceParamsOffset);
2633684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(parameters);
2634ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
263588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kTraceCommandOffset);
2636684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(command);
2637684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2638684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // Emit nothing on real hardware.
2639684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    USE(parameters, command);
2640684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  }
2641ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2642ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2643ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2644ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Log(TraceParameters parameters) {
2645b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2646ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2647703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2648684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // The arguments to the log pseudo instruction need to be contiguous in
2649684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // memory, so make sure we don't try to emit a literal pool.
2650684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    InstructionAccurateScope scope(this, kLogLength / kInstructionSize);
2651ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2652684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Label start;
2653684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    bind(&start);
2654ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2655d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames    // Refer to simulator-aarch64.h for a description of the marker and its
2656684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // arguments.
2657684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    hlt(kLogOpcode);
2658ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
265988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kLogParamsOffset);
2660684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(parameters);
2661684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2662684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // Emit nothing on real hardware.
2663684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    USE(parameters);
2664684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  }
2665ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2666ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2667578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2668578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::EnableInstrumentation() {
2669b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!isprint(InstrumentStateEnable));
2670578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
2671578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateEnable);
2672578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2673578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2674578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2675578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::DisableInstrumentation() {
2676b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!isprint(InstrumentStateDisable));
2677578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
2678578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateDisable);
2679578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2680578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2681578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2682578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
2683b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(strlen(marker_name) == 2);
2684578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2685578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // We allow only printable characters in the marker names. Unprintable
2686578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // characters are reserved for controlling features of the instrumentation.
2687b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(isprint(marker_name[0]) && isprint(marker_name[1]));
2688578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2689578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
2690578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, (marker_name[1] << 8) | marker_name[0]);
2691578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2692578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2693b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2694330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid UseScratchRegisterScope::Open(MacroAssembler* masm) {
2695330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(!initialised_);
26960f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(masm != NULL);
269788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available_ = masm->GetScratchRegisterList();
269888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  availablefp_ = masm->GetScratchFPRegisterList();
269988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  old_available_ = available_->GetList();
270088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  old_availablefp_ = availablefp_->GetList();
270188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(available_->GetType() == CPURegister::kRegister);
270288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(availablefp_->GetType() == CPURegister::kVRegister);
2703330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2704330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = true;
2705330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2706330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2707330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2708330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2709330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid UseScratchRegisterScope::Close() {
2710330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (available_) {
271188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    available_->SetList(old_available_);
2712330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    available_ = NULL;
2713330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
2714330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (availablefp_) {
271588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    availablefp_->SetList(old_availablefp_);
2716330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    availablefp_ = NULL;
2717330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
2718330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2719330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = false;
2720330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2721330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2722330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2723330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2724330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlUseScratchRegisterScope::UseScratchRegisterScope(MacroAssembler* masm) {
2725330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2726330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = false;
2727fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames#else
2728fd09817b8770a5e3a64a6fe4fefe85cc29805cd7Alexandre Rames  USE(initialised_);
2729330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2730330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  Open(masm);
2731330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2732330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2733330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl// This allows deferred (and optional) initialisation of the scope.
2734330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlUseScratchRegisterScope::UseScratchRegisterScope()
27350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    : available_(NULL),
27360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      availablefp_(NULL),
27370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      old_available_(0),
27380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      old_availablefp_(0) {
2739330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2740330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = false;
2741330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2742330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2743330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
27440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlUseScratchRegisterScope::~UseScratchRegisterScope() { Close(); }
2745b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2746b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27475799d6c5d10729eaade85ad608109c83ed1ae63barmvixlbool UseScratchRegisterScope::IsAvailable(const CPURegister& reg) const {
27485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  return available_->IncludesAliasOf(reg) || availablefp_->IncludesAliasOf(reg);
27495799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
27505799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
27515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
27524e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre RamesRegister UseScratchRegisterScope::AcquireRegisterOfSize(int size_in_bits) {
275388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int code = AcquireNextAvailable(available_).GetCode();
27544e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  return Register(code, size_in_bits);
2755b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2756b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2757b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27584e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre RamesFPRegister UseScratchRegisterScope::AcquireVRegisterOfSize(int size_in_bits) {
275988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int code = AcquireNextAvailable(availablefp_).GetCode();
27604e7c93cc256c7719d69279d64e4f5d09044b8b2cAlexandre Rames  return FPRegister(code, size_in_bits);
2761b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2762b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2763b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2764b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Release(const CPURegister& reg) {
2765330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(initialised_);
2766b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (reg.IsRegister()) {
276788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ReleaseByCode(available_, reg.GetCode());
2768b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else if (reg.IsFPRegister()) {
276988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ReleaseByCode(availablefp_, reg.GetCode());
2770b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
2771b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT(reg.IsNone());
2772b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2773b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2774b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2775b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27765799d6c5d10729eaade85ad608109c83ed1ae63barmvixlvoid UseScratchRegisterScope::Include(const CPURegList& list) {
2777330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(initialised_);
277888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (list.GetType() == CPURegister::kRegister) {
27795799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Make sure that neither sp nor xzr are included the list.
278088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    IncludeByRegList(available_,
278188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                     list.GetList() & ~(xzr.GetBit() | sp.GetBit()));
27825799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  } else {
278388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(list.GetType() == CPURegister::kVRegister);
278488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    IncludeByRegList(availablefp_, list.GetList());
27855799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
27865799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
27875799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
27885799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2789b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Include(const Register& reg1,
2790b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg2,
2791b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg3,
2792b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg4) {
2793330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(initialised_);
279488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList include =
279588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2796b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // Make sure that neither sp nor xzr are included the list.
279788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  include &= ~(xzr.GetBit() | sp.GetBit());
2798b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2799b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  IncludeByRegList(available_, include);
2800b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2801b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2802b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2803b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Include(const FPRegister& reg1,
2804b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg2,
2805b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg3,
2806b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg4) {
280788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList include =
280888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2809b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  IncludeByRegList(availablefp_, include);
2810b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2811b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2812b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
28135799d6c5d10729eaade85ad608109c83ed1ae63barmvixlvoid UseScratchRegisterScope::Exclude(const CPURegList& list) {
281488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (list.GetType() == CPURegister::kRegister) {
281588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ExcludeByRegList(available_, list.GetList());
28165799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  } else {
281788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(list.GetType() == CPURegister::kVRegister);
281888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ExcludeByRegList(availablefp_, list.GetList());
28195799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
28205799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
28215799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
28225799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2823b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const Register& reg1,
2824b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg2,
2825b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg3,
2826b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg4) {
282788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList exclude =
282888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2829b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(available_, exclude);
2830b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2831b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2832b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2833b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const FPRegister& reg1,
2834b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg2,
2835b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg3,
2836b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg4) {
283788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList excludefp =
283888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2839b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(availablefp_, excludefp);
2840b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2841b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2842b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2843b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const CPURegister& reg1,
2844b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg2,
2845b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg3,
2846b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg4) {
2847b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  RegList exclude = 0;
2848b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  RegList excludefp = 0;
2849b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2850b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  const CPURegister regs[] = {reg1, reg2, reg3, reg4};
2851b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2852b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  for (unsigned i = 0; i < (sizeof(regs) / sizeof(regs[0])); i++) {
2853b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (regs[i].IsRegister()) {
285488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      exclude |= regs[i].GetBit();
2855b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else if (regs[i].IsFPRegister()) {
285688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      excludefp |= regs[i].GetBit();
2857b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else {
2858b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(regs[i].IsNone());
2859b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    }
2860b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2861b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2862b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(available_, exclude);
2863b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(availablefp_, excludefp);
2864b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2865b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2866b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2867b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ExcludeAll() {
286888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ExcludeByRegList(available_, available_->GetList());
286988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ExcludeByRegList(availablefp_, availablefp_->GetList());
2870b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2871b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2872b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2873b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlCPURegister UseScratchRegisterScope::AcquireNextAvailable(
2874b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    CPURegList* available) {
2875b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_CHECK(!available->IsEmpty());
2876b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  CPURegister result = available->PopLowestIndex();
2877b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(result, xzr, sp));
2878b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  return result;
2879b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2880b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2881b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2882b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ReleaseByCode(CPURegList* available, int code) {
2883b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ReleaseByRegList(available, static_cast<RegList>(1) << code);
2884b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2885b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2886b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2887b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ReleaseByRegList(CPURegList* available,
2888b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList regs) {
288988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() | regs);
2890b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2891b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2892b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2893b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::IncludeByRegList(CPURegList* available,
2894b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList regs) {
289588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() | regs);
2896b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2897b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2898b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2899b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ExcludeByRegList(CPURegList* available,
2900b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList exclude) {
290188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() & ~exclude);
2902b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2903b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
290488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch64
2905ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
2906