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