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