macro-assembler-aarch64.cc revision 703ff06a087f67fccde24a7ffbc8a2e74a406cb1
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
27684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl#include <ctype.h>
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);
1045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  InstructionAccurateScope guard(masm_, emit_size / kInstructionSize);
1055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (option == kBranchRequired) masm_->b(&end_of_pool);
106c68cb64496485710cdb5b8480f8fee287058c93farmvixl
107c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Marker indicating the size of the literal pool in 32-bit words.
108c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT((pool_size % kWRegSizeInBytes) == 0);
109db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  masm_->ldr(xzr, static_cast<int>(pool_size / kWRegSizeInBytes));
110c68cb64496485710cdb5b8480f8fee287058c93farmvixl
111c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Now populate the literal pool.
112c68cb64496485710cdb5b8480f8fee287058c93farmvixl  std::vector<RawLiteral*>::iterator it, end;
113c68cb64496485710cdb5b8480f8fee287058c93farmvixl  for (it = entries_.begin(), end = entries_.end(); it != end; ++it) {
114c68cb64496485710cdb5b8480f8fee287058c93farmvixl    VIXL_ASSERT((*it)->IsUsed());
1155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    masm_->place(*it);
116c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
117c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (option == kBranchRequired) masm_->bind(&end_of_pool);
119c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Reset();
1215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
124db6443499376478f5281607a3923e6ffc4c8d8ecarmvixlvoid LiteralPool::AddEntry(RawLiteral* literal) {
125db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  // A literal must be registered immediately before its first use. Here we
126db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  // cannot control that it is its first use, but we check no code has been
127db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  // emitted since its last use.
12888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(masm_->GetCursorOffset() == literal->GetLastUse());
1295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
13088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  UpdateFirstUse(masm_->GetCursorOffset());
13188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(masm_->GetCursorOffset() >= first_use_);
1325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  entries_.push_back(literal);
13388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  size_ += literal->GetSize();
134db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl}
135db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl
1365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
137db6443499376478f5281607a3923e6ffc4c8d8ecarmvixlvoid LiteralPool::UpdateFirstUse(ptrdiff_t use_position) {
138db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  first_use_ = std::min(first_use_, use_position);
139db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  if (first_use_ == -1) {
140db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    first_use_ = use_position;
14188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    SetNextRecommendedCheckpoint(GetNextRecommendedCheckpoint());
142db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    SetNextCheckpoint(first_use_ + Instruction::kLoadLiteralRange);
143db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  } else {
144db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    VIXL_ASSERT(use_position > first_use_);
145db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  }
1465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::Reset() {
1505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Pool::Reset();
1515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unresolved_branches_.Reset();
1525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::Release() {
1565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (--monitor_ == 0) {
1575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(IsEmpty() ||
15888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                masm_->GetCursorOffset() <
15988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    unresolved_branches_.GetFirstLimit());
1605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
161c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
162c68cb64496485710cdb5b8480f8fee287058c93farmvixl
163c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::RegisterUnresolvedBranch(ptrdiff_t branch_pos,
1655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                          Label* label,
1665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                          ImmBranchType branch_type) {
1675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!label->IsBound());
1685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  BranchInfo branch_info = BranchInfo(branch_pos, label, branch_type);
1695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unresolved_branches_.insert(branch_info);
1705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UpdateNextCheckPoint();
1715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // TODO: In debug mode register the label with the assembler to make sure it
1725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // is bound with masm Bind and not asm bind.
1735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::DeleteUnresolvedBranchInfoForLabel(Label* label) {
177c68cb64496485710cdb5b8480f8fee287058c93farmvixl  if (IsEmpty()) {
1785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(checkpoint_ == kNoCheckpointRequired);
1795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
180c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
181c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsLinked()) {
1835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label::LabelLinksIterator links_it(label);
1845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (; !links_it.Done(); links_it.Advance()) {
1855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      ptrdiff_t link_offset = *links_it.Current();
18688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Instruction* link = masm_->GetInstructionAt(link_offset);
187c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // ADR instructions are not handled.
18988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (BranchTypeUsesVeneers(link->GetBranchType())) {
19088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        BranchInfo branch_info(link_offset, label, link->GetBranchType());
1915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        unresolved_branches_.erase(branch_info);
1925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
1935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
1945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
1955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UpdateNextCheckPoint();
1975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
1985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
200db6443499376478f5281607a3923e6ffc4c8d8ecarmvixlbool VeneerPool::ShouldEmitVeneer(int64_t max_reachable_pc, size_t amount) {
2015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  ptrdiff_t offset =
20288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      kPoolNonVeneerCodeSize + amount + GetMaxSize() + GetOtherPoolsMaxSize();
20388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return (masm_->GetCursorOffset() + offset) > max_reachable_pc;
2045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
2055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::CheckEmitFor(size_t amount, EmitOption option) {
2085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsEmpty()) return;
2095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
21088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(masm_->GetCursorOffset() < unresolved_branches_.GetFirstLimit());
2115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsBlocked()) return;
2135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (ShouldEmitVeneers(amount)) {
2155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Emit(option, amount);
2165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
2175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UpdateNextCheckPoint();
2185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
2205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid VeneerPool::Emit(EmitOption option, size_t amount) {
2235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // There is an issue if we are asked to emit a blocked or empty pool.
2245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!IsBlocked());
2255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!IsEmpty());
2265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Label end;
2285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (option == kBranchRequired) {
2295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    InstructionAccurateScope scope(masm_, 1);
2305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    masm_->b(&end);
2315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // We want to avoid generating veneer pools too often, so generate veneers for
2345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // branches that don't immediately require a veneer but will soon go out of
2355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // range.
2365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  static const size_t kVeneerEmissionMargin = 1 * KBytes;
2375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (BranchInfoSetIterator it(&unresolved_branches_); !it.Done();) {
2395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    BranchInfo* branch_info = it.Current();
2405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (ShouldEmitVeneer(branch_info->max_reachable_pc_,
2415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                         amount + kVeneerEmissionMargin)) {
2425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      InstructionAccurateScope scope(masm_, kVeneerCodeSize / kInstructionSize);
2435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      ptrdiff_t branch_pos = branch_info->pc_offset_;
24488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Instruction* branch = masm_->GetInstructionAt(branch_pos);
2455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Label* label = branch_info->label_;
2465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // Patch the branch to point to the current position, and emit a branch
2485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // to the label.
2495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Instruction* veneer = masm_->GetCursorAddress<Instruction*>();
2505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      branch->SetImmPCOffsetTarget(veneer);
2515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      masm_->b(label);
2525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // Update the label. The branch patched does not point to it any longer.
2545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      label->DeleteLink(branch_pos);
2555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      it.DeleteCurrentAndAdvance();
2575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
2585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      it.AdvanceToNextType();
2595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
2605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
2615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UpdateNextCheckPoint();
2635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  masm_->bind(&end);
265c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
266c68cb64496485710cdb5b8480f8fee287058c93farmvixl
267c68cb64496485710cdb5b8480f8fee287058c93farmvixl
268db6443499376478f5281607a3923e6ffc4c8d8ecarmvixlEmissionCheckScope::EmissionCheckScope(MacroAssembler* masm, size_t size)
269db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl    : masm_(masm) {
2700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (masm_ == NULL) {
2710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    // Nothing to do.
2720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    // We may reach this point in a context of conditional code generation. See
2730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    // `MacroAssembler::MoveImmediateHelper()` for an example.
2740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
2750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
276db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  masm_->EnsureEmitFor(size);
277db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  masm_->BlockPools();
278330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
279db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  masm_->Bind(&start_);
280db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  size_ = size;
281db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  masm_->AcquireBuffer();
282c68cb64496485710cdb5b8480f8fee287058c93farmvixl#endif
283c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
284c68cb64496485710cdb5b8480f8fee287058c93farmvixl
285c68cb64496485710cdb5b8480f8fee287058c93farmvixl
286c68cb64496485710cdb5b8480f8fee287058c93farmvixlEmissionCheckScope::~EmissionCheckScope() {
2870f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (masm_ == NULL) {
2880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    // Nothing to do.
2890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
2900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
291330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
292db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  masm_->ReleaseBuffer();
29388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(masm_->GetSizeOfCodeGeneratedSince(&start_) <= size_);
294c68cb64496485710cdb5b8480f8fee287058c93farmvixl#endif
295db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  masm_->ReleasePools();
296c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
297c68cb64496485710cdb5b8480f8fee287058c93farmvixl
298c68cb64496485710cdb5b8480f8fee287058c93farmvixl
299f2f550c0bfd0f15a4d1c51ff06ec898536f14205Alexandre RamesMacroAssembler::MacroAssembler(PositionIndependentCodeOption pic)
300f2f550c0bfd0f15a4d1c51ff06ec898536f14205Alexandre Rames    : Assembler(pic),
301b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames#ifdef VIXL_DEBUG
302b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      allow_macro_instructions_(true),
303b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames#endif
304703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames      generate_simulator_code_(VIXL_GENERATE_SIMULATOR_CODE),
305b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      sp_(sp),
306b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      tmp_list_(ip0, ip1),
307b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      fptmp_list_(d31),
308b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      literal_pool_(this),
309b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      veneer_pool_(this),
310b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames      recommended_checkpoint_(Pool::kNoCheckpointRequired) {
311b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames  checkpoint_ = GetNextCheckPoint();
312b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames}
313b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames
314b0d7672aa9d5163ffce32f14a0fc1aa32f516f89Alexandre Rames
315c68cb64496485710cdb5b8480f8fee287058c93farmvixlMacroAssembler::MacroAssembler(size_t capacity,
316c68cb64496485710cdb5b8480f8fee287058c93farmvixl                               PositionIndependentCodeOption pic)
317c68cb64496485710cdb5b8480f8fee287058c93farmvixl    : Assembler(capacity, pic),
318330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
319c68cb64496485710cdb5b8480f8fee287058c93farmvixl      allow_macro_instructions_(true),
320c68cb64496485710cdb5b8480f8fee287058c93farmvixl#endif
321703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames      generate_simulator_code_(VIXL_GENERATE_SIMULATOR_CODE),
322c68cb64496485710cdb5b8480f8fee287058c93farmvixl      sp_(sp),
323c68cb64496485710cdb5b8480f8fee287058c93farmvixl      tmp_list_(ip0, ip1),
324c68cb64496485710cdb5b8480f8fee287058c93farmvixl      fptmp_list_(d31),
3255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      literal_pool_(this),
326db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      veneer_pool_(this),
327db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      recommended_checkpoint_(Pool::kNoCheckpointRequired) {
32888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
329c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
330c68cb64496485710cdb5b8480f8fee287058c93farmvixl
331c68cb64496485710cdb5b8480f8fee287058c93farmvixl
3320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlMacroAssembler::MacroAssembler(byte* buffer,
333c68cb64496485710cdb5b8480f8fee287058c93farmvixl                               size_t capacity,
334c68cb64496485710cdb5b8480f8fee287058c93farmvixl                               PositionIndependentCodeOption pic)
335c68cb64496485710cdb5b8480f8fee287058c93farmvixl    : Assembler(buffer, capacity, pic),
336330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
337c68cb64496485710cdb5b8480f8fee287058c93farmvixl      allow_macro_instructions_(true),
338c68cb64496485710cdb5b8480f8fee287058c93farmvixl#endif
339703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames      generate_simulator_code_(VIXL_GENERATE_SIMULATOR_CODE),
340c68cb64496485710cdb5b8480f8fee287058c93farmvixl      sp_(sp),
341c68cb64496485710cdb5b8480f8fee287058c93farmvixl      tmp_list_(ip0, ip1),
342c68cb64496485710cdb5b8480f8fee287058c93farmvixl      fptmp_list_(d31),
3435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      literal_pool_(this),
344db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      veneer_pool_(this),
345db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl      recommended_checkpoint_(Pool::kNoCheckpointRequired) {
34688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
347c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
348c68cb64496485710cdb5b8480f8fee287058c93farmvixl
349c68cb64496485710cdb5b8480f8fee287058c93farmvixl
3500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlMacroAssembler::~MacroAssembler() {}
351c68cb64496485710cdb5b8480f8fee287058c93farmvixl
352c68cb64496485710cdb5b8480f8fee287058c93farmvixl
353c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid MacroAssembler::Reset() {
354c68cb64496485710cdb5b8480f8fee287058c93farmvixl  Assembler::Reset();
355c68cb64496485710cdb5b8480f8fee287058c93farmvixl
356c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!literal_pool_.IsBlocked());
357c68cb64496485710cdb5b8480f8fee287058c93farmvixl  literal_pool_.Reset();
3585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.Reset();
359c68cb64496485710cdb5b8480f8fee287058c93farmvixl
36088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
361c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
362c68cb64496485710cdb5b8480f8fee287058c93farmvixl
363c68cb64496485710cdb5b8480f8fee287058c93farmvixl
364c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid MacroAssembler::FinalizeCode() {
365c68cb64496485710cdb5b8480f8fee287058c93farmvixl  if (!literal_pool_.IsEmpty()) literal_pool_.Emit();
3665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(veneer_pool_.IsEmpty());
367c68cb64496485710cdb5b8480f8fee287058c93farmvixl
368c68cb64496485710cdb5b8480f8fee287058c93farmvixl  Assembler::FinalizeCode();
369c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
370c68cb64496485710cdb5b8480f8fee287058c93farmvixl
371c68cb64496485710cdb5b8480f8fee287058c93farmvixl
3725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::CheckEmitFor(size_t amount) {
3735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  ptrdiff_t offset = amount;
3745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
3755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  literal_pool_.CheckEmitFor(amount);
3765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.CheckEmitFor(amount);
3775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Ensure there's enough space for the emit, keep in mind the cursor will
3785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // have moved if a pool was emitted.
37988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((GetCursorOffset() + offset) > GetBufferEndOffset()) {
3805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    EnsureSpaceFor(amount);
3815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
3825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
38388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  checkpoint_ = GetNextCheckPoint();
3845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
3855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
3865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
387330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlint MacroAssembler::MoveImmediateHelper(MacroAssembler* masm,
3880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                        const Register& rd,
389330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl                                        uint64_t imm) {
390330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  bool emit_code = (masm != NULL);
39188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint32(imm) || IsInt32(imm) || rd.Is64Bits());
392330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The worst case for size is mov 64-bit immediate to sp:
393330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  * up to 4 instructions to materialise the constant
394330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  * 1 instruction to move to sp
395330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MacroEmissionCheckScope guard(masm);
396330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
397330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Immediates on Aarch64 can be produced using an initial value, and zero to
398330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // three move keep operations.
399330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //
400330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Initial values can be generated with:
401330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  1. 64-bit move zero (movz).
402330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  2. 32-bit move inverted (movn).
403330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  3. 64-bit move inverted.
404330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  4. 32-bit orr immediate.
405330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //  5. 64-bit orr immediate.
406330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Move-keep may then be used to modify each of the 16-bit half words.
407330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  //
408330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The code below supports all five initial value generators, and
409330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // applying move-keep operations to move-zero and move-inverted initial
410330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // values.
411330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
412330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Try to move the immediate in one instruction, and if that fails, switch to
413330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // using multiple instructions.
414330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (OneInstrMoveImmediateHelper(masm, rd, imm)) {
415330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return 1;
416330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else {
417330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    int instruction_count = 0;
41888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    unsigned reg_size = rd.GetSizeInBits();
419330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
420330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Generic immediate case. Imm will be represented by
421330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    //   [imm3, imm2, imm1, imm0], where each imm is 16 bits.
422330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // A move-zero or move-inverted is generated for the first non-zero or
423330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // non-0xffff immX, and a move-keep for subsequent non-zero immX.
424330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
425330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    uint64_t ignored_halfword = 0;
426330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    bool invert_move = false;
427330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // If the number of 0xffff halfwords is greater than the number of 0x0000
428330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // halfwords, it's more efficient to use move-inverted.
429330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (CountClearHalfWords(~imm, reg_size) >
430330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        CountClearHalfWords(imm, reg_size)) {
431330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      ignored_halfword = 0xffff;
432330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      invert_move = true;
433330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
434330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
435330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Mov instructions can't move values into the stack pointer, so set up a
436330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // temporary register, if needed.
437330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    UseScratchRegisterScope temps;
438330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    Register temp;
439330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
440330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      temps.Open(masm);
441330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      temp = rd.IsSP() ? temps.AcquireSameSizeAs(rd) : rd;
442330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
443330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
444330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Iterate through the halfwords. Use movn/movz for the first non-ignored
445330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // halfword, and movk for subsequent halfwords.
446330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    VIXL_ASSERT((reg_size % 16) == 0);
447330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    bool first_mov_done = false;
4480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    for (unsigned i = 0; i < (reg_size / 16); i++) {
449330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      uint64_t imm16 = (imm >> (16 * i)) & 0xffff;
450330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      if (imm16 != ignored_halfword) {
451330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        if (!first_mov_done) {
452330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          if (invert_move) {
453330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            if (emit_code) masm->movn(temp, ~imm16 & 0xffff, 16 * i);
454330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            instruction_count++;
455330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          } else {
456330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            if (emit_code) masm->movz(temp, imm16, 16 * i);
457330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl            instruction_count++;
458330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          }
459330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          first_mov_done = true;
460330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        } else {
461330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          // Construct a wider constant.
462330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          if (emit_code) masm->movk(temp, imm16, 16 * i);
463330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl          instruction_count++;
464330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl        }
465330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      }
466330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
467330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
468330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    VIXL_ASSERT(first_mov_done);
469330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
470330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Move the temporary if the original destination register was the stack
471330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // pointer.
472330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (rd.IsSP()) {
473330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      if (emit_code) masm->mov(rd, temp);
474330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      instruction_count++;
475330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
476330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return instruction_count;
477330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
478330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
479330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
480330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
481330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlbool MacroAssembler::OneInstrMoveImmediateHelper(MacroAssembler* masm,
482330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl                                                 const Register& dst,
483330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl                                                 int64_t imm) {
484330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  bool emit_code = masm != NULL;
485330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  unsigned n, imm_s, imm_r;
48688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = dst.GetSizeInBits();
487330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
488330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (IsImmMovz(imm, reg_size) && !dst.IsSP()) {
489330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate can be represented in a move zero instruction. Movz can't write
490330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // to the stack pointer.
491330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
492330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      masm->movz(dst, imm);
493330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
494330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return true;
495330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else if (IsImmMovn(imm, reg_size) && !dst.IsSP()) {
496330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate can be represented in a move negative instruction. Movn can't
497330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // write to the stack pointer.
498330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
499330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl      masm->movn(dst, dst.Is64Bits() ? ~imm : (~imm & kWRegMask));
500330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
501330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return true;
502330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else if (IsImmLogical(imm, reg_size, &n, &imm_s, &imm_r)) {
503330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate can be represented in a logical orr instruction.
504330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    VIXL_ASSERT(!dst.IsZero());
505330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    if (emit_code) {
5060f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->LogicalImmediate(dst,
5070f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             AppropriateZeroRegFor(dst),
5080f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             n,
5090f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             imm_s,
5100f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             imm_r,
5110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             ORR);
512330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    }
513330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    return true;
514330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
515330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  return false;
516330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
517330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
518330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
519b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid MacroAssembler::B(Label* label, BranchType type, Register reg, int bit) {
520b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((reg.Is(NoReg) || (type >= kBranchTypeFirstUsingReg)) &&
521b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl              ((bit == -1) || (type >= kBranchTypeFirstUsingBit)));
522b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (kBranchTypeFirstCondition <= type && type <= kBranchTypeLastCondition) {
523b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    B(static_cast<Condition>(type), label);
524b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
525b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    switch (type) {
5260f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case always:
5270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        B(label);
5280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case never:
5300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_zero:
5320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Cbz(reg, label);
5330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_not_zero:
5350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Cbnz(reg, label);
5360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_bit_clear:
5380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Tbz(reg, bit, label);
5390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
5400f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      case reg_bit_set:
5410f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        Tbnz(reg, bit, label);
5420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        break;
543b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      default:
544b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl        VIXL_UNREACHABLE();
545b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    }
546b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
547b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
548b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
5495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::B(Label* label) {
5515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  SingleEmissionCheckScope guard(this);
5525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  b(label);
5535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
5545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::B(Label* label, Condition cond) {
5575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
5585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
5595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
5605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) {
5625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
5635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(&done, InvertCondition(cond));
5645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
5655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
5665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
5675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
56888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
5695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
5705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            CondBranchType);
5715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
5725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label, cond);
5735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
5745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
5755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Cbnz(const Register& rt, Label* label) {
5785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
5795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
5805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
5815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) {
5835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
5845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbz(rt, &done);
5855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
5865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
5875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
5885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
58988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
5905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
5915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            CompareBranchType);
5925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
5935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbnz(rt, label);
5945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
5955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
5965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
5985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Cbz(const Register& rt, Label* label) {
5995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) {
6045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbnz(rt, &done);
6065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
61088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            CompareBranchType);
6135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    cbz(rt, label);
6155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Tbnz(const Register& rt, unsigned bit_pos, Label* label) {
6205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, TestBranchType)) {
6255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbz(rt, bit_pos, &done);
6275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
63188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            TestBranchType);
6345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbnz(rt, bit_pos, label);
6365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Tbz(const Register& rt, unsigned bit_pos, Label* label) {
6415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(!rt.IsZero());
6435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  EmissionCheckScope guard(this, 2 * kInstructionSize);
6445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (label->IsBound() && LabelIsOutOfRange(label, TestBranchType)) {
6465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Label done;
6475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbnz(rt, bit_pos, &done);
6485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    b(label);
6495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bind(&done);
6505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
6515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (!label->IsBound()) {
65288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      veneer_pool_.RegisterUnresolvedBranch(GetCursorOffset(),
6535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            label,
6545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                            TestBranchType);
6555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
6565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    tbz(rt, bit_pos, label);
6575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
6585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Bind(Label* label) {
6625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.DeleteUnresolvedBranchInfoForLabel(label);
6645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  bind(label);
6655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// Bind a label to a specified offset from the start of the buffer.
6695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::BindToOffset(Label* label, ptrdiff_t offset) {
6705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
6715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  veneer_pool_.DeleteUnresolvedBranchInfoForLabel(label);
6725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Assembler::BindToOffset(label, offset);
6735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
6745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
6755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
676ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::And(const Register& rd,
677ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
678f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
679b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
680f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, AND);
681f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
682f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
683f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
684f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Ands(const Register& rd,
685f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
686f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
687b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
688f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, ANDS);
689ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
690ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
691ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
6920f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Tst(const Register& rn, const Operand& operand) {
693b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
694f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Ands(AppropriateZeroRegFor(rn), rn, operand);
695ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
696ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
697ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
698ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Bic(const Register& rd,
699ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
700f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
701b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
702f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, BIC);
703f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
704f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
705f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
706f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Bics(const Register& rd,
707f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
708f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
709b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
710f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  LogicalMacro(rd, rn, operand, BICS);
711ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
712ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
713ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
714ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Orr(const Register& rd,
715ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
716ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
717b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
718ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, ORR);
719ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
720ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
721ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
722ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Orn(const Register& rd,
723ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
724ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
725b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
726ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, ORN);
727ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
728ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
729ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
730ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Eor(const Register& rd,
731ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
732ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
733b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
734ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, EOR);
735ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
736ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
737ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
738ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Eon(const Register& rd,
739ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
740ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Operand& operand) {
741b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
742ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  LogicalMacro(rd, rn, operand, EON);
743ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
744ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
745ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
746ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::LogicalMacro(const Register& rd,
747ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  const Register& rn,
748ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  const Operand& operand,
749ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                  LogicalOp op) {
750c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is logical immediate to sp:
751c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
752c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to do the operation
753c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to move to sp
754c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
755b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
756b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
757ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
75888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t immediate = operand.GetImmediate();
75988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    unsigned reg_size = rd.GetSizeInBits();
760ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
761ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the operation is NOT, invert the operation and immediate.
762ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if ((op & NOT) == NOT) {
763ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      op = static_cast<LogicalOp>(op & ~NOT);
764ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      immediate = ~immediate;
765ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
766ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
7674a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Ignore the top 32 bits of an immediate if we're moving to a W register.
7684a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (rd.Is32Bits()) {
7694a102baf640077d6794c0b33bb976f94b86c532barmvixl      // Check that the top 32 bits are consistent.
7704a102baf640077d6794c0b33bb976f94b86c532barmvixl      VIXL_ASSERT(((immediate >> kWRegSize) == 0) ||
7714a102baf640077d6794c0b33bb976f94b86c532barmvixl                  ((immediate >> kWRegSize) == -1));
7724a102baf640077d6794c0b33bb976f94b86c532barmvixl      immediate &= kWRegMask;
7734a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
7744a102baf640077d6794c0b33bb976f94b86c532barmvixl
77588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(rd.Is64Bits() || IsUint32(immediate));
7764a102baf640077d6794c0b33bb976f94b86c532barmvixl
777ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Special cases for all set or all clear immediates.
778ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (immediate == 0) {
779ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (op) {
780ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case AND:
781ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, 0);
782ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
7836e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        case ORR:
7846e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl          VIXL_FALLTHROUGH();
785ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case EOR:
786ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, rn);
787ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
7886e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        case ANDS:
7896e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl          VIXL_FALLTHROUGH();
790ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case BICS:
791ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
792ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        default:
793b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl          VIXL_UNREACHABLE();
794ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
795b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else if ((rd.Is64Bits() && (immediate == -1)) ||
796b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl               (rd.Is32Bits() && (immediate == 0xffffffff))) {
797ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      switch (op) {
798ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case AND:
799ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, rn);
800ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
801ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case ORR:
802ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mov(rd, immediate);
803ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
804ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case EOR:
805ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          Mvn(rd, rn);
806ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          return;
8076e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        case ANDS:
8086e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl          VIXL_FALLTHROUGH();
809ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        case BICS:
810ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl          break;
811ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        default:
812b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl          VIXL_UNREACHABLE();
813ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
814ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
815ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
816ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    unsigned n, imm_s, imm_r;
817ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) {
818ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Immediate can be encoded in the instruction.
819ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      LogicalImmediate(rd, rn, n, imm_s, imm_r, op);
820ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
821ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Immediate can't be encoded: synthesize using move immediate.
822b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      Register temp = temps.AcquireSameSizeAs(rn);
8234a102baf640077d6794c0b33bb976f94b86c532barmvixl      Operand imm_operand = MoveImmediateForShiftedOp(temp, immediate);
8244a102baf640077d6794c0b33bb976f94b86c532barmvixl
825ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      if (rd.Is(sp)) {
826ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // If rd is the stack pointer we cannot use it as the destination
827ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        // register so we use the temp register as an intermediate again.
8284a102baf640077d6794c0b33bb976f94b86c532barmvixl        Logical(temp, rn, imm_operand, op);
829ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl        Mov(sp, temp);
830ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      } else {
8314a102baf640077d6794c0b33bb976f94b86c532barmvixl        Logical(rd, rn, imm_operand, op);
832ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      }
833ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
834ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
83588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() <= rd.GetSizeInBits());
836ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub extended supports shift <= 4. We want to support exactly the
837ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // same modes here.
83888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShiftAmount() <= 4);
83988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
84088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        operand.GetRegister().Is64Bits() ||
84188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        ((operand.GetExtend() != UXTX) && (operand.GetExtend() != SXTX)));
842b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
84388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
844b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
8450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
84688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
84788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
84888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
849ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Logical(rd, rn, Operand(temp), op);
850ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
851ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The operand can be encoded in the instruction.
852b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT(operand.IsShiftedRegister());
853ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Logical(rd, rn, operand, op);
854ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
855ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
856ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
857ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
858f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Mov(const Register& rd,
859f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand,
860f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         DiscardMoveMode discard_mode) {
861b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
862c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is mov immediate with up to 4 instructions.
863c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
864c68cb64496485710cdb5b8480f8fee287058c93farmvixl
865ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
866ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Call the macro assembler for generic immediates.
86788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(rd, operand.GetImmediate());
86888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } else if (operand.IsShiftedRegister() && (operand.GetShiftAmount() != 0)) {
869ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit a shift instruction if moving a shifted register. This operation
870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // could also be achieved using an orr instruction (like orn used by Mvn),
871ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // but using a shift instruction makes the disassembly clearer.
87288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    EmitShift(rd,
87388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetRegister(),
87488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShift(),
87588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShiftAmount());
876ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
877ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit an extend instruction if moving an extended register. This handles
878ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // extend with post-shift operations, too.
8790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(rd,
88088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
88188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
88288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
883ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
884ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Otherwise, emit a register move only if the registers are distinct, or
885f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // if they are not X registers.
886f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    //
887f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // Note that mov(w0, w0) is not a no-op because it clears the top word of
888f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // x0. A flag is provided (kDiscardForSameWReg) if a move between the same W
889f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // registers is not required to clear the top word of the X register. In
890f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // this case, the instruction is discarded.
891f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    //
892ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the sp is an operand, add #0 is emitted, otherwise, orr #0.
89388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (!rd.Is(operand.GetRegister()) ||
8940f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl        (rd.Is32Bits() && (discard_mode == kDontDiscardForSameWReg))) {
89588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      mov(rd, operand.GetRegister());
896ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
897ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
898ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
899ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
900ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
9015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi16bitHelper(const VRegister& vd, uint64_t imm) {
90288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint16(imm));
9035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  int byte1 = (imm & 0xff);
9045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  int byte2 = ((imm >> 8) & 0xff);
9055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (byte1 == byte2) {
9065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd.Is64Bits() ? vd.V8B() : vd.V16B(), byte1);
9075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte1 == 0) {
9085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, byte2, LSL, 8);
9095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte2 == 0) {
9105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, byte1);
9115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte1 == 0xff) {
9125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~byte2 & 0xff, LSL, 8);
9135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (byte2 == 0xff) {
9145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~byte1 & 0xff);
9155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
9165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
9175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireW();
9185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movz(temp, imm);
9195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    dup(vd, temp);
9205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
9225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi32bitHelper(const VRegister& vd, uint64_t imm) {
92588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(IsUint32(imm));
9265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  uint8_t bytes[sizeof(imm)];
9285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  memcpy(bytes, &imm, sizeof(imm));
9295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // All bytes are either 0x00 or 0xff.
9315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
9325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bool all0orff = true;
9335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (int i = 0; i < 4; ++i) {
9345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if ((bytes[i] != 0) && (bytes[i] != 0xff)) {
9355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        all0orff = false;
9365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        break;
9375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
9385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
9395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (all0orff == true) {
9415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd.Is64Bits() ? vd.V1D() : vd.V2D(), ((imm << 32) | imm));
9425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
9435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
9445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Of the 4 bytes, only one byte is non-zero.
9475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (int i = 0; i < 4; i++) {
9485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if ((imm & (0xff << (i * 8))) == imm) {
9495289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd, bytes[i], LSL, i * 8);
9505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
9515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
9525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Of the 4 bytes, only one byte is not 0xff.
9555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  for (int i = 0; i < 4; i++) {
9565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    uint32_t mask = ~(0xff << (i * 8));
9575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if ((imm & mask) == mask) {
9585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      mvni(vd, ~bytes[i] & 0xff, LSL, i * 8);
9595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
9605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
9615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0x00MMFFFF.
9645289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xff00ffff) == 0x0000ffff) {
9655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, bytes[2], MSL, 16);
9665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
9675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0x0000MMFF.
9705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xffff00ff) == 0x000000ff) {
9715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, bytes[1], MSL, 8);
9725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
9735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0xFFMM0000.
9765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xff00ffff) == 0xff000000) {
9775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~bytes[2] & 0xff, MSL, 16);
9785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
9795289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Immediate is of the form 0xFFFFMM00.
9815289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if ((imm & 0xffff00ff) == 0xffff0000) {
9825289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    mvni(vd, ~bytes[1] & 0xff, MSL, 8);
9835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
9845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Top and bottom 16-bits are equal.
9875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (((imm >> 16) & 0xffff) == (imm & 0xffff)) {
9885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi16bitHelper(vd.Is64Bits() ? vd.V4H() : vd.V8H(), imm & 0xffff);
9895289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
9905289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
9925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Default case.
9935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
9945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
9955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireW();
9965289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Mov(temp, imm);
9975289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    dup(vd, temp);
9985289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
9995289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
10005289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10015289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10025289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi64bitHelper(const VRegister& vd, uint64_t imm) {
10035289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // All bytes are either 0x00 or 0xff.
10045289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10055289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    bool all0orff = true;
10065289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    for (int i = 0; i < 8; ++i) {
10075289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      int byteval = (imm >> (i * 8)) & 0xff;
10085289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (byteval != 0 && byteval != 0xff) {
10095289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        all0orff = false;
10105289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        break;
10115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
10125289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10135289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (all0orff == true) {
10145289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      movi(vd, imm);
10155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      return;
10165289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10185289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10195289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Top and bottom 32-bits are equal.
10205289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (((imm >> 32) & 0xffffffff) == (imm & 0xffffffff)) {
10215289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi32bitHelper(vd.Is64Bits() ? vd.V2S() : vd.V4S(), imm & 0xffffffff);
10225289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    return;
10235289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10245289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10255289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // Default case.
10265289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  {
10275289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    UseScratchRegisterScope temps(this);
10285289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Register temp = temps.AcquireX();
10295289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Mov(temp, imm);
10305289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.Is1D()) {
10315289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      mov(vd.D(), 0, temp);
10325289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
10335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      dup(vd.V2D(), temp);
10345289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
10355289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
10375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10395289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Movi(const VRegister& vd,
10405289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          uint64_t imm,
10415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          Shift shift,
10425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                          int shift_amount) {
10435289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(allow_macro_instructions_);
10445289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  MacroEmissionCheckScope guard(this);
10455289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (shift_amount != 0 || shift != LSL) {
10465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, imm, shift, shift_amount);
10475289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is8B() || vd.Is16B()) {
10485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 8-bit immediate.
104988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(IsUint8(imm));
10505289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    movi(vd, imm);
10515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is4H() || vd.Is8H()) {
10525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 16-bit immediate.
10535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi16bitHelper(vd, imm);
10545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else if (vd.Is2S() || vd.Is4S()) {
10555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 32-bit immediate.
10565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi32bitHelper(vd, imm);
10575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
10585289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    // 64-bit immediate.
10595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Movi64bitHelper(vd, imm);
10605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
10615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
10625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Movi(const VRegister& vd, uint64_t hi, uint64_t lo) {
10655289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // TODO: Move 128-bit values in a more efficient way.
10665289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is128Bits());
10675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  UseScratchRegisterScope temps(this);
10685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Movi(vd.V2D(), lo);
10695289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Register temp = temps.AcquireX();
10705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Mov(temp, hi);
10715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  Ins(vd.V2D(), 1, temp);
10725289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
10735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
10745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1075ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mvn(const Register& rd, const Operand& operand) {
1076b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1077c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is mvn immediate with up to 4 instructions.
1078c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1079c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1080ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
1081ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Call the macro assembler for generic immediates.
108288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mvn(rd, operand.GetImmediate());
1083ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
1084b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
108588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1086b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1087ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Emit two instructions for the extend case. This differs from Mov, as
1088ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the extend and invert can't be achieved in one instruction.
1089b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rd);
10900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
109188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
109288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
109388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
1094ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, Operand(temp));
1095ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1096ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Otherwise, register and shifted register cases can be handled by the
1097ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // assembler directly, using orn.
1098ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    mvn(rd, operand);
1099ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1100ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1101ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1102ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Mov(const Register& rd, uint64_t imm) {
1104b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1105330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MoveImmediateHelper(this, rd, imm);
1106ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmp(const Register& rn,
1110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
1111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
1112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
1113b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
111488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0)) {
111588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ConditionalCompareMacro(rn, -operand.GetImmediate(), nzcv, cond, CCMN);
1116f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
1117f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMP);
1118f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1119ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1120ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1121ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1122ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Ccmn(const Register& rn,
1123ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          const Operand& operand,
1124ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          StatusFlags nzcv,
1125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                          Condition cond) {
1126b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
112788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0)) {
112888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ConditionalCompareMacro(rn, -operand.GetImmediate(), nzcv, cond, CCMP);
1129f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
1130f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompareMacro(rn, operand, nzcv, cond, CCMN);
1131f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::ConditionalCompareMacro(const Register& rn,
1136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             const Operand& operand,
1137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             StatusFlags nzcv,
1138ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             Condition cond,
1139ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                             ConditionalCompareOp op) {
1140b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
1141c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is ccmp immediate:
1142c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1143c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ccmp
1144c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1145c68cb64496485710cdb5b8480f8fee287058c93farmvixl
114688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((operand.IsShiftedRegister() && (operand.GetShiftAmount() == 0)) ||
114788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsImmediate() &&
114888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois       IsImmConditionalCompare(operand.GetImmediate()))) {
1149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The immediate can be encoded in the instruction, or the operand is an
1150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // unshifted register: call the assembler.
1151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    ConditionalCompare(rn, operand, nzcv, cond, op);
1152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1153b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1154ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The operand isn't directly supported by the instruction: perform the
1155ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // operation on a temporary register.
1156b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
1157f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Mov(temp, operand);
1158f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    ConditionalCompare(rn, temp, nzcv, cond, op);
1159f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1160f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1161f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1162f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
11630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::CselHelper(MacroAssembler* masm,
11640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                const Register& rd,
11650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Operand left,
11660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Operand right,
11670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                Condition cond,
11680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                bool* should_synthesise_left,
11690f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                bool* should_synthesise_right) {
11700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
11710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
11720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(!emit_code || masm->allow_macro_instructions_);
1173b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT((cond != al) && (cond != nv));
11740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(!rd.IsZero() && !rd.IsSP());
117588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(left.IsImmediate() || !left.GetRegister().IsSP());
117688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(right.IsImmediate() || !right.GetRegister().IsSP());
11770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
11780f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_left != NULL) *should_synthesise_left = false;
11790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_right != NULL) *should_synthesise_right = false;
11800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
11810f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // The worst case for size occurs when the inputs are two non encodable
11820f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // constants:
11830f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  //  * up to 4 instructions to materialise the left constant
11840f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  //  * up to 4 instructions to materialise the right constant
1185c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for csel
11860f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  EmissionCheckScope guard(masm, 9 * kInstructionSize);
11870f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  UseScratchRegisterScope temps;
11880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (masm != NULL) {
11890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    temps.Open(masm);
11900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
11910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
11920f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Try to handle cases where both inputs are immediates.
11930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool left_is_immediate = left.IsImmediate() || left.IsZero();
11940f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool right_is_immediate = right.IsImmediate() || right.IsZero();
11950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left_is_immediate && right_is_immediate &&
11960f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      CselSubHelperTwoImmediates(masm,
11970f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 rd,
11980f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 left.GetEquivalentImmediate(),
11990f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 right.GetEquivalentImmediate(),
12000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 cond,
12010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 should_synthesise_left,
12020f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 should_synthesise_right)) {
12030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
12040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1205c68cb64496485710cdb5b8480f8fee287058c93farmvixl
12060f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Handle cases where one of the two inputs is -1, 0, or 1.
12070f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool left_is_small_immediate =
12080f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left_is_immediate && ((-1 <= left.GetEquivalentImmediate()) &&
12090f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                            (left.GetEquivalentImmediate() <= 1));
12100f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool right_is_small_immediate =
12110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      right_is_immediate && ((-1 <= right.GetEquivalentImmediate()) &&
12120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             (right.GetEquivalentImmediate() <= 1));
12130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (right_is_small_immediate || left_is_small_immediate) {
12140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    bool swapped_inputs = false;
12150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (!right_is_small_immediate) {
12160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      std::swap(left, right);
12170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      cond = InvertCondition(cond);
12180f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      swapped_inputs = true;
12190f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12200f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    CselSubHelperRightSmallImmediate(masm,
12210f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     &temps,
12220f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     rd,
12230f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     left,
12240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     right,
12250f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     cond,
12260f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                     swapped_inputs ? should_synthesise_right
12270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                    : should_synthesise_left);
12280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return;
12290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // Otherwise both inputs need to be available in registers. Synthesise them
12320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // if necessary and emit the `csel`.
12330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (!left.IsPlainRegister()) {
12340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
12350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Register temp = temps.AcquireSameSizeAs(rd);
12360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(temp, left);
12370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left = temp;
12380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_left != NULL) *should_synthesise_left = true;
12400f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12410f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (!right.IsPlainRegister()) {
12420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
12430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Register temp = temps.AcquireSameSizeAs(rd);
12440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(temp, right);
12450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      right = temp;
12460f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_right != NULL) *should_synthesise_right = true;
12480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (emit_code) {
12500f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(left.IsPlainRegister() && right.IsPlainRegister());
125188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if (left.GetRegister().Is(right.GetRegister())) {
125288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      masm->Mov(rd, left.GetRegister());
12530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    } else {
125488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      masm->csel(rd, left.GetRegister(), right.GetRegister(), cond);
12550f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12570f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
12580f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12590f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12600f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlbool MacroAssembler::CselSubHelperTwoImmediates(MacroAssembler* masm,
12610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                const Register& rd,
12620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                int64_t left,
12630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                int64_t right,
12640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                Condition cond,
12650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                bool* should_synthesise_left,
12660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                bool* should_synthesise_right) {
12670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
12680f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_left != NULL) *should_synthesise_left = false;
12690f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (should_synthesise_right != NULL) *should_synthesise_right = false;
12700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left == right) {
12720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) masm->Mov(rd, left);
12730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
12740f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else if (left == -right) {
12750f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_right != NULL) *should_synthesise_right = true;
12760f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
12770f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(rd, right);
12780f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Cneg(rd, rd, cond);
12790f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12800f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
12810f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12820f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12830f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (CselSubHelperTwoOrderedImmediates(masm, rd, left, right, cond)) {
12840f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
12850f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else {
12860f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    std::swap(left, right);
12870f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (CselSubHelperTwoOrderedImmediates(masm,
12880f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          rd,
12890f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          left,
12900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          right,
12910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                          InvertCondition(cond))) {
12920f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      return true;
12930f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
12940f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
12950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
12960f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // TODO: Handle more situations. For example handle `csel rd, #5, #6, cond`
12970f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  // with `cinc`.
12980f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  return false;
12990f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13020f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlbool MacroAssembler::CselSubHelperTwoOrderedImmediates(MacroAssembler* masm,
13030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       const Register& rd,
13040f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       int64_t left,
13050f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       int64_t right,
13060f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                                       Condition cond) {
13070f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13080f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
1309dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames  if ((left == 1) && (right == 0)) {
13100f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) masm->cset(rd, cond);
13110f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
1312dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames  } else if ((left == -1) && (right == 0)) {
1313dd47fed5e4cd380a8a5a3dd4ab80d8531a5e7c93Alexandre Rames    if (emit_code) masm->csetm(rd, cond);
13140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    return true;
13150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  return false;
13170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl}
13180f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13190f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13200f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::CselSubHelperRightSmallImmediate(
13210f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    MacroAssembler* masm,
13220f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    UseScratchRegisterScope* temps,
13230f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Register& rd,
13240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Operand& left,
13250f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    const Operand& right,
13260f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    Condition cond,
13270f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    bool* should_synthesise_left) {
13280f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  bool emit_code = (masm != NULL);
13290f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT((right.IsImmediate() || right.IsZero()) &&
13300f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl              (-1 <= right.GetEquivalentImmediate()) &&
13310f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl              (right.GetEquivalentImmediate() <= 1));
13320f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  Register left_register;
13330f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl
13340f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (left.IsPlainRegister()) {
133588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    left_register = left.GetRegister();
13360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  } else {
13370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (emit_code) {
13380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      left_register = temps->AcquireSameSizeAs(rd);
13390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->Mov(left_register, left);
13400f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    }
13410f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    if (should_synthesise_left != NULL) *should_synthesise_left = true;
13420f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
13430f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  if (emit_code) {
13440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    int64_t imm = right.GetEquivalentImmediate();
13450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    Register zr = AppropriateZeroRegFor(rd);
1346f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    if (imm == 0) {
13470f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csel(rd, left_register, zr, cond);
1348f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    } else if (imm == 1) {
13490f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csinc(rd, left_register, zr, cond);
1350ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
13510f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      VIXL_ASSERT(imm == -1);
13520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      masm->csinv(rd, left_register, zr, cond);
1353ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
1354ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1355ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1356ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1357ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1358ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Add(const Register& rd,
1359ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
13606e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         const Operand& operand,
13616e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         FlagsUpdate S) {
1362b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
136388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0) &&
136488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      IsImmAddSub(-operand.GetImmediate())) {
136588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    AddSubMacro(rd, rn, -operand.GetImmediate(), S, SUB);
1366ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
13676e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    AddSubMacro(rd, rn, operand, S, ADD);
1368f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1369f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1370f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1371f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1372f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adds(const Register& rd,
1373f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1374f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
13756e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Add(rd, rn, operand, SetFlags);
1376ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1377ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1378ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1379ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sub(const Register& rd,
1380ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
13816e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         const Operand& operand,
13826e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                         FlagsUpdate S) {
1383b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
138488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (operand.IsImmediate() && (operand.GetImmediate() < 0) &&
138588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      IsImmAddSub(-operand.GetImmediate())) {
138688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    AddSubMacro(rd, rn, -operand.GetImmediate(), S, ADD);
1387f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  } else {
13886e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    AddSubMacro(rd, rn, operand, S, SUB);
1389f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1390f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1391f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1392f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1393f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Subs(const Register& rd,
1394f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1395f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
13966e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Sub(rd, rn, operand, SetFlags);
1397ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1398ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1399ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1400ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmn(const Register& rn, const Operand& operand) {
1401b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1402f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Adds(AppropriateZeroRegFor(rn), rn, operand);
1403ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1404ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1406ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Cmp(const Register& rn, const Operand& operand) {
1407b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1408f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(AppropriateZeroRegFor(rn), rn, operand);
1409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1411ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
14120f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Fcmp(const FPRegister& fn,
14130f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          double value,
14146e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                          FPTrapFlags trap) {
1415b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1416c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // The worst case for size is:
1417c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 to materialise the constant, using literal pool if necessary
14186e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  //  * 1 instruction for fcmp{e}
1419c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1420b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (value != 0.0) {
1421b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1422b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    FPRegister tmp = temps.AcquireSameSizeAs(fn);
1423b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Fmov(tmp, value);
14246e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    FPCompareMacro(fn, tmp, trap);
1425b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
14266e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    FPCompareMacro(fn, value, trap);
1427b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1428b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1429b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1430b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
14316e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::Fcmpe(const FPRegister& fn, double value) {
14326e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  Fcmp(fn, value, EnableTrap);
14336e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
14346e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
14356e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
14365289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Fmov(VRegister vd, double imm) {
1437b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1438c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Floating point immediates are loaded through the literal pool.
1439c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1440c68cb64496485710cdb5b8480f8fee287058c93farmvixl
14415289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (vd.Is1S() || vd.Is2S() || vd.Is4S()) {
14425289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Fmov(vd, static_cast<float>(imm));
1443b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    return;
1444b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1445b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
14465289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is1D() || vd.Is2D());
1447b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (IsImmFP64(imm)) {
14485289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    fmov(vd, imm);
1449b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
145088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint64_t rawbits = DoubleToRawbits(imm);
14515289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.IsScalar()) {
14525289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (rawbits == 0) {
14535289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        fmov(vd, xzr);
14545289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      } else {
1455db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl        ldr(vd,
1456db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl            new Literal<double>(imm,
1457db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                                &literal_pool_,
1458db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                                RawLiteral::kDeletedOnPlacementByPool));
14595289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
14605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
14615289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // TODO: consider NEON support for load literal.
14625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Movi(vd, rawbits);
14635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
1464b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1465b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1466b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1467b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
14685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::Fmov(VRegister vd, float imm) {
1469b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1470c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Floating point immediates are loaded through the literal pool.
1471c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1472c68cb64496485710cdb5b8480f8fee287058c93farmvixl
14735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (vd.Is1D() || vd.Is2D()) {
14745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    Fmov(vd, static_cast<double>(imm));
1475b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    return;
1476b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1477b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
14785289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  VIXL_ASSERT(vd.Is1S() || vd.Is2S() || vd.Is4S());
1479b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (IsImmFP32(imm)) {
14805289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    fmov(vd, imm);
1481b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
148288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    uint32_t rawbits = FloatToRawbits(imm);
14835289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (vd.IsScalar()) {
14845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      if (rawbits == 0) {
14855289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl        fmov(vd, wzr);
14865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      } else {
1487db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl        ldr(vd,
1488db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl            new Literal<float>(imm,
1489db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                               &literal_pool_,
1490db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl                               RawLiteral::kDeletedOnPlacementByPool));
14915289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      }
14925289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
14935289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      // TODO: consider NEON support for load literal.
14945289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      Movi(vd, rawbits);
14955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
1496b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
1497b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
1498b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
1499b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
15000f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Neg(const Register& rd, const Operand& operand) {
1501b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1502ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate()) {
150388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(rd, -operand.GetImmediate());
1504ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1505f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    Sub(rd, AppropriateZeroRegFor(rd), operand);
1506ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1507ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1508ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1509ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
15100f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Negs(const Register& rd, const Operand& operand) {
1511b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1512f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Subs(rd, AppropriateZeroRegFor(rd), operand);
1513f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1514f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1515f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
15164a102baf640077d6794c0b33bb976f94b86c532barmvixlbool MacroAssembler::TryOneInstrMoveImmediate(const Register& dst,
15174a102baf640077d6794c0b33bb976f94b86c532barmvixl                                              int64_t imm) {
1518330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  return OneInstrMoveImmediateHelper(this, dst, imm);
15194a102baf640077d6794c0b33bb976f94b86c532barmvixl}
15204a102baf640077d6794c0b33bb976f94b86c532barmvixl
15214a102baf640077d6794c0b33bb976f94b86c532barmvixl
15224a102baf640077d6794c0b33bb976f94b86c532barmvixlOperand MacroAssembler::MoveImmediateForShiftedOp(const Register& dst,
15234a102baf640077d6794c0b33bb976f94b86c532barmvixl                                                  int64_t imm) {
152488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = dst.GetSizeInBits();
15254a102baf640077d6794c0b33bb976f94b86c532barmvixl
15264a102baf640077d6794c0b33bb976f94b86c532barmvixl  // Encode the immediate in a single move instruction, if possible.
15274a102baf640077d6794c0b33bb976f94b86c532barmvixl  if (TryOneInstrMoveImmediate(dst, imm)) {
15284a102baf640077d6794c0b33bb976f94b86c532barmvixl    // The move was successful; nothing to do here.
15294a102baf640077d6794c0b33bb976f94b86c532barmvixl  } else {
15304a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Pre-shift the immediate to the least-significant bits of the register.
15314a102baf640077d6794c0b33bb976f94b86c532barmvixl    int shift_low = CountTrailingZeros(imm, reg_size);
15324a102baf640077d6794c0b33bb976f94b86c532barmvixl    int64_t imm_low = imm >> shift_low;
15334a102baf640077d6794c0b33bb976f94b86c532barmvixl
15344a102baf640077d6794c0b33bb976f94b86c532barmvixl    // Pre-shift the immediate to the most-significant bits of the register,
15354a102baf640077d6794c0b33bb976f94b86c532barmvixl    // inserting set bits in the least-significant bits.
15364a102baf640077d6794c0b33bb976f94b86c532barmvixl    int shift_high = CountLeadingZeros(imm, reg_size);
15375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    int64_t imm_high = (imm << shift_high) | ((INT64_C(1) << shift_high) - 1);
15384a102baf640077d6794c0b33bb976f94b86c532barmvixl
15394a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (TryOneInstrMoveImmediate(dst, imm_low)) {
15404a102baf640077d6794c0b33bb976f94b86c532barmvixl      // The new immediate has been moved into the destination's low bits:
15414a102baf640077d6794c0b33bb976f94b86c532barmvixl      // return a new leftward-shifting operand.
15424a102baf640077d6794c0b33bb976f94b86c532barmvixl      return Operand(dst, LSL, shift_low);
15434a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else if (TryOneInstrMoveImmediate(dst, imm_high)) {
15444a102baf640077d6794c0b33bb976f94b86c532barmvixl      // The new immediate has been moved into the destination's high bits:
15454a102baf640077d6794c0b33bb976f94b86c532barmvixl      // return a new rightward-shifting operand.
15464a102baf640077d6794c0b33bb976f94b86c532barmvixl      return Operand(dst, LSR, shift_high);
15474a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else {
15484a102baf640077d6794c0b33bb976f94b86c532barmvixl      Mov(dst, imm);
15494a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
15504a102baf640077d6794c0b33bb976f94b86c532barmvixl  }
15514a102baf640077d6794c0b33bb976f94b86c532barmvixl  return Operand(dst);
15524a102baf640077d6794c0b33bb976f94b86c532barmvixl}
15534a102baf640077d6794c0b33bb976f94b86c532barmvixl
15544a102baf640077d6794c0b33bb976f94b86c532barmvixl
15555289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixlvoid MacroAssembler::ComputeAddress(const Register& dst,
15565289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl                                    const MemOperand& mem_op) {
15575289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  // We cannot handle pre-indexing or post-indexing.
155888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(mem_op.GetAddrMode() == Offset);
155988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  Register base = mem_op.GetBaseRegister();
15605289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (mem_op.IsImmediateOffset()) {
156188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(dst, base, mem_op.GetOffset());
15625289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  } else {
15635289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    VIXL_ASSERT(mem_op.IsRegisterOffset());
156488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register reg_offset = mem_op.GetRegisterOffset();
156588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Shift shift = mem_op.GetShift();
156688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Extend extend = mem_op.GetExtend();
15675289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    if (shift == NO_SHIFT) {
15685289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(extend != NO_EXTEND);
156988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Add(dst, base, Operand(reg_offset, extend, mem_op.GetShiftAmount()));
15705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else {
15715289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(extend == NO_EXTEND);
157288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      Add(dst, base, Operand(reg_offset, shift, mem_op.GetShiftAmount()));
15735289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    }
15745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  }
15755289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl}
15765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
15775289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
1578ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubMacro(const Register& rd,
1579ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Register& rn,
1580ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 const Operand& operand,
1581ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 FlagsUpdate S,
1582ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                 AddSubOp op) {
1583c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is add/sub immediate:
1584c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1585c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for add/sub
1586c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1587c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1588f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (operand.IsZero() && rd.Is(rn) && rd.Is64Bits() && rn.Is64Bits() &&
1589f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl      (S == LeaveFlags)) {
1590f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    // The instruction would be a nop. Avoid generating useless code.
1591f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
1592f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
1593f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
159488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if ((operand.IsImmediate() && !IsImmAddSub(operand.GetImmediate())) ||
15950f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      (rn.IsZero() && !operand.IsShiftedRegister()) ||
159688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsShiftedRegister() && (operand.GetShift() == ROR))) {
1597b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
1598b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
15994a102baf640077d6794c0b33bb976f94b86c532barmvixl    if (operand.IsImmediate()) {
16004a102baf640077d6794c0b33bb976f94b86c532barmvixl      Operand imm_operand =
160188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          MoveImmediateForShiftedOp(temp, operand.GetImmediate());
16024a102baf640077d6794c0b33bb976f94b86c532barmvixl      AddSub(rd, rn, imm_operand, S, op);
16034a102baf640077d6794c0b33bb976f94b86c532barmvixl    } else {
16044a102baf640077d6794c0b33bb976f94b86c532barmvixl      Mov(temp, operand);
16054a102baf640077d6794c0b33bb976f94b86c532barmvixl      AddSub(rd, rn, temp, S, op);
16064a102baf640077d6794c0b33bb976f94b86c532barmvixl    }
1607ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1608ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSub(rd, rn, operand, S, op);
1609ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1610ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1611ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1612ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1613ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Adc(const Register& rd,
1614ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
1615f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
1616b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1617f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, ADC);
1618f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1619f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1620f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1621f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Adcs(const Register& rd,
1622f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1623f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
1624b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1625f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, ADC);
1626ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1627ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1628ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1629ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Sbc(const Register& rd,
1630ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                         const Register& rn,
1631f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                         const Operand& operand) {
1632b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1633f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, LeaveFlags, SBC);
1634f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1635f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1636f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1637f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixlvoid MacroAssembler::Sbcs(const Register& rd,
1638f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Register& rn,
1639f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl                          const Operand& operand) {
1640b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1641f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  AddSubWithCarryMacro(rd, rn, operand, SetFlags, SBC);
1642ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1643ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1644ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
16450f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Ngc(const Register& rd, const Operand& operand) {
1646b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1647ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Register zr = AppropriateZeroRegFor(rd);
1648f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbc(rd, zr, operand);
1649f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl}
1650f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
1651f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
16520f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Ngcs(const Register& rd, const Operand& operand) {
1653b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1654f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Register zr = AppropriateZeroRegFor(rd);
1655f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  Sbcs(rd, zr, operand);
1656ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1657ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1658ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1659ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::AddSubWithCarryMacro(const Register& rd,
1660ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Register& rn,
1661ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          const Operand& operand,
1662ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          FlagsUpdate S,
1663ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                          AddSubWithCarryOp op) {
166488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(rd.GetSizeInBits() == rn.GetSizeInBits());
1665c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is addc/subc immediate:
1666c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1667c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for add/sub
1668c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1669b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
1670ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1671ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (operand.IsImmediate() ||
167288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      (operand.IsShiftedRegister() && (operand.GetShift() == ROR))) {
1673ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (immediate or ROR shifted register.)
1674b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
1675ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Mov(temp, operand);
1676ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
167788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  } else if (operand.IsShiftedRegister() && (operand.GetShiftAmount() != 0)) {
1678ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (shifted register).
167988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() == rd.GetSizeInBits());
168088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShift() != ROR);
168188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
168288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        IsUintN(rd.GetSizeInBits() == kXRegSize ? kXRegSizeLog2 : kWRegSizeLog2,
168388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                operand.GetShiftAmount()));
168488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1685b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
168688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    EmitShift(temp,
168788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetRegister(),
168888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShift(),
168988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              operand.GetShiftAmount());
1690ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
1691ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (operand.IsExtendedRegister()) {
1692ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub with carry (extended register).
169388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetRegister().GetSizeInBits() <= rd.GetSizeInBits());
1694ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Add/sub extended supports a shift <= 4. We want to support exactly the
1695ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // same modes.
169688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(operand.GetShiftAmount() <= 4);
169788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(
169888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        operand.GetRegister().Is64Bits() ||
169988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        ((operand.GetExtend() != UXTX) && (operand.GetExtend() != SXTX)));
170088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    temps.Exclude(operand.GetRegister());
1701b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register temp = temps.AcquireSameSizeAs(rn);
17020f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmitExtendShift(temp,
170388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetRegister(),
170488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetExtend(),
170588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                    operand.GetShiftAmount());
1706ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, Operand(temp), S, op);
1707ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1708ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // The addressing mode is directly supported by the instruction.
1709ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    AddSubWithCarry(rd, rn, operand, S, op);
1710ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1711ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1712ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1713ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
17140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl#define DEFINE_FUNCTION(FN, REGTYPE, REG, OP)                          \
17150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  void MacroAssembler::FN(const REGTYPE REG, const MemOperand& addr) { \
17160f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(allow_macro_instructions_);                            \
17170f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    LoadStoreMacro(REG, addr, OP);                                     \
17180f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1719ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlLS_MACRO_LIST(DEFINE_FUNCTION)
1720ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl#undef DEFINE_FUNCTION
1721ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1722330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1723ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::LoadStoreMacro(const CPURegister& rt,
1724ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    const MemOperand& addr,
1725ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                    LoadStoreOp op) {
1726c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is ldr/str pre/post index:
1727c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ldr/str
1728c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1729c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to update the base
1730c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1731c68cb64496485710cdb5b8480f8fee287058c93farmvixl
173288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t offset = addr.GetOffset();
17335289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned access_size = CalcLSDataSize(op);
1734ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1735ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Check if an immediate offset fits in the immediate field of the
1736ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // appropriate instruction. If not, emit two instructions to perform
1737ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the operation.
17385289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (addr.IsImmediateOffset() && !IsImmLSScaled(offset, access_size) &&
1739ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      !IsImmLSUnscaled(offset)) {
1740ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Immediate offset that can't be encoded using unsigned or unscaled
1741ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // addressing modes.
1742b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    UseScratchRegisterScope temps(this);
174388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register temp = temps.AcquireSameSizeAs(addr.GetBaseRegister());
174488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(temp, addr.GetOffset());
174588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister(), temp), op);
1746ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPostIndex() && !IsImmLSUnscaled(offset)) {
1747ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Post-index beyond unscaled addressing range.
174888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister()), op);
174988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(addr.GetBaseRegister(), addr.GetBaseRegister(), Operand(offset));
1750ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else if (addr.IsPreIndex() && !IsImmLSUnscaled(offset)) {
1751ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Pre-index beyond unscaled addressing range.
175288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Add(addr.GetBaseRegister(), addr.GetBaseRegister(), Operand(offset));
175388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    LoadStore(rt, MemOperand(addr.GetBaseRegister()), op);
1754ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
1755ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Encodable in one load/store instruction.
1756ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    LoadStore(rt, addr, op);
1757ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1758ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1759ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1760ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
17610f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl#define DEFINE_FUNCTION(FN, REGTYPE, REG, REG2, OP) \
17620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  void MacroAssembler::FN(const REGTYPE REG,        \
17630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const REGTYPE REG2,       \
17640f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const MemOperand& addr) { \
17650f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    VIXL_ASSERT(allow_macro_instructions_);         \
17660f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    LoadStorePairMacro(REG, REG2, addr, OP);        \
17670f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  }
1768c68cb64496485710cdb5b8480f8fee287058c93farmvixlLSPAIR_MACRO_LIST(DEFINE_FUNCTION)
1769c68cb64496485710cdb5b8480f8fee287058c93farmvixl#undef DEFINE_FUNCTION
1770c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1771c68cb64496485710cdb5b8480f8fee287058c93farmvixlvoid MacroAssembler::LoadStorePairMacro(const CPURegister& rt,
1772c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        const CPURegister& rt2,
1773c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        const MemOperand& addr,
1774c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                        LoadStorePairOp op) {
1775c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we support register offset for load-store-pair?
1776c68cb64496485710cdb5b8480f8fee287058c93farmvixl  VIXL_ASSERT(!addr.IsRegisterOffset());
1777c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case is ldp/stp immediate:
1778c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction for ldp/stp
1779c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * up to 4 instructions to materialise the constant
1780c68cb64496485710cdb5b8480f8fee287058c93farmvixl  //  * 1 instruction to update the base
1781c68cb64496485710cdb5b8480f8fee287058c93farmvixl  MacroEmissionCheckScope guard(this);
1782c68cb64496485710cdb5b8480f8fee287058c93farmvixl
178388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int64_t offset = addr.GetOffset();
17845289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned access_size = CalcLSPairDataSize(op);
1785c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1786c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Check if the offset fits in the immediate field of the appropriate
1787c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // instruction. If not, emit two instructions to perform the operation.
17885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  if (IsImmLSPair(offset, access_size)) {
1789c68cb64496485710cdb5b8480f8fee287058c93farmvixl    // Encodable in one load/store pair instruction.
1790c68cb64496485710cdb5b8480f8fee287058c93farmvixl    LoadStorePair(rt, rt2, addr, op);
1791c68cb64496485710cdb5b8480f8fee287058c93farmvixl  } else {
179288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register base = addr.GetBaseRegister();
1793c68cb64496485710cdb5b8480f8fee287058c93farmvixl    if (addr.IsImmediateOffset()) {
1794c68cb64496485710cdb5b8480f8fee287058c93farmvixl      UseScratchRegisterScope temps(this);
1795c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Register temp = temps.AcquireSameSizeAs(base);
1796c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(temp, base, offset);
1797c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(temp), op);
1798c68cb64496485710cdb5b8480f8fee287058c93farmvixl    } else if (addr.IsPostIndex()) {
1799c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(base), op);
1800c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(base, base, offset);
1801c68cb64496485710cdb5b8480f8fee287058c93farmvixl    } else {
1802c68cb64496485710cdb5b8480f8fee287058c93farmvixl      VIXL_ASSERT(addr.IsPreIndex());
1803c68cb64496485710cdb5b8480f8fee287058c93farmvixl      Add(base, base, offset);
1804c68cb64496485710cdb5b8480f8fee287058c93farmvixl      LoadStorePair(rt, rt2, MemOperand(base), op);
1805c68cb64496485710cdb5b8480f8fee287058c93farmvixl    }
1806c68cb64496485710cdb5b8480f8fee287058c93farmvixl  }
1807c68cb64496485710cdb5b8480f8fee287058c93farmvixl}
1808c68cb64496485710cdb5b8480f8fee287058c93farmvixl
1809330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1810330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid MacroAssembler::Prfm(PrefetchOperation op, const MemOperand& addr) {
1811330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  MacroEmissionCheckScope guard(this);
1812330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1813330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // There are no pre- or post-index modes for prfm.
1814330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(addr.IsImmediateOffset() || addr.IsRegisterOffset());
1815330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1816330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // The access size is implicitly 8 bytes for all prefetch operations.
18175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  unsigned size = kXRegSizeInBytesLog2;
1818330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1819330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // Check if an immediate offset fits in the immediate field of the
1820330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // appropriate instruction. If not, emit two instructions to perform
1821330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  // the operation.
182288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (addr.IsImmediateOffset() && !IsImmLSScaled(addr.GetOffset(), size) &&
182388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      !IsImmLSUnscaled(addr.GetOffset())) {
1824330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Immediate offset that can't be encoded using unsigned or unscaled
1825330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // addressing modes.
1826330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    UseScratchRegisterScope temps(this);
182788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Register temp = temps.AcquireSameSizeAs(addr.GetBaseRegister());
182888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Mov(temp, addr.GetOffset());
182988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    Prefetch(op, MemOperand(addr.GetBaseRegister(), temp));
1830330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  } else {
1831330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    // Simple register-offsets are encodable in one instruction.
1832330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    Prefetch(op, addr);
1833330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
1834330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
1835330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
1836330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
18370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Push(const CPURegister& src0,
18380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src1,
18390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src2,
18400f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                          const CPURegister& src3) {
1841b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1842b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
1843b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(src0.IsValid());
1844ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1845ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + src1.IsValid() + src2.IsValid() + src3.IsValid();
184688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = src0.GetSizeInBytes();
1847ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1848ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
1849ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushHelper(count, size, src0, src1, src2, src3);
1850ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1851ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1852ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
18530f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Pop(const CPURegister& dst0,
18540f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst1,
18550f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst2,
18560f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                         const CPURegister& dst3) {
1857ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // It is not valid to pop into the same register more than once in one
1858ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // instruction, not even into the zero register.
1859b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
1860b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(dst0, dst1, dst2, dst3));
1861b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
1862b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(dst0.IsValid());
1863ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1864ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  int count = 1 + dst1.IsValid() + dst2.IsValid() + dst3.IsValid();
186588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = dst0.GetSizeInBytes();
1866ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1867ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPop(count, size);
1868ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopHelper(count, size, dst0, dst1, dst2, dst3);
1869ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1870ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1871ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1872ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCPURegList(CPURegList registers) {
187388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchRegisterList()));
187488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchFPRegisterList()));
1875b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
18766e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
187788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = registers.GetRegisterSizeInBytes();
187888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  PrepareForPush(registers.GetCount(), reg_size);
18796e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
18806e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // Bump the stack pointer and store two registers at the bottom.
188188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = registers.GetTotalSizeInBytes();
18826e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_0 = registers.PopLowestIndex();
18836e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_1 = registers.PopLowestIndex();
18846e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (bottom_0.IsValid() && bottom_1.IsValid()) {
18856e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Stp(bottom_0, bottom_1, MemOperand(StackPointer(), -size, PreIndex));
18866e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (bottom_0.IsValid()) {
18876e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Str(bottom_0, MemOperand(StackPointer(), -size, PreIndex));
18886e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
18896e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
18906e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  int offset = 2 * reg_size;
1891ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
18926e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& src0 = registers.PopLowestIndex();
18936e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& src1 = registers.PopLowestIndex();
18946e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (src1.IsValid()) {
18956e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Stp(src0, src1, MemOperand(StackPointer(), offset));
18966e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
18976e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Str(src0, MemOperand(StackPointer(), offset));
18986e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
18996e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    offset += 2 * reg_size;
1900ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1901ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1902ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1903ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1904ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCPURegList(CPURegList registers) {
190588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchRegisterList()));
190688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(!registers.Overlaps(*GetScratchFPRegisterList()));
1907b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
19086e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
190988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int reg_size = registers.GetRegisterSizeInBytes();
191088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  PrepareForPop(registers.GetCount(), reg_size);
19116e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
19126e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
191388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = registers.GetTotalSizeInBytes();
19146e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_0 = registers.PopLowestIndex();
19156e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  const CPURegister& bottom_1 = registers.PopLowestIndex();
19166e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
19176e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  int offset = 2 * reg_size;
1918ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (!registers.IsEmpty()) {
1919ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst0 = registers.PopLowestIndex();
1920ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    const CPURegister& dst1 = registers.PopLowestIndex();
19216e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (dst1.IsValid()) {
19226e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldp(dst0, dst1, MemOperand(StackPointer(), offset));
19236e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
19246e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldr(dst0, MemOperand(StackPointer(), offset));
19256e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
19266e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    offset += 2 * reg_size;
19276e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
19286e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
19296e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // Load the two registers at the bottom and drop the stack pointer.
19306e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (bottom_0.IsValid() && bottom_1.IsValid()) {
19316e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Ldp(bottom_0, bottom_1, MemOperand(StackPointer(), size, PostIndex));
19326e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (bottom_0.IsValid()) {
19336e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Ldr(bottom_0, MemOperand(StackPointer(), size, PostIndex));
1934ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1935ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1936ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1937ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1938ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushMultipleTimes(int count, Register src) {
1939b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
194088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int size = src.GetSizeInBytes();
1941ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1942ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PrepareForPush(count, size);
1943ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push up to four registers at a time if possible because if the current
1944ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer is sp and the register size is 32, registers must be pushed
1945ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in blocks of four in order to maintain the 16-byte alignment for sp.
1946ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  while (count >= 4) {
1947ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(4, size, src, src, src, src);
1948ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 4;
1949ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1950ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count >= 2) {
1951ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(2, size, src, src, NoReg, NoReg);
1952ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 2;
1953ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1954ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (count == 1) {
1955ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    PushHelper(1, size, src, NoReg, NoReg, NoReg);
1956ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    count -= 1;
1957ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
1958b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(count == 0);
1959ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
1960ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1961ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
19620f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PushHelper(int count,
19630f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                int size,
1964ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src0,
1965ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src1,
1966ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src2,
1967ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                const CPURegister& src3) {
1968ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
1969c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case for size is 2 stp.
19700f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  InstructionAccurateScope scope(this,
19710f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2,
1972c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                 InstructionAccurateScope::kMaximumSize);
1973ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1974b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(src0, src1, src2, src3));
197588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(size == src0.GetSizeInBytes());
1976ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
1977ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When pushing multiple registers, the store order is chosen such that
1978ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Push(a, b) is equivalent to Push(a) followed by Push(b).
1979ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
1980ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
1981b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src1.IsNone() && src2.IsNone() && src3.IsNone());
1982ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), -1 * size, PreIndex));
1983ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1984ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
1985b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src2.IsNone() && src3.IsNone());
1986ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), -2 * size, PreIndex));
1987ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1988ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
1989b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(src3.IsNone());
1990ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src2, src1, MemOperand(StackPointer(), -3 * size, PreIndex));
1991ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      str(src0, MemOperand(StackPointer(), 2 * size));
1992ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
1993ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
1994ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Skip over 4 * size, then fill in the gap. This allows four W registers
1995ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be pushed using sp, whilst maintaining 16-byte alignment for sp at
1996ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
1997ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src3, src2, MemOperand(StackPointer(), -4 * size, PreIndex));
1998ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      stp(src1, src0, MemOperand(StackPointer(), 2 * size));
1999ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2000ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
2001b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_UNREACHABLE();
2002ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2003ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2004ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2005ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
20060f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PopHelper(int count,
20070f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                               int size,
2008ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst0,
2009ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst1,
2010ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst2,
2011ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                               const CPURegister& dst3) {
2012ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that we don't unintentionally modify scratch or debug registers.
2013c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // Worst case for size is 2 ldp.
20140f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  InstructionAccurateScope scope(this,
20150f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2,
2016c68cb64496485710cdb5b8480f8fee287058c93farmvixl                                 InstructionAccurateScope::kMaximumSize);
2017ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2018b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(AreSameSizeAndType(dst0, dst1, dst2, dst3));
201988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(size == dst0.GetSizeInBytes());
2020ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2021ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // When popping multiple registers, the load order is chosen such that
2022ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Pop(a, b) is equivalent to Pop(a) followed by Pop(b).
2023ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  switch (count) {
2024ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 1:
2025b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst1.IsNone() && dst2.IsNone() && dst3.IsNone());
2026ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst0, MemOperand(StackPointer(), 1 * size, PostIndex));
2027ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2028ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 2:
2029b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst2.IsNone() && dst3.IsNone());
2030ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 2 * size, PostIndex));
2031ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2032ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 3:
2033b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(dst3.IsNone());
2034ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldr(dst2, MemOperand(StackPointer(), 2 * size));
2035ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 3 * size, PostIndex));
2036ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2037ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    case 4:
2038ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // Load the higher addresses first, then load the lower addresses and skip
2039ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // the whole block in the second instruction. This allows four W registers
2040ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // to be popped using sp, whilst maintaining 16-byte alignment for sp at
2041ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      // all times.
2042ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst2, dst3, MemOperand(StackPointer(), 2 * size));
2043ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      ldp(dst0, dst1, MemOperand(StackPointer(), 4 * size, PostIndex));
2044ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2045ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    default:
2046b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_UNREACHABLE();
2047ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2048ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2049ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2050ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2051ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPush(int count, int size) {
2052ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
2053ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
2054ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
2055ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
2056b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT((count * size) % 16 == 0);
2057ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  } else {
2058ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // Even if the current stack pointer is not the system stack pointer (sp),
2059ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // the system stack pointer will still be modified in order to comply with
2060ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // ABI rules about accessing memory below the system stack pointer.
2061ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(count * size);
2062ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2063ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2064ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2065ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2066ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PrepareForPop(int count, int size) {
2067db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  USE(count, size);
2068ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (sp.Is(StackPointer())) {
2069ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // If the current stack pointer is sp, then it must be aligned to 16 bytes
2070ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // on entry and the total size of the specified registers must also be a
2071ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    // multiple of 16 bytes.
2072b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT((count * size) % 16 == 0);
2073ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2074ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2075ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2076ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Poke(const Register& src, const Operand& offset) {
2077b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2078ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
207988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(offset.GetImmediate() >= 0);
2080ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2081ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2082ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Str(src, MemOperand(StackPointer(), offset));
2083ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2084ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2085ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2086ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Peek(const Register& dst, const Operand& offset) {
2087b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2088ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (offset.IsImmediate()) {
208988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(offset.GetImmediate() >= 0);
2090ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2091ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2092ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Ldr(dst, MemOperand(StackPointer(), offset));
2093ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2094ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2095ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2096ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Claim(const Operand& size) {
2097b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2098f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2099f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
2100f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
2101f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
2102f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2103ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
210488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(size.GetImmediate() > 0);
2105ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
210688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      VIXL_ASSERT((size.GetImmediate() % 16) == 0);
2107ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2108ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2109ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2110ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
2111ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    BumpSystemStackPointer(size);
2112ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2113ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2114ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Sub(StackPointer(), StackPointer(), size);
2115ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2116ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2117ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2118ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Drop(const Operand& size) {
2119b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2120f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2121f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  if (size.IsZero()) {
2122f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl    return;
2123f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl  }
2124f37fdc0b307fc66239b8b754b0465d36bc0f8aedarmvixl
2125ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (size.IsImmediate()) {
212688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(size.GetImmediate() > 0);
2127ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (sp.Is(StackPointer())) {
212888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      VIXL_ASSERT((size.GetImmediate() % 16) == 0);
2129ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2130ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2131ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2132ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Add(StackPointer(), StackPointer(), size);
2133ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2134ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2135ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2136ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PushCalleeSavedRegisters() {
2137ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
2138c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // 10 stp will be emitted.
2139c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we use GetCalleeSaved and SavedFP.
2140c68cb64496485710cdb5b8480f8fee287058c93farmvixl  InstructionAccurateScope scope(this, 10);
2141ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2142ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
2143b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
2144ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2145db6443499376478f5281607a3923e6ffc4c8d8ecarmvixl  MemOperand tos(sp, -2 * static_cast<int>(kXRegSizeInBytes), PreIndex);
2146ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2147ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x29, x30, tos);
2148ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x27, x28, tos);
2149ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x25, x26, tos);
2150ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x23, x24, tos);
2151ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x21, x22, tos);
2152ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  stp(x19, x20, tos);
21535799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
21545799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d14, d15, tos);
21555799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d12, d13, tos);
21565799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d10, d11, tos);
21575799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  stp(d8, d9, tos);
2158ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2159ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2160ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2161ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::PopCalleeSavedRegisters() {
2162ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Ensure that the macro-assembler doesn't use any scratch registers.
2163c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // 10 ldp will be emitted.
2164c68cb64496485710cdb5b8480f8fee287058c93farmvixl  // TODO(all): Should we use GetCalleeSaved and SavedFP.
2165c68cb64496485710cdb5b8480f8fee287058c93farmvixl  InstructionAccurateScope scope(this, 10);
2166ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2167ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // This method must not be called unless the current stack pointer is sp.
2168b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(sp.Is(StackPointer()));
2169ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2170ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  MemOperand tos(sp, 2 * kXRegSizeInBytes, PostIndex);
2171ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
21725799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d8, d9, tos);
21735799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d10, d11, tos);
21745799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d12, d13, tos);
21755799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  ldp(d14, d15, tos);
21765799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2177ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x19, x20, tos);
2178ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x21, x22, tos);
2179ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x23, x24, tos);
2180ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x25, x26, tos);
2181ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x27, x28, tos);
2182ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  ldp(x29, x30, tos);
2183ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2184ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
21856e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::LoadCPURegList(CPURegList registers,
21866e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                    const MemOperand& src) {
21876e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  LoadStoreCPURegListHelper(kLoad, registers, src);
21886e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
21896e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
21906e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::StoreCPURegList(CPURegList registers,
21916e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                     const MemOperand& dst) {
21926e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  LoadStoreCPURegListHelper(kStore, registers, dst);
21936e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
21946e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
21956e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
21966e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlvoid MacroAssembler::LoadStoreCPURegListHelper(LoadStoreCPURegListAction op,
21976e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                               CPURegList registers,
21986e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl                                               const MemOperand& mem) {
21996e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // We do not handle pre-indexing or post-indexing.
22006e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!(mem.IsPreIndex() || mem.IsPostIndex()));
22016e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.Overlaps(tmp_list_));
22026e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.Overlaps(fptmp_list_));
22036e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  VIXL_ASSERT(!registers.IncludesAliasOf(sp));
22046e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
22056e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  UseScratchRegisterScope temps(this);
22066e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
22070f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  MemOperand loc = BaseMemOperandForLoadStoreCPURegList(registers, mem, &temps);
22086a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  const int reg_size = registers.GetRegisterSizeInBytes();
22096e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
22106a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  VIXL_ASSERT(IsPowerOf2(reg_size));
22116a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov
22126a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // Since we are operating on register pairs, we would like to align on double
22136a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // the standard size; on the other hand, we don't want to insert an extra
22146a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // operation, which will happen if the number of registers is even. Note that
22156a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // the alignment of the base pointer is unknown here, but we assume that it
22166a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  // is more likely to be aligned.
22176a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  if (((loc.GetOffset() & (2 * reg_size - 1)) != 0) &&
22186a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      ((registers.GetCount() % 2) != 0)) {
22196a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    if (op == kStore) {
22206a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      Str(registers.PopLowestIndex(), loc);
22216a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    } else {
22226a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      VIXL_ASSERT(op == kLoad);
22236a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov      Ldr(registers.PopLowestIndex(), loc);
22246a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    }
22256a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    loc.AddOffset(reg_size);
22266a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov  }
222788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  while (registers.GetCount() >= 2) {
22286e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& dst0 = registers.PopLowestIndex();
22296e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegister& dst1 = registers.PopLowestIndex();
22306e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (op == kStore) {
22316e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Stp(dst0, dst1, loc);
22326e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
22336e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      VIXL_ASSERT(op == kLoad);
22346e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldp(dst0, dst1, loc);
22356e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
22366a46bf3b4e9ec6010133ee160dffa66f5dd4027aAnton Kirilov    loc.AddOffset(2 * reg_size);
22376e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
22386e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (!registers.IsEmpty()) {
22396e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    if (op == kStore) {
22406e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Str(registers.PopLowestIndex(), loc);
22416e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    } else {
22426e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      VIXL_ASSERT(op == kLoad);
22436e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Ldr(registers.PopLowestIndex(), loc);
22446e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
22456e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
22466e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
22476e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
22486e2c8275d5f34a531fe1eef7a7aa877601be8558armvixlMemOperand MacroAssembler::BaseMemOperandForLoadStoreCPURegList(
22496e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const CPURegList& registers,
22506e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    const MemOperand& mem,
22516e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    UseScratchRegisterScope* scratch_scope) {
22526e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  // If necessary, pre-compute the base address for the accesses.
22536e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  if (mem.IsRegisterOffset()) {
22546e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    Register reg_base = scratch_scope->AcquireX();
22556e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    ComputeAddress(reg_base, mem);
22566e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    return MemOperand(reg_base);
22576e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
22586e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  } else if (mem.IsImmediateOffset()) {
225988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int reg_size = registers.GetRegisterSizeInBytes();
226088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int total_size = registers.GetTotalSizeInBytes();
226188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t min_offset = mem.GetOffset();
226288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    int64_t max_offset =
226388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois        mem.GetOffset() + std::max(0, total_size - 2 * reg_size);
226488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    if ((registers.GetCount() >= 2) &&
22656e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl        (!Assembler::IsImmLSPair(min_offset, WhichPowerOf2(reg_size)) ||
22666e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl         !Assembler::IsImmLSPair(max_offset, WhichPowerOf2(reg_size)))) {
22676e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      Register reg_base = scratch_scope->AcquireX();
22686e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      ComputeAddress(reg_base, mem);
22696e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl      return MemOperand(reg_base);
22706e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl    }
22716e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  }
22726e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
22736e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl  return mem;
22746e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl}
22756e2c8275d5f34a531fe1eef7a7aa877601be8558armvixl
2276ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::BumpSystemStackPointer(const Operand& space) {
2277b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!sp.Is(StackPointer()));
2278ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // TODO: Several callers rely on this not using scratch registers, so we use
2279ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the assembler directly here. However, this means that large immediate
2280ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // values of 'space' cannot be handled.
2281c68cb64496485710cdb5b8480f8fee287058c93farmvixl  InstructionAccurateScope scope(this, 1);
2282ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  sub(sp, StackPointer(), space);
2283ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2284ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2285ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
22865289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// TODO(all): Fix printf for NEON registers, and resolve whether we should be
22875289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl// using FPRegister or VRegister here.
22885289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl
2289ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// This is the main Printf implementation. All callee-saved registers are
2290ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl// preserved, but NZCV and the caller-saved registers may be clobbered.
22910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::PrintfNoPreserve(const char* format,
2292ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg0,
2293ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg1,
2294ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg2,
2295ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl                                      const CPURegister& arg3) {
2296ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We cannot handle a caller-saved stack pointer. It doesn't make much sense
2297ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // in most cases anyway, so this restriction shouldn't be too serious.
2298b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!kCallerSaved.IncludesAliasOf(StackPointer()));
2299b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
23005799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // The provided arguments, and their proper PCS registers.
23015799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegister args[kPrintfMaxArgCount] = {arg0, arg1, arg2, arg3};
23025799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegister pcs[kPrintfMaxArgCount];
23035799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
23045799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  int arg_count = kPrintfMaxArgCount;
23055799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
23065799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // The PCS varargs registers for printf. Note that x0 is used for the printf
23075799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // format string.
23085799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  static const CPURegList kPCSVarargs =
23095799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      CPURegList(CPURegister::kRegister, kXRegSize, 1, arg_count);
23105799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  static const CPURegList kPCSVarargsFP =
23115289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      CPURegList(CPURegister::kVRegister, kDRegSize, 0, arg_count - 1);
23125799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
23135799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // We can use caller-saved registers as scratch values, except for the
23145799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // arguments and the PCS registers where they might need to go.
2315b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope temps(this);
23165799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Include(kCallerSaved);
23175289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  temps.Include(kCallerSavedV);
23185799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(kPCSVarargs);
23195799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(kPCSVarargsFP);
2320b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  temps.Exclude(arg0, arg1, arg2, arg3);
2321ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
23225799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Copies of the arg lists that we can iterate through.
23235799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegList pcs_varargs = kPCSVarargs;
23245799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  CPURegList pcs_varargs_fp = kPCSVarargsFP;
23255799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
23265799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Place the arguments. There are lots of clever tricks and optimizations we
23275799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // could use here, but Printf is a debug tool so instead we just try to keep
23285799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // it simple: Move each input that isn't already in the right place to a
23295799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // scratch register, then move everything back.
23305799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  for (unsigned i = 0; i < kPrintfMaxArgCount; i++) {
23315799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Work out the proper PCS register for this argument.
2332ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    if (args[i].IsRegister()) {
23335799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      pcs[i] = pcs_varargs.PopLowestIndex().X();
23345799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // We might only need a W register here. We need to know the size of the
23355799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // argument so we can properly encode it for the simulator call.
23365799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (args[i].Is32Bits()) pcs[i] = pcs[i].W();
23375289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    } else if (args[i].IsVRegister()) {
23385799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // In C, floats are always cast to doubles for varargs calls.
23395799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      pcs[i] = pcs_varargs_fp.PopLowestIndex().D();
2340ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
23415799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      VIXL_ASSERT(args[i].IsNone());
2342ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      arg_count = i;
2343ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl      break;
2344ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2345ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
23465799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // If the argument is already in the right place, leave it where it is.
23475799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (args[i].Aliases(pcs[i])) continue;
23485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
23495799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Otherwise, if the argument is in a PCS argument register, allocate an
23505799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // appropriate scratch register and then move it out of the way.
23515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (kPCSVarargs.IncludesAliasOf(args[i]) ||
23525799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        kPCSVarargsFP.IncludesAliasOf(args[i])) {
23535799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (args[i].IsRegister()) {
23545799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Register old_arg = Register(args[i]);
23555799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Register new_arg = temps.AcquireSameSizeAs(old_arg);
23565799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Mov(new_arg, old_arg);
23575799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        args[i] = new_arg;
23585799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
23595799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        FPRegister old_arg = FPRegister(args[i]);
23605799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        FPRegister new_arg = temps.AcquireSameSizeAs(old_arg);
23615799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fmov(new_arg, old_arg);
23625799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        args[i] = new_arg;
23635799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
23645799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
2365ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2366ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
23675799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // Do a second pass to move values into their final positions and perform any
23685799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // conversions that may be required.
23695799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  for (int i = 0; i < arg_count; i++) {
237088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(pcs[i].GetType() == args[i].GetType());
23715799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (pcs[i].IsRegister()) {
23725799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      Mov(Register(pcs[i]), Register(args[i]), kDiscardForSameWReg);
2373ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    } else {
23745289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl      VIXL_ASSERT(pcs[i].IsVRegister());
237588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (pcs[i].GetSizeInBits() == args[i].GetSizeInBits()) {
23765799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fmov(FPRegister(pcs[i]), FPRegister(args[i]));
23775799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
23785799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        Fcvt(FPRegister(pcs[i]), FPRegister(args[i]));
23795799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
2380ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    }
2381ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2382ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2383ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Load the format string into x0, as per the procedure-call standard.
2384ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  //
2385ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // To make the code as portable as possible, the format string is encoded
2386ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // directly in the instruction stream. It might be cleaner to encode it in a
2387ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // literal pool, but since Printf is usually used for debugging, it is
2388ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // beneficial for it to be minimally dependent on other features.
23895799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  temps.Exclude(x0);
2390ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Label format_address;
2391ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  Adr(x0, &format_address);
2392ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2393ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Emit the format string directly in the instruction stream.
2394c68cb64496485710cdb5b8480f8fee287058c93farmvixl  {
23955289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    BlockPoolsScope scope(this);
2396c68cb64496485710cdb5b8480f8fee287058c93farmvixl    // Data emitted:
2397c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   branch
2398c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   strlen(format) + 1 (includes null termination)
2399c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   padding to next instruction
2400c68cb64496485710cdb5b8480f8fee287058c93farmvixl    //   unreachable
24010f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    EmissionCheckScope guard(this,
24020f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                             AlignUp(strlen(format) + 1, kInstructionSize) +
24030f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl                                 2 * kInstructionSize);
2404ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Label after_data;
2405ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    B(&after_data);
2406ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&format_address);
2407c68cb64496485710cdb5b8480f8fee287058c93farmvixl    EmitString(format);
2408ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Unreachable();
2409ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bind(&after_data);
2410ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2411ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2412ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // We don't pass any arguments on the stack, but we still need to align the C
2413ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // stack pointer to a 16-byte boundary for PCS compliance.
2414ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  if (!sp.Is(StackPointer())) {
2415ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    Bic(sp, StackPointer(), 0xf);
2416ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2417ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2418ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Actually call printf. This part needs special handling for the simulator,
2419ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // since the system printf function will use a different instruction set and
2420ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // the procedure-call standard will not be compatible.
2421703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2422c68cb64496485710cdb5b8480f8fee287058c93farmvixl    InstructionAccurateScope scope(this, kPrintfLength / kInstructionSize);
2423ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl    hlt(kPrintfOpcode);
24240f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    dc32(arg_count);  // kPrintfArgCountOffset
24255799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
24265799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Determine the argument pattern.
24275799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    uint32_t arg_pattern_list = 0;
24285799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    for (int i = 0; i < arg_count; i++) {
24295799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      uint32_t arg_pattern;
24305799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      if (pcs[i].IsRegister()) {
24315799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        arg_pattern = pcs[i].Is32Bits() ? kPrintfArgW : kPrintfArgX;
24325799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      } else {
24335799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        VIXL_ASSERT(pcs[i].Is64Bits());
24345799d6c5d10729eaade85ad608109c83ed1ae63barmvixl        arg_pattern = kPrintfArgD;
24355799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      }
24365799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      VIXL_ASSERT(arg_pattern < (1 << kPrintfArgPatternBits));
24375799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      arg_pattern_list |= (arg_pattern << (kPrintfArgPatternBits * i));
24385799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
24390f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    dc32(arg_pattern_list);  // kPrintfArgPatternListOffset
2440684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2441684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Register tmp = temps.AcquireX();
2442684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Mov(tmp, reinterpret_cast<uintptr_t>(printf));
2443684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Blr(tmp);
2444ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  }
2445ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2446ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2447ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24480f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlvoid MacroAssembler::Printf(const char* format,
24495799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg0,
24505799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg1,
24515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg2,
24525799d6c5d10729eaade85ad608109c83ed1ae63barmvixl                            CPURegister arg3) {
24535799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  // We can only print sp if it is the current stack pointer.
24545799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  if (!sp.Is(StackPointer())) {
24555799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg0));
24565799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg1));
24575799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg2));
24585799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    VIXL_ASSERT(!sp.Aliases(arg3));
24595799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
24605799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2461b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // Make sure that the macro assembler doesn't try to use any of our arguments
2462b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // as scratch registers.
2463b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  UseScratchRegisterScope exclude_all(this);
2464b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  exclude_all.ExcludeAll();
2465b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2466ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // Preserve all caller-saved registers as well as NZCV.
2467ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // If sp is the stack pointer, PushCPURegList asserts that the size of each
2468ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  // list is a multiple of 16 bytes.
2469ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PushCPURegList(kCallerSaved);
24705289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  PushCPURegList(kCallerSavedV);
2471ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
24720f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  {
24730f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    UseScratchRegisterScope temps(this);
2474b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    // We can use caller-saved registers as scratch values (except for argN).
24755799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Include(kCallerSaved);
24765289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl    temps.Include(kCallerSavedV);
2477b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    temps.Exclude(arg0, arg1, arg2, arg3);
2478b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
24795799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // If any of the arguments are the current stack pointer, allocate a new
24805799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // register for them, and adjust the value to compensate for pushing the
24815799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // caller-saved registers.
24825799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg0_sp = StackPointer().Aliases(arg0);
24835799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg1_sp = StackPointer().Aliases(arg1);
24845799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg2_sp = StackPointer().Aliases(arg2);
24855799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    bool arg3_sp = StackPointer().Aliases(arg3);
24865799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    if (arg0_sp || arg1_sp || arg2_sp || arg3_sp) {
24875799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // Allocate a register to hold the original stack pointer value, to pass
24885799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      // to PrintfNoPreserve as an argument.
24895799d6c5d10729eaade85ad608109c83ed1ae63barmvixl      Register arg_sp = temps.AcquireX();
24900f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      Add(arg_sp,
24910f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl          StackPointer(),
249288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois          kCallerSaved.GetTotalSizeInBytes() +
249388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois              kCallerSavedV.GetTotalSizeInBytes());
249488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg0_sp) arg0 = Register(arg_sp.GetCode(), arg0.GetSizeInBits());
249588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg1_sp) arg1 = Register(arg_sp.GetCode(), arg1.GetSizeInBits());
249688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg2_sp) arg2 = Register(arg_sp.GetCode(), arg2.GetSizeInBits());
249788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      if (arg3_sp) arg3 = Register(arg_sp.GetCode(), arg3.GetSizeInBits());
24985799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    }
24995799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2500b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    // Preserve NZCV.
2501b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Register tmp = temps.AcquireX();
2502b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Mrs(tmp, NZCV);
2503b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Push(tmp, xzr);
25045799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Release(tmp);
2505b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2506b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    PrintfNoPreserve(format, arg0, arg1, arg2, arg3);
2507b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
25085799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Restore NZCV.
25095799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    tmp = temps.AcquireX();
2510b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Pop(xzr, tmp);
2511b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    Msr(NZCV, tmp);
25125799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    temps.Release(tmp);
2513b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2514ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
25155289c5900fb214f2f6aa61e2a9263730dcf4cc17armvixl  PopCPURegList(kCallerSavedV);
2516ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl  PopCPURegList(kCallerSaved);
2517ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2518ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2519ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Trace(TraceParameters parameters, TraceCommand command) {
2520b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2521ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2522703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2523684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // The arguments to the trace pseudo instruction need to be contiguous in
2524684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // memory, so make sure we don't try to emit a literal pool.
2525684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    InstructionAccurateScope scope(this, kTraceLength / kInstructionSize);
2526ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2527684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Label start;
2528684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    bind(&start);
2529ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2530d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames    // Refer to simulator-aarch64.h for a description of the marker and its
2531684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // arguments.
2532684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    hlt(kTraceOpcode);
2533ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
253488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kTraceParamsOffset);
2535684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(parameters);
2536ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
253788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kTraceCommandOffset);
2538684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(command);
2539684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2540684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // Emit nothing on real hardware.
2541684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    USE(parameters, command);
2542684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  }
2543ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2544ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2545ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2546ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixlvoid MacroAssembler::Log(TraceParameters parameters) {
2547b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(allow_macro_instructions_);
2548ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2549703ff06a087f67fccde24a7ffbc8a2e74a406cb1Alexandre Rames  if (generate_simulator_code_) {
2550684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // The arguments to the log pseudo instruction need to be contiguous in
2551684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // memory, so make sure we don't try to emit a literal pool.
2552684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    InstructionAccurateScope scope(this, kLogLength / kInstructionSize);
2553ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2554684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    Label start;
2555684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    bind(&start);
2556ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2557d3832965c62a8ad461b9ea9eb0994ca6b0a3da2cAlexandre Rames    // Refer to simulator-aarch64.h for a description of the marker and its
2558684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // arguments.
2559684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    hlt(kLogOpcode);
2560ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
256188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(GetSizeOfCodeGeneratedSince(&start) == kLogParamsOffset);
2562684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    dc32(parameters);
2563684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  } else {
2564684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    // Emit nothing on real hardware.
2565684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl    USE(parameters);
2566684cd2a7f5845539b58d0da7e012e39df49ceff0armvixl  }
2567ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}
2568ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl
2569578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2570578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::EnableInstrumentation() {
2571b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!isprint(InstrumentStateEnable));
2572578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
2573578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateEnable);
2574578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2575578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2576578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2577578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::DisableInstrumentation() {
2578b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!isprint(InstrumentStateDisable));
2579578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
2580578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, InstrumentStateDisable);
2581578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2582578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2583578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2584578645f14e122d2b87d907e298cda7e7d0babf1farmvixlvoid MacroAssembler::AnnotateInstrumentation(const char* marker_name) {
2585b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(strlen(marker_name) == 2);
2586578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2587578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // We allow only printable characters in the marker names. Unprintable
2588578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  // characters are reserved for controlling features of the instrumentation.
2589b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(isprint(marker_name[0]) && isprint(marker_name[1]));
2590578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2591578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  InstructionAccurateScope scope(this, 1);
2592578645f14e122d2b87d907e298cda7e7d0babf1farmvixl  movn(xzr, (marker_name[1] << 8) | marker_name[0]);
2593578645f14e122d2b87d907e298cda7e7d0babf1farmvixl}
2594578645f14e122d2b87d907e298cda7e7d0babf1farmvixl
2595b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2596330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid UseScratchRegisterScope::Open(MacroAssembler* masm) {
2597330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(!initialised_);
25980f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl  VIXL_ASSERT(masm != NULL);
259988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available_ = masm->GetScratchRegisterList();
260088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  availablefp_ = masm->GetScratchFPRegisterList();
260188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  old_available_ = available_->GetList();
260288c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  old_availablefp_ = availablefp_->GetList();
260388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(available_->GetType() == CPURegister::kRegister);
260488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  VIXL_ASSERT(availablefp_->GetType() == CPURegister::kVRegister);
2605330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2606330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = true;
2607330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2608330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2609330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2610330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2611330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlvoid UseScratchRegisterScope::Close() {
2612330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (available_) {
261388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    available_->SetList(old_available_);
2614330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    available_ = NULL;
2615330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
2616330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  if (availablefp_) {
261788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    availablefp_->SetList(old_availablefp_);
2618330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl    availablefp_ = NULL;
2619330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  }
2620330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2621330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = false;
2622330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2623330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2624330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2625330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2626330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlUseScratchRegisterScope::UseScratchRegisterScope(MacroAssembler* masm) {
2627330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2628330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = false;
2629330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2630330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  Open(masm);
2631330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2632330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
2633330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl// This allows deferred (and optional) initialisation of the scope.
2634330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixlUseScratchRegisterScope::UseScratchRegisterScope()
26350f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl    : available_(NULL),
26360f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      availablefp_(NULL),
26370f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      old_available_(0),
26380f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixl      old_availablefp_(0) {
2639330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#ifdef VIXL_DEBUG
2640330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  initialised_ = false;
2641330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl#endif
2642330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl}
2643330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl
26440f35e36b7f5d1d2f4d95989b418447e1a4bcc8cdarmvixlUseScratchRegisterScope::~UseScratchRegisterScope() { Close(); }
2645b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2646b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
26475799d6c5d10729eaade85ad608109c83ed1ae63barmvixlbool UseScratchRegisterScope::IsAvailable(const CPURegister& reg) const {
26485799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  return available_->IncludesAliasOf(reg) || availablefp_->IncludesAliasOf(reg);
26495799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
26505799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
26515799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2652b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlRegister UseScratchRegisterScope::AcquireSameSizeAs(const Register& reg) {
265388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int code = AcquireNextAvailable(available_).GetCode();
265488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return Register(code, reg.GetSizeInBits());
2655b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2656b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2657b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2658b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlFPRegister UseScratchRegisterScope::AcquireSameSizeAs(const FPRegister& reg) {
265988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  int code = AcquireNextAvailable(availablefp_).GetCode();
266088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  return FPRegister(code, reg.GetSizeInBits());
2661b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2662b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2663b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2664b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Release(const CPURegister& reg) {
2665330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(initialised_);
2666b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  if (reg.IsRegister()) {
266788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ReleaseByCode(available_, reg.GetCode());
2668b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else if (reg.IsFPRegister()) {
266988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ReleaseByCode(availablefp_, reg.GetCode());
2670b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  } else {
2671b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    VIXL_ASSERT(reg.IsNone());
2672b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2673b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2674b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2675b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
26765799d6c5d10729eaade85ad608109c83ed1ae63barmvixlvoid UseScratchRegisterScope::Include(const CPURegList& list) {
2677330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(initialised_);
267888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (list.GetType() == CPURegister::kRegister) {
26795799d6c5d10729eaade85ad608109c83ed1ae63barmvixl    // Make sure that neither sp nor xzr are included the list.
268088c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    IncludeByRegList(available_,
268188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois                     list.GetList() & ~(xzr.GetBit() | sp.GetBit()));
26825799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  } else {
268388c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(list.GetType() == CPURegister::kVRegister);
268488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    IncludeByRegList(availablefp_, list.GetList());
26855799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
26865799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
26875799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
26885799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2689b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Include(const Register& reg1,
2690b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg2,
2691b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg3,
2692b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg4) {
2693330dc7153e671968beb67f09ed2cb7b5bda334dbarmvixl  VIXL_ASSERT(initialised_);
269488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList include =
269588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2696b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  // Make sure that neither sp nor xzr are included the list.
269788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  include &= ~(xzr.GetBit() | sp.GetBit());
2698b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2699b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  IncludeByRegList(available_, include);
2700b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2701b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2702b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2703b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Include(const FPRegister& reg1,
2704b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg2,
2705b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg3,
2706b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg4) {
270788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList include =
270888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2709b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  IncludeByRegList(availablefp_, include);
2710b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2711b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2712b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
27135799d6c5d10729eaade85ad608109c83ed1ae63barmvixlvoid UseScratchRegisterScope::Exclude(const CPURegList& list) {
271488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  if (list.GetType() == CPURegister::kRegister) {
271588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ExcludeByRegList(available_, list.GetList());
27165799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  } else {
271788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    VIXL_ASSERT(list.GetType() == CPURegister::kVRegister);
271888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois    ExcludeByRegList(availablefp_, list.GetList());
27195799d6c5d10729eaade85ad608109c83ed1ae63barmvixl  }
27205799d6c5d10729eaade85ad608109c83ed1ae63barmvixl}
27215799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
27225799d6c5d10729eaade85ad608109c83ed1ae63barmvixl
2723b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const Register& reg1,
2724b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg2,
2725b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg3,
2726b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const Register& reg4) {
272788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList exclude =
272888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2729b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(available_, exclude);
2730b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2731b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2732b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2733b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const FPRegister& reg1,
2734b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg2,
2735b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg3,
2736b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const FPRegister& reg4) {
273788c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  RegList excludefp =
273888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      reg1.GetBit() | reg2.GetBit() | reg3.GetBit() | reg4.GetBit();
2739b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(availablefp_, excludefp);
2740b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2741b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2742b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2743b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::Exclude(const CPURegister& reg1,
2744b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg2,
2745b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg3,
2746b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                      const CPURegister& reg4) {
2747b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  RegList exclude = 0;
2748b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  RegList excludefp = 0;
2749b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2750b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  const CPURegister regs[] = {reg1, reg2, reg3, reg4};
2751b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2752b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  for (unsigned i = 0; i < (sizeof(regs) / sizeof(regs[0])); i++) {
2753b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    if (regs[i].IsRegister()) {
275488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      exclude |= regs[i].GetBit();
2755b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else if (regs[i].IsFPRegister()) {
275688c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois      excludefp |= regs[i].GetBit();
2757b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    } else {
2758b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl      VIXL_ASSERT(regs[i].IsNone());
2759b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    }
2760b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  }
2761b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2762b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(available_, exclude);
2763b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ExcludeByRegList(availablefp_, excludefp);
2764b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2765b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2766b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2767b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ExcludeAll() {
276888c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ExcludeByRegList(available_, available_->GetList());
276988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  ExcludeByRegList(availablefp_, availablefp_->GetList());
2770b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2771b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2772b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2773b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlCPURegister UseScratchRegisterScope::AcquireNextAvailable(
2774b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl    CPURegList* available) {
2775b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_CHECK(!available->IsEmpty());
2776b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  CPURegister result = available->PopLowestIndex();
2777b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  VIXL_ASSERT(!AreAliased(result, xzr, sp));
2778b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  return result;
2779b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2780b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2781b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2782b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ReleaseByCode(CPURegList* available, int code) {
2783b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl  ReleaseByRegList(available, static_cast<RegList>(1) << code);
2784b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2785b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2786b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2787b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ReleaseByRegList(CPURegList* available,
2788b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList regs) {
278988c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() | regs);
2790b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2791b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2792b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2793b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::IncludeByRegList(CPURegList* available,
2794b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList regs) {
279588c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() | regs);
2796b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2797b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2798b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
2799b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixlvoid UseScratchRegisterScope::ExcludeByRegList(CPURegList* available,
2800b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl                                               RegList exclude) {
280188c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois  available->SetList(available->GetList() & ~exclude);
2802b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl}
2803b0c8ae2a5f0abc58f67322052d39bfd47edb2892armvixl
280488c46b84df005638546de5e4e965bdcc31352f48Pierre Langlois}  // namespace aarch64
2805ad96eda8944ab1c1ba55715c50d9d6f0a3ed1dcarmvixl}  // namespace vixl
2806