1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Redistribution and use in source and binary forms, with or without 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modification, are permitted provided that the following conditions are 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// met: 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// * Redistributions of source code must retain the above copyright 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// notice, this list of conditions and the following disclaimer. 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// * Redistributions in binary form must reproduce the above 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// copyright notice, this list of conditions and the following 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// disclaimer in the documentation and/or other materials provided 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// with the distribution. 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// * Neither the name of Google Inc. nor the names of its 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// contributors may be used to endorse or promote products derived 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// from this software without specific prior written permission. 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM64 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ARM64_DEFINE_REG_STATICS 32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/arm64/assembler-arm64.h" 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/assembler-arm64-inl.h" 35014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/arm64/frames-arm64.h" 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h" 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/cpu.h" 38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/register-configuration.h" 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CpuFeatures implementation. 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CpuFeatures::ProbeImpl(bool cross_compile) { 48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // AArch64 has no configuration options, no further probing is required. 49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier supported_ = 0; 50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Only use statically determined features for cross compile (snapshot). 52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (cross_compile) return; 53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 54bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // We used to probe for coherent cache support, but on older CPUs it 55bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // causes crashes (crbug.com/524337), and newer CPUs don't even have 56bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch // the feature any more. 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CpuFeatures::PrintTarget() { } 60bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid CpuFeatures::PrintFeatures() {} 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CPURegList utilities. 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCPURegister CPURegList::PopLowestIndex() { 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEmpty()) { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return NoCPUReg; 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = CountTrailingZeros(list_, kRegListSizeInBits); 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((1 << index) & list_); 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Remove(index); 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CPURegister::Create(index, size_, type_); 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCPURegister CPURegList::PopHighestIndex() { 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEmpty()) { 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return NoCPUReg; 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int index = CountLeadingZeros(list_, kRegListSizeInBits); 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index = kRegListSizeInBits - 1 - index; 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((1 << index) & list_); 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Remove(index); 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CPURegister::Create(index, size_, type_); 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid CPURegList::RemoveCalleeSaved() { 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (type() == CPURegister::kRegister) { 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Remove(GetCalleeSaved(RegisterSizeInBits())); 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (type() == CPURegister::kFPRegister) { 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Remove(GetCalleeSavedFP(RegisterSizeInBits())); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(type() == CPURegister::kNoRegister); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsEmpty()); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The list must already be empty, so do nothing. 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCPURegList CPURegList::GetCalleeSaved(int size) { 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CPURegList(CPURegister::kRegister, size, 19, 29); 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 108014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCPURegList CPURegList::GetCalleeSavedFP(int size) { 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CPURegList(CPURegister::kFPRegister, size, 8, 15); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCPURegList CPURegList::GetCallerSaved(int size) { 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Registers x0-x18 and lr (x30) are caller-saved. 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list.Combine(lr); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return list; 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochCPURegList CPURegList::GetCallerSavedFP(int size) { 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Registers d0-d7 and d16-d31 are caller-saved. 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegList list = CPURegList(CPURegister::kFPRegister, size, 0, 7); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list.Combine(CPURegList(CPURegister::kFPRegister, size, 16, 31)); 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return list; 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This function defines the list of registers which are associated with a 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// safepoint slot. Safepoint register slots are saved contiguously on the stack. 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// MacroAssembler::SafepointRegisterStackIndex handles mapping from register 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// code to index in the safepoint register slots. Any change here can affect 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// this mapping. 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCPURegList CPURegList::GetSafepointSavedRegisters() { 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegList list = CPURegList::GetCalleeSaved(); 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list.Combine( 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegList(CPURegister::kRegister, kXRegSizeInBits, kJSCallerSaved)); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note that unfortunately we can't use symbolic names for registers and have 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to directly use register codes. This is because this function is used to 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // initialize some static variables and we can't rely on register variables 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to be initialized due to static initialization order issues in C++. 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Drop ip0 and ip1 (i.e. x16 and x17), as they should not be expected to be 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // preserved outside of the macro assembler. 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list.Remove(16); 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list.Remove(17); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add x18 to the safepoint list, as although it's not in kJSCallerSaved, it 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a caller-saved register according to the procedure call standard. 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list.Combine(18); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Drop jssp as the stack pointer doesn't need to be included. 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list.Remove(28); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add the link register (x30) to the safepoint list. 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list.Combine(30); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return list; 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Implementation of RelocInfo 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE; 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool RelocInfo::IsCodedSpecially() { 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The deserializer needs to know whether a pointer is specially coded. Being 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // specially coded on ARM64 means that it is a movz/movk sequence. We don't 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // generate those for relocatable pointers. 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool RelocInfo::IsInConstantPool() { 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* instr = reinterpret_cast<Instruction*>(pc_); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return instr->IsLdrLiteralX(); 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 182bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochAddress RelocInfo::wasm_memory_reference() { 183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(IsWasmMemoryReference(rmode_)); 184bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return Memory::Address_at(Assembler::target_pointer_address_at(pc_)); 185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 187bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochuint32_t RelocInfo::wasm_memory_size_reference() { 188bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch DCHECK(IsWasmMemorySizeReference(rmode_)); 189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch return Memory::uint32_at(Assembler::target_pointer_address_at(pc_)); 190bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 191bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch 19213e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochAddress RelocInfo::wasm_global_reference() { 19313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(IsWasmGlobalReference(rmode_)); 19413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch return Memory::Address_at(Assembler::target_pointer_address_at(pc_)); 19513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 19613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 19762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochuint32_t RelocInfo::wasm_function_table_size_reference() { 19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK(IsWasmFunctionTableSizeReference(rmode_)); 19962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return Memory::uint32_at(Assembler::target_pointer_address_at(pc_)); 20062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 20162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch 20213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid RelocInfo::unchecked_update_wasm_memory_reference( 20313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Address address, ICacheFlushMode flush_mode) { 20413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode); 20513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 20613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid RelocInfo::unchecked_update_wasm_size(uint32_t size, 20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ICacheFlushMode flush_mode) { 20913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Memory::uint32_at(Assembler::target_pointer_address_at(pc_)) = size; 210bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch} 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2, 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg3, Register reg4) { 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegList regs(reg1, reg2, reg3, reg4); 21513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch const RegisterConfiguration* config = RegisterConfiguration::Crankshaft(); 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int code = config->GetAllocatableDoubleCode(i); 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register candidate = Register::from_code(code); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (regs.IncludesAliasOf(candidate)) continue; 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return candidate; 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return NoReg; 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(const CPURegister& reg1, const CPURegister& reg2, 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg3, const CPURegister& reg4, 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg5, const CPURegister& reg6, 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg7, const CPURegister& reg8) { 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int number_of_valid_regs = 0; 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int number_of_valid_fpregs = 0; 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegList unique_regs = 0; 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegList unique_fpregs = 0; 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister regs[] = {reg1, reg2, reg3, reg4, reg5, reg6, reg7, reg8}; 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (unsigned i = 0; i < arraysize(regs); i++) { 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (regs[i].IsRegister()) { 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch number_of_valid_regs++; 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unique_regs |= regs[i].Bit(); 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (regs[i].IsFPRegister()) { 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch number_of_valid_fpregs++; 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unique_fpregs |= regs[i].Bit(); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!regs[i].IsValid()); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int number_of_unique_regs = 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CountSetBits(unique_regs, sizeof(unique_regs) * kBitsPerByte); 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int number_of_unique_fpregs = 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CountSetBits(unique_fpregs, sizeof(unique_fpregs) * kBitsPerByte); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(number_of_valid_regs >= number_of_unique_regs); 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(number_of_valid_fpregs >= number_of_unique_fpregs); 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (number_of_valid_regs != number_of_unique_regs) || 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (number_of_valid_fpregs != number_of_unique_fpregs); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreSameSizeAndType(const CPURegister& reg1, const CPURegister& reg2, 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg3, const CPURegister& reg4, 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg5, const CPURegister& reg6, 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg7, const CPURegister& reg8) { 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg1.IsValid()); 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool match = true; 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match &= !reg2.IsValid() || reg2.IsSameSizeAndType(reg1); 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match &= !reg3.IsValid() || reg3.IsSameSizeAndType(reg1); 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match &= !reg4.IsValid() || reg4.IsSameSizeAndType(reg1); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match &= !reg5.IsValid() || reg5.IsSameSizeAndType(reg1); 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match &= !reg6.IsValid() || reg6.IsSameSizeAndType(reg1); 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match &= !reg7.IsValid() || reg7.IsSameSizeAndType(reg1); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch match &= !reg8.IsValid() || reg8.IsSameSizeAndType(reg1); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return match; 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Immediate::InitializeHandle(Handle<Object> handle) { 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowDeferredHandleDereference using_raw_address; 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Verify all Objects referred by code are NOT in new space. 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* obj = *handle; 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (obj->IsHeapObject()) { 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value_ = reinterpret_cast<intptr_t>(handle.location()); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rmode_ = RelocInfo::EMBEDDED_OBJECT; 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(intptr_t) == sizeof(int64_t)); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value_ = reinterpret_cast<intptr_t>(obj); 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rmode_ = RelocInfo::NONE64; 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Operand::NeedsRelocation(const Assembler* assembler) const { 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode rmode = immediate_.rmode(); 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (rmode == RelocInfo::EXTERNAL_REFERENCE) { 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return assembler->serializer_enabled(); 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return !RelocInfo::IsNone(rmode); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Constant Pool. 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ConstPool::RecordEntry(intptr_t data, 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode mode) { 311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch DCHECK(mode != RelocInfo::COMMENT && mode != RelocInfo::CONST_POOL && 312f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch mode != RelocInfo::VENEER_POOL && 313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch mode != RelocInfo::CODE_AGE_SEQUENCE && 314c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch mode != RelocInfo::DEOPT_SCRIPT_OFFSET && 315c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch mode != RelocInfo::DEOPT_INLINING_ID && 316c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch mode != RelocInfo::DEOPT_REASON && mode != RelocInfo::DEOPT_ID); 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t raw_data = static_cast<uint64_t>(data); 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = assm_->pc_offset(); 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEmpty()) { 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch first_use_ = offset; 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<uint64_t, int> entry = std::make_pair(raw_data, offset); 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CanBeShared(mode)) { 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shared_entries_.insert(entry); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shared_entries_.count(entry.first) == 1) { 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shared_entries_count++; 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unique_entries_.push_back(entry); 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (EntryCount() > Assembler::kApproxMaxPoolEntryCount) { 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Request constant pool emission after the next instruction. 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->SetNextConstPoolCheckIn(1); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint ConstPool::DistanceToFirstUse() { 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(first_use_ >= 0); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return assm_->pc_offset() - first_use_; 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint ConstPool::MaxPcOffset() { 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // There are no pending entries in the pool so we can never get out of 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // range. 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEmpty()) return kMaxInt; 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Entries are not necessarily emitted in the order they are added so in the 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // worst case the first constant pool use will be accessing the last entry. 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return first_use_ + kMaxLoadLiteralRange - WorstCaseSize(); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint ConstPool::WorstCaseSize() { 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEmpty()) return 0; 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Max size prologue: 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // b over 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr xzr, #pool_size 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // blr xzr 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nop 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All entries are 64-bit for now. 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 4 * kInstructionSize + EntryCount() * kPointerSize; 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint ConstPool::SizeIfEmittedAtCurrentPc(bool require_jump) { 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsEmpty()) return 0; 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prologue is: 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // b over ;; if require_jump 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr xzr, #pool_size 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // blr xzr 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nop ;; if not 64-bit aligned 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int prologue_size = require_jump ? kInstructionSize : 0; 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prologue_size += 2 * kInstructionSize; 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prologue_size += IsAligned(assm_->pc_offset() + prologue_size, 8) ? 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0 : kInstructionSize; 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All entries are 64-bit for now. 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return prologue_size + EntryCount() * kPointerSize; 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ConstPool::Emit(bool require_jump) { 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!assm_->is_const_pool_blocked()); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prevent recursive pool emission and protect from veneer pools. 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::BlockPoolsScope block_pools(assm_); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int size = SizeIfEmittedAtCurrentPc(require_jump); 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label size_check; 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->bind(&size_check); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->RecordConstPool(size); 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the constant pool. It is preceded by an optional branch if 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // require_jump and a header which will: 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1) Encode the size of the constant pool, for use by the disassembler. 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2) Terminate the program, to try to prevent execution from accidentally 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // flowing into the constant pool. 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 3) align the pool entries to 64-bit. 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The header is therefore made of up to three arm64 instructions: 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr xzr, #<size of the constant pool in 32-bit words> 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // blr xzr 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nop 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If executed, the header will likely segfault and lr will point to the 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction following the offending blr. 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): Make the alignment part less fragile. Currently code is 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // allocated as a byte array so there are no guarantees the alignment will 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // be preserved on compaction. Currently it works as allocation seems to be 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 64-bit aligned. 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit branch if required 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label after_pool; 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (require_jump) { 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->b(&after_pool); 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the header. 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->RecordComment("[ Constant Pool"); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitMarker(); 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitGuard(); 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->Align(8); 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit constant pool entries. 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): currently each relocated constant is 64 bits, consider adding 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // support for 32-bit entries. 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitEntries(); 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->RecordComment("]"); 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (after_pool.is_linked()) { 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->bind(&after_pool); 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(assm_->SizeOfCodeGeneratedSince(&size_check) == 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<unsigned>(size)); 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ConstPool::Clear() { 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shared_entries_.clear(); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shared_entries_count = 0; 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unique_entries_.clear(); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch first_use_ = -1; 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool ConstPool::CanBeShared(RelocInfo::Mode mode) { 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constant pool currently does not support 32-bit entries. 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(mode != RelocInfo::NONE32); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return RelocInfo::IsNone(mode) || 4563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch (!assm_->serializer_enabled() && 4573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch (mode >= RelocInfo::FIRST_SHAREABLE_RELOC_MODE)); 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ConstPool::EmitMarker() { 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A constant pool size is expressed in number of 32-bits words. 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Currently all entries are 64-bit. 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // + 1 is for the crash guard. 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // + 0/1 for alignment. 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int word_count = EntryCount() * 2 + 1 + 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (IsAligned(assm_->pc_offset(), 8) ? 0 : 1); 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->Emit(LDR_x_lit | 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::ImmLLiteral(word_count) | 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::Rt(xzr)); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMemOperand::PairResult MemOperand::AreConsistentForPair( 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& operandA, 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& operandB, 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int access_size_log2) { 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(access_size_log2 >= 0); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(access_size_log2 <= 3); 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Step one: check that they share the same base, that the mode is Offset 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and that the offset is a multiple of access size. 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!operandA.base().Is(operandB.base()) || 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (operandA.addrmode() != Offset) || 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (operandB.addrmode() != Offset) || 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ((operandA.offset() & ((1 << access_size_log2) - 1)) != 0)) { 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return kNotPair; 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Step two: check that the offsets are contiguous and that the range 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is OK for ldp/stp. 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((operandB.offset() == operandA.offset() + (1 << access_size_log2)) && 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch is_int7(operandA.offset() >> access_size_log2)) { 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return kPairAB; 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((operandA.offset() == operandB.offset() + (1 << access_size_log2)) && 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch is_int7(operandB.offset() >> access_size_log2)) { 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return kPairBA; 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return kNotPair; 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ConstPool::EmitGuard() { 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* instr = reinterpret_cast<Instruction*>(assm_->pc()); 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->preceding()->IsLdrLiteralX() && 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->preceding()->Rt() == xzr.code()); 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->EmitPoolGuard(); 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ConstPool::EmitEntries() { 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsAligned(assm_->pc_offset(), 8)); 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef std::multimap<uint64_t, int>::const_iterator SharedEntriesIterator; 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedEntriesIterator value_it; 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Iterate through the keys (constant pool values). 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (value_it = shared_entries_.begin(); 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value_it != shared_entries_.end(); 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value_it = shared_entries_.upper_bound(value_it->first)) { 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<SharedEntriesIterator, SharedEntriesIterator> range; 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t data = value_it->first; 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch range = shared_entries_.equal_range(data); 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedEntriesIterator offset_it; 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Iterate through the offsets of a given key. 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (offset_it = range.first; offset_it != range.second; offset_it++) { 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* instr = assm_->InstructionAt(offset_it->second); 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0. 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0); 531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch instr->SetImmPCOffsetTarget(assm_->isolate(), assm_->pc()); 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->dc64(data); 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shared_entries_.clear(); 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shared_entries_count = 0; 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit unique entries. 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::vector<std::pair<uint64_t, int> >::const_iterator unique_it; 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (unique_it = unique_entries_.begin(); 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unique_it != unique_entries_.end(); 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unique_it++) { 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* instr = assm_->InstructionAt(unique_it->second); 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0. 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0); 547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch instr->SetImmPCOffsetTarget(assm_->isolate(), assm_->pc()); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assm_->dc64(unique_it->first); 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unique_entries_.clear(); 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch first_use_ = -1; 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Assembler 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAssembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : AssemblerBase(isolate, buffer, buffer_size), 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch constpool_(this), 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch recorded_ast_id_(TypeFeedbackId::None()), 560f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch unresolved_branches_() { 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const_pool_blocked_nesting_ = 0; 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch veneer_pool_blocked_nesting_ = 0; 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Reset(); 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochAssembler::~Assembler() { 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(constpool_.IsEmpty()); 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(const_pool_blocked_nesting_ == 0); 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(veneer_pool_blocked_nesting_ == 0); 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::Reset() { 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((pc_ >= buffer_) && (pc_ < buffer_ + buffer_size_)); 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(const_pool_blocked_nesting_ == 0); 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(veneer_pool_blocked_nesting_ == 0); 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(unresolved_branches_.empty()); 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memset(buffer_, 0, pc_ - buffer_); 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pc_ = buffer_; 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info_writer.Reposition(reinterpret_cast<byte*>(buffer_ + buffer_size_), 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<byte*>(pc_)); 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch constpool_.Clear(); 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_constant_pool_check_ = 0; 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_veneer_pool_check_ = kMaxInt; 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch no_const_pool_before_ = 0; 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ClearRecordedAstId(); 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::GetCode(CodeDesc* desc) { 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit constant pool if necessary. 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckConstPool(true, false); 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(constpool_.IsEmpty()); 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set up code descriptor. 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (desc) { 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch desc->buffer = reinterpret_cast<byte*>(buffer_); 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch desc->buffer_size = buffer_size_; 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch desc->instr_size = pc_offset(); 603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch desc->reloc_size = 604014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<int>((reinterpret_cast<byte*>(buffer_) + buffer_size_) - 605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reloc_info_writer.pos()); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch desc->origin = this; 607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch desc->constant_pool_size = 0; 60813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch desc->unwinding_info_size = 0; 60913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch desc->unwinding_info = nullptr; 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::Align(int m) { 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while ((pc_offset() & (m - 1)) != 0) { 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch nop(); 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::CheckLabelLinkChain(Label const * label) { 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (label->is_linked()) { 625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier static const int kMaxLinksToCheck = 64; // Avoid O(n2) behaviour. 626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier int links_checked = 0; 627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t linkoffset = label->pos(); 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool end_of_chain = false; 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (!end_of_chain) { 630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (++links_checked > kMaxLinksToCheck) break; 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction * link = InstructionAt(linkoffset); 632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t linkpcoffset = link->ImmPCOffset(); 633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int64_t prevlinkoffset = linkoffset + linkpcoffset; 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch end_of_chain = (linkoffset == prevlinkoffset); 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch linkoffset = linkoffset + linkpcoffset; 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::RemoveBranchFromLabelLinkChain(Instruction* branch, 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* label, 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* label_veneer) { 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(label->is_linked()); 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckLabelLinkChain(label); 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* link = InstructionAt(label->pos()); 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* prev_link = link; 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* next_link; 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool end_of_chain = false; 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (link != branch && !end_of_chain) { 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_link = link->ImmPCOffsetTarget(); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch end_of_chain = (link == next_link); 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prev_link = link; 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch link = next_link; 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(branch == link); 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_link = branch->ImmPCOffsetTarget(); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (branch == prev_link) { 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The branch is the first instruction in the chain. 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (branch == next_link) { 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It is also the last instruction in the chain, so it is the only branch 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // currently referring to this label. 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label->Unuse(); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch label->link_to( 673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<int>(reinterpret_cast<byte*>(next_link) - buffer_)); 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (branch == next_link) { 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The branch is the last (but not also the first) instruction in the chain. 678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prev_link->SetImmPCOffsetTarget(isolate(), prev_link); 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The branch is in the middle of the chain. 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (prev_link->IsTargetInImmPCOffsetRange(next_link)) { 683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prev_link->SetImmPCOffsetTarget(isolate(), next_link); 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (label_veneer != NULL) { 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use the veneer for all previous links in the chain. 686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch prev_link->SetImmPCOffsetTarget(isolate(), prev_link); 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch end_of_chain = false; 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch link = next_link; 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (!end_of_chain) { 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_link = link->ImmPCOffsetTarget(); 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch end_of_chain = (link == next_link); 693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch link->SetImmPCOffsetTarget(isolate(), label_veneer); 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch link = next_link; 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The assert below will fire. 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Some other work could be attempted to fix up the chain, but it would be 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rather complicated. If we crash here, we may want to consider using an 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // other mechanism than a chain of branches. 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note that this situation currently should not happen, as we always call 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this function with a veneer to the target label. 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // However this could happen with a MacroAssembler in the following state: 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [previous code] 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // B(label); 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [20KB code] 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Tbz(label); // First tbz. Pointing to unconditional branch. 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [20KB code] 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Tbz(label); // Second tbz. Pointing to the first tbz. 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [more code] 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and this function is called to remove the first tbz from the label link 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // chain. Since tbz has a range of +-32KB, the second tbz cannot point to 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the unconditional branch. 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(prev_link->IsTargetInImmPCOffsetRange(next_link)); 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckLabelLinkChain(label); 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bind(Label* label) { 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bind label to the address at pc_. All instructions (most likely branches) 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that are linked to this label will be updated to point to the newly-bound 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // label. 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!label->is_near_linked()); 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!label->is_bound()); 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeleteUnresolvedBranchInfoForLabel(label); 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the label is linked, the link chain looks something like this: 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // |--I----I-------I-------L 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // |---------------------->| pc_offset 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // |-------------->| linkoffset = label->pos() 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // |<------| link->ImmPCOffset() 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // |------>| prevlinkoffset = linkoffset + link->ImmPCOffset() 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // On each iteration, the last link is updated and then removed from the 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // chain until only one remains. At that point, the label is bound. 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the label is not linked, no preparation is required before binding. 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (label->is_linked()) { 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int linkoffset = label->pos(); 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* link = InstructionAt(linkoffset); 749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int prevlinkoffset = linkoffset + static_cast<int>(link->ImmPCOffset()); 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckLabelLinkChain(label); 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(linkoffset >= 0); 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(linkoffset < pc_offset()); 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((linkoffset > prevlinkoffset) || 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (linkoffset - prevlinkoffset == kStartOfLabelLinkChain)); 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prevlinkoffset >= 0); 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the link to point to the label. 760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (link->IsUnresolvedInternalReference()) { 761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Internal references do not get patched to an instruction but directly 762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // to an address. 763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch internal_reference_positions_.push_back(linkoffset); 764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PatchingAssembler patcher(isolate(), link, 2); 765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch patcher.dc64(reinterpret_cast<uintptr_t>(pc_)); 766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch link->SetImmPCOffsetTarget(isolate(), 768014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<Instruction*>(pc_)); 769014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Link the label to the previous link in the chain. 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) { 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We hit kStartOfLabelLinkChain, so the chain is fully processed. 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label->Unuse(); 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the label for the next iteration. 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label->link_to(prevlinkoffset); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label->bind_to(pc_offset()); 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(label->is_bound()); 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!label->is_linked()); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Assembler::LinkAndGetByteOffsetTo(Label* label) { 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(sizeof(*pc_) == 1); 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckLabelLinkChain(label); 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset; 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (label->is_bound()) { 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The label is bound, so it does not need to be updated. Referring 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instructions must link directly to the label as they will not be 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // updated. 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In this case, label->pos() returns the offset of the label from the 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // start of the buffer. 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note that offset can be zero for self-referential instructions. (This 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // could be useful for ADR, for example.) 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset = label->pos() - pc_offset(); 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(offset <= 0); 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (label->is_linked()) { 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The label is linked, so the referring instruction should be added onto 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the end of the label's link chain. 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In this case, label->pos() returns the offset of the last linked 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction from the start of the buffer. 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset = label->pos() - pc_offset(); 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(offset != kStartOfLabelLinkChain); 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note that the offset here needs to be PC-relative only so that the 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // first instruction in a buffer can link to an unbound label. Otherwise, 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the offset would be 0 for this case, and 0 is reserved for 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // kStartOfLabelLinkChain. 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The label is unused, so it now becomes linked and the referring 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction is at the start of the new link chain. 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset = kStartOfLabelLinkChain; 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The instruction at pc is now the last link in the label's chain. 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch label->link_to(pc_offset()); 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return offset; 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::DeleteUnresolvedBranchInfoForLabelTraverse(Label* label) { 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(label->is_linked()); 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckLabelLinkChain(label); 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int link_offset = label->pos(); 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int link_pcoffset; 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool end_of_chain = false; 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (!end_of_chain) { 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction * link = InstructionAt(link_offset); 840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch link_pcoffset = static_cast<int>(link->ImmPCOffset()); 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ADR instructions are not handled by veneers. 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (link->IsImmBranch()) { 844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int max_reachable_pc = 845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<int>(InstructionOffset(link) + 846014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Instruction::ImmBranchRange(link->BranchType())); 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch typedef std::multimap<int, FarBranchInfo>::iterator unresolved_info_it; 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::pair<unresolved_info_it, unresolved_info_it> range; 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch range = unresolved_branches_.equal_range(max_reachable_pc); 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unresolved_info_it it; 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (it = range.first; it != range.second; ++it) { 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (it->second.pc_offset_ == link_offset) { 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unresolved_branches_.erase(it); 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch end_of_chain = (link_pcoffset == 0); 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch link_offset = link_offset + link_pcoffset; 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::DeleteUnresolvedBranchInfoForLabel(Label* label) { 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (unresolved_branches_.empty()) { 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(next_veneer_pool_check_ == kMaxInt); 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (label->is_linked()) { 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branches to this label will be resolved when the label is bound, normally 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // just after all the associated info has been deleted. 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeleteUnresolvedBranchInfoForLabelTraverse(label); 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (unresolved_branches_.empty()) { 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_veneer_pool_check_ = kMaxInt; 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_veneer_pool_check_ = 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unresolved_branches_first_limit() - kVeneerDistanceCheckMargin; 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::StartBlockConstPool() { 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (const_pool_blocked_nesting_++ == 0) { 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prevent constant pool checks happening by setting the next check to 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the biggest possible offset. 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_constant_pool_check_ = kMaxInt; 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::EndBlockConstPool() { 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (--const_pool_blocked_nesting_ == 0) { 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the constant pool hasn't been blocked for too long. 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(pc_offset() < constpool_.MaxPcOffset()); 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Two cases: 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // * no_const_pool_before_ >= next_constant_pool_check_ and the emission is 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // still blocked 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // * no_const_pool_before_ < next_constant_pool_check_ and the next emit 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // will trigger a check. 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_constant_pool_check_ = no_const_pool_before_; 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::is_const_pool_blocked() const { 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (const_pool_blocked_nesting_ > 0) || 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (pc_offset() < no_const_pool_before_); 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsConstantPoolAt(Instruction* instr) { 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The constant pool marker is made of two instructions. These instructions 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // will never be emitted by the JIT, so checking for the first one is enough: 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0: ldr xzr, #<size of pool> 918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool result = instr->IsLdrLiteralX() && (instr->Rt() == kZeroRegCode); 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It is still worth asserting the marker is complete. 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 4: blr xzr 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result || (instr->following()->IsBranchAndLinkToRegister() && 923014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch instr->following()->Rn() == kZeroRegCode)); 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Assembler::ConstantPoolSizeAt(Instruction* instr) { 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef USE_SIMULATOR 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assembler::debug() embeds constants directly into the instruction stream. 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Although this is not a genuine constant pool, treat it like one to avoid 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // disassembling the constants. 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((instr->Mask(ExceptionMask) == HLT) && 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (instr->ImmException() == kImmExceptionIsDebug)) { 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* message = 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<const char*>( 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch instr->InstructionAtOffset(kDebugMessageOffset)); 939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int size = static_cast<int>(kDebugMessageOffset + strlen(message) + 1); 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return RoundUp(size, kInstructionSize) / kInstructionSize; 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Same for printf support, see MacroAssembler::CallPrintf(). 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((instr->Mask(ExceptionMask) == HLT) && 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (instr->ImmException() == kImmExceptionIsPrintf)) { 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return kPrintfLength / kInstructionSize; 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsConstantPoolAt(instr)) { 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return instr->ImmLLiteral(); 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return -1; 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::EmitPoolGuard() { 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We must generate only one instruction as this is used in scopes that 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // control the size of the code generated. 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(BLR | Rn(xzr)); 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::StartBlockVeneerPool() { 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++veneer_pool_blocked_nesting_; 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::EndBlockVeneerPool() { 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (--veneer_pool_blocked_nesting_ == 0) { 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the veneer pool hasn't been blocked for too long. 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(unresolved_branches_.empty() || 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (pc_offset() < unresolved_branches_first_limit())); 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::br(const Register& xn) { 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(xn.Is64Bits()); 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(BR | Rn(xn)); 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::blr(const Register& xn) { 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(xn.Is64Bits()); 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The pattern 'blr xzr' is used as a guard to detect when execution falls 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // through the constant pool. It should not be emitted. 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!xn.Is(xzr)); 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(BLR | Rn(xn)); 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ret(const Register& xn) { 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(xn.Is64Bits()); 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(RET | Rn(xn)); 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::b(int imm26) { 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(B | ImmUncondBranch(imm26)); 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::b(Label* label) { 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch b(LinkAndGetInstructionOffsetTo(label)); 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::b(int imm19, Condition cond) { 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(B_cond | ImmCondBranch(imm19) | cond); 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::b(Label* label, Condition cond) { 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch b(LinkAndGetInstructionOffsetTo(label), cond); 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bl(int imm26) { 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(BL | ImmUncondBranch(imm26)); 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bl(Label* label) { 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bl(LinkAndGetInstructionOffsetTo(label)); 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cbz(const Register& rt, 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int imm19) { 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rt) | CBZ | ImmCmpBranch(imm19) | Rt(rt)); 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cbz(const Register& rt, 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* label) { 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cbz(rt, LinkAndGetInstructionOffsetTo(label)); 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cbnz(const Register& rt, 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int imm19) { 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rt) | CBNZ | ImmCmpBranch(imm19) | Rt(rt)); 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cbnz(const Register& rt, 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* label) { 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cbnz(rt, LinkAndGetInstructionOffsetTo(label)); 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::tbz(const Register& rt, 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned bit_pos, 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int imm14) { 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits))); 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(TBZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt)); 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::tbz(const Register& rt, 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned bit_pos, 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* label) { 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tbz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label)); 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::tbnz(const Register& rt, 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned bit_pos, 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int imm14) { 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rt.Is64Bits() || (rt.Is32Bits() && (bit_pos < kWRegSizeInBits))); 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(TBNZ | ImmTestBranchBit(bit_pos) | ImmTestBranch(imm14) | Rt(rt)); 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::tbnz(const Register& rt, 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned bit_pos, 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* label) { 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tbnz(rt, bit_pos, LinkAndGetInstructionOffsetTo(label)); 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::adr(const Register& rd, int imm21) { 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits()); 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(ADR | ImmPCRelAddress(imm21) | Rd(rd)); 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::adr(const Register& rd, Label* label) { 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch adr(rd, LinkAndGetByteOffsetTo(label)); 1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::add(const Register& rd, 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSub(rd, rn, operand, LeaveFlags, ADD); 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::adds(const Register& rd, 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSub(rd, rn, operand, SetFlags, ADD); 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cmn(const Register& rn, 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rn); 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch adds(zr, rn, operand); 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::sub(const Register& rd, 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSub(rd, rn, operand, LeaveFlags, SUB); 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::subs(const Register& rd, 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSub(rd, rn, operand, SetFlags, SUB); 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cmp(const Register& rn, const Operand& operand) { 1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rn); 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch subs(zr, rn, operand); 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::neg(const Register& rd, const Operand& operand) { 1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rd); 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sub(rd, zr, operand); 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::negs(const Register& rd, const Operand& operand) { 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rd); 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch subs(rd, zr, operand); 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::adc(const Register& rd, 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubWithCarry(rd, rn, operand, LeaveFlags, ADC); 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::adcs(const Register& rd, 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubWithCarry(rd, rn, operand, SetFlags, ADC); 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::sbc(const Register& rd, 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubWithCarry(rd, rn, operand, LeaveFlags, SBC); 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::sbcs(const Register& rd, 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubWithCarry(rd, rn, operand, SetFlags, SBC); 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ngc(const Register& rd, const Operand& operand) { 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rd); 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sbc(rd, zr, operand); 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ngcs(const Register& rd, const Operand& operand) { 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rd); 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sbcs(rd, zr, operand); 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Logical instructions. 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::and_(const Register& rd, 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Logical(rd, rn, operand, AND); 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ands(const Register& rd, 1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Logical(rd, rn, operand, ANDS); 1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::tst(const Register& rn, 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ands(AppropriateZeroRegFor(rn), rn, operand); 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bic(const Register& rd, 1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Logical(rd, rn, operand, BIC); 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::bics(const Register& rd, 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Logical(rd, rn, operand, BICS); 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::orr(const Register& rd, 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Logical(rd, rn, operand, ORR); 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::orn(const Register& rd, 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Logical(rd, rn, operand, ORN); 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::eor(const Register& rd, 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Logical(rd, rn, operand, EOR); 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::eon(const Register& rd, 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand) { 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Logical(rd, rn, operand, EON); 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::lslv(const Register& rd, 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rm.SizeInBits()); 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | LSLV | Rm(rm) | Rn(rn) | Rd(rd)); 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::lsrv(const Register& rd, 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rm.SizeInBits()); 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | LSRV | Rm(rm) | Rn(rn) | Rd(rd)); 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::asrv(const Register& rd, 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rm.SizeInBits()); 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | ASRV | Rm(rm) | Rn(rn) | Rd(rd)); 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::rorv(const Register& rd, 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rm.SizeInBits()); 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | RORV | Rm(rm) | Rn(rn) | Rd(rd)); 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Bitfield operations. 1286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::bfm(const Register& rd, const Register& rn, int immr, 1287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int imms) { 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset); 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | BFM | N | 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImmR(immr, rd.SizeInBits()) | 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImmS(imms, rn.SizeInBits()) | 1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Rn(rn) | Rd(rd)); 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::sbfm(const Register& rd, const Register& rn, int immr, 1298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int imms) { 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits() || rn.Is32Bits()); 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset); 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | SBFM | N | 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImmR(immr, rd.SizeInBits()) | 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImmS(imms, rn.SizeInBits()) | 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Rn(rn) | Rd(rd)); 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::ubfm(const Register& rd, const Register& rn, int immr, 1309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int imms) { 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset); 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | UBFM | N | 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImmR(immr, rd.SizeInBits()) | 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImmS(imms, rn.SizeInBits()) | 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Rn(rn) | Rd(rd)); 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::extr(const Register& rd, const Register& rn, const Register& rm, 1320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int lsb) { 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rm.SizeInBits()); 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr N = SF(rd) >> (kSFOffset - kBitfieldNOffset); 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | EXTR | N | Rm(rm) | 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImmS(lsb, rn.SizeInBits()) | Rn(rn) | Rd(rd)); 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::csel(const Register& rd, 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond) { 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalSelect(rd, rn, rm, cond, CSEL); 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::csinc(const Register& rd, 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond) { 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalSelect(rd, rn, rm, cond, CSINC); 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::csinv(const Register& rd, 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond) { 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalSelect(rd, rn, rm, cond, CSINV); 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::csneg(const Register& rd, 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond) { 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalSelect(rd, rn, rm, cond, CSNEG); 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cset(const Register &rd, Condition cond) { 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((cond != al) && (cond != nv)); 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rd); 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch csinc(rd, zr, zr, NegateCondition(cond)); 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::csetm(const Register &rd, Condition cond) { 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((cond != al) && (cond != nv)); 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rd); 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch csinv(rd, zr, zr, NegateCondition(cond)); 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cinc(const Register &rd, const Register &rn, Condition cond) { 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((cond != al) && (cond != nv)); 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch csinc(rd, rn, rn, NegateCondition(cond)); 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cinv(const Register &rd, const Register &rn, Condition cond) { 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((cond != al) && (cond != nv)); 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch csinv(rd, rn, rn, NegateCondition(cond)); 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cneg(const Register &rd, const Register &rn, Condition cond) { 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((cond != al) && (cond != nv)); 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch csneg(rd, rn, rn, NegateCondition(cond)); 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ConditionalSelect(const Register& rd, 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond, 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalSelectOp op) { 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rm.SizeInBits()); 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | op | Rm(rm) | Cond(cond) | Rn(rn) | Rd(rd)); 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ccmn(const Register& rn, 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StatusFlags nzcv, 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond) { 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalCompare(rn, operand, nzcv, cond, CCMN); 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ccmp(const Register& rn, 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StatusFlags nzcv, 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond) { 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalCompare(rn, operand, nzcv, cond, CCMP); 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::DataProcessing3Source(const Register& rd, 1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra, 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3SourceOp op) { 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | op | Rm(rm) | Ra(ra) | Rn(rn) | Rd(rd)); 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mul(const Register& rd, 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AreSameSizeAndType(rd, rn, rm)); 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rn); 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, zr, MADD); 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::madd(const Register& rd, 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra) { 1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AreSameSizeAndType(rd, rn, rm, ra)); 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, ra, MADD); 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mneg(const Register& rd, 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AreSameSizeAndType(rd, rn, rm)); 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register zr = AppropriateZeroRegFor(rn); 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, zr, MSUB); 1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::msub(const Register& rd, 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra) { 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AreSameSizeAndType(rd, rn, rm, ra)); 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, ra, MSUB); 1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::smaddl(const Register& rd, 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra) { 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits() && ra.Is64Bits()); 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rn.Is32Bits() && rm.Is32Bits()); 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, ra, SMADDL_x); 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::smsubl(const Register& rd, 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra) { 1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits() && ra.Is64Bits()); 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rn.Is32Bits() && rm.Is32Bits()); 1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, ra, SMSUBL_x); 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::umaddl(const Register& rd, 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra) { 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits() && ra.Is64Bits()); 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rn.Is32Bits() && rm.Is32Bits()); 1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, ra, UMADDL_x); 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::umsubl(const Register& rd, 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra) { 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits() && ra.Is64Bits()); 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rn.Is32Bits() && rm.Is32Bits()); 1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, ra, UMSUBL_x); 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::smull(const Register& rd, 1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits()); 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rn.Is32Bits() && rm.Is32Bits()); 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, xzr, SMADDL_x); 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::smulh(const Register& rd, 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AreSameSizeAndType(rd, rn, rm)); 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3Source(rd, rn, rm, xzr, SMULH_x); 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::sdiv(const Register& rd, 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rm.SizeInBits()); 1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | SDIV | Rm(rm) | Rn(rn) | Rd(rd)); 1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::udiv(const Register& rd, 1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm) { 1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rm.SizeInBits()); 1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | UDIV | Rm(rm) | Rn(rn) | Rd(rd)); 1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::rbit(const Register& rd, 1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn) { 1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing1Source(rd, rn, RBIT); 1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::rev16(const Register& rd, 1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn) { 1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing1Source(rd, rn, REV16); 1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::rev32(const Register& rd, 1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn) { 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits()); 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing1Source(rd, rn, REV); 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::rev(const Register& rd, 1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn) { 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing1Source(rd, rn, rd.Is64Bits() ? REV_x : REV_w); 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::clz(const Register& rd, 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn) { 1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing1Source(rd, rn, CLZ); 1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::cls(const Register& rd, 1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn) { 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing1Source(rd, rn, CLS); 1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldp(const CPURegister& rt, 1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& rt2, 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& src) { 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStorePair(rt, rt2, src, LoadPairOpFor(rt, rt2)); 1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::stp(const CPURegister& rt, 1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& rt2, 1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& dst) { 1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStorePair(rt, rt2, dst, StorePairOpFor(rt, rt2)); 1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldpsw(const Register& rt, 1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rt2, 1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& src) { 1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rt.Is64Bits()); 1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStorePair(rt, rt2, src, LDPSW_x); 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::LoadStorePair(const CPURegister& rt, 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& rt2, 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& addr, 1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStorePairOp op) { 1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 'rt' and 'rt2' can only be aliased for stores. 1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(((op & LoadStorePairLBit) == 0) || !rt.Is(rt2)); 1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AreSameSizeAndType(rt, rt2)); 1606014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(IsImmLSPair(addr.offset(), CalcLSPairDataSize(op))); 1607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset = static_cast<int>(addr.offset()); 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr memop = op | Rt(rt) | Rt2(rt2) | RnSP(addr.base()) | 1610014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ImmLSPair(offset, CalcLSPairDataSize(op)); 1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr addrmodeop; 1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (addr.IsImmediateOffset()) { 1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addrmodeop = LoadStorePairOffsetFixed; 1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pre-index and post-index modes. 1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!rt.Is(addr.base())); 1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!rt2.Is(addr.base())); 1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(addr.offset() != 0); 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (addr.IsPreIndex()) { 1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addrmodeop = LoadStorePairPreIndexFixed; 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(addr.IsPostIndex()); 1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch addrmodeop = LoadStorePairPostIndexFixed; 1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(addrmodeop | memop); 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Memory instructions. 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldrb(const Register& rt, const MemOperand& src) { 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStore(rt, src, LDRB_w); 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::strb(const Register& rt, const MemOperand& dst) { 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStore(rt, dst, STRB_w); 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldrsb(const Register& rt, const MemOperand& src) { 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStore(rt, src, rt.Is64Bits() ? LDRSB_x : LDRSB_w); 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldrh(const Register& rt, const MemOperand& src) { 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStore(rt, src, LDRH_w); 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::strh(const Register& rt, const MemOperand& dst) { 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStore(rt, dst, STRH_w); 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldrsh(const Register& rt, const MemOperand& src) { 1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStore(rt, src, rt.Is64Bits() ? LDRSH_x : LDRSH_w); 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldr(const CPURegister& rt, const MemOperand& src) { 1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStore(rt, src, LoadOpFor(rt)); 1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::str(const CPURegister& rt, const MemOperand& src) { 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStore(rt, src, StoreOpFor(rt)); 1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldrsw(const Register& rt, const MemOperand& src) { 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rt.Is64Bits()); 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStore(rt, src, LDRSW_x); 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldr_pcrel(const CPURegister& rt, int imm19) { 1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The pattern 'ldr xzr, #offset' is used to indicate the beginning of a 1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // constant pool. It should not be emitted. 1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!rt.IsZero()); 1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(LoadLiteralOpFor(rt) | ImmLLiteral(imm19) | Rt(rt)); 1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ldr(const CPURegister& rt, const Immediate& imm) { 1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Currently we only support 64-bit literals. 1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rt.Is64Bits()); 1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordRelocInfo(imm.rmode(), imm.value()); 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BlockConstPoolFor(1); 1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The load will be patched when the constpool is emitted, patching code 1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // expect a load literal with offset 0. 1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ldr_pcrel(rt, 0); 1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 169713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::ldar(const Register& rt, const Register& rn) { 169813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 169913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? LDAR_w : LDAR_x; 170013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(op | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt)); 170113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 170213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 170313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::ldaxr(const Register& rt, const Register& rn) { 170413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 170513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? LDAXR_w : LDAXR_x; 170613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(op | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt)); 170713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 170813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 170913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::stlr(const Register& rt, const Register& rn) { 171013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 171113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? STLR_w : STLR_x; 171213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(op | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt)); 171313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 171413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 171513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::stlxr(const Register& rs, const Register& rt, 171613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch const Register& rn) { 171713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rs.Is32Bits()); 171813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 171913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch LoadStoreAcquireReleaseOp op = rt.Is32Bits() ? STLXR_w : STLXR_x; 172013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(op | Rs(rs) | Rt2(x31) | Rn(rn) | Rt(rt)); 172113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 172213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 172313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::ldarb(const Register& rt, const Register& rn) { 172413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rt.Is32Bits()); 172513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 172613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(LDAR_b | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt)); 172713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 172813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 172913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::ldaxrb(const Register& rt, const Register& rn) { 173013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rt.Is32Bits()); 173113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 173213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(LDAXR_b | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt)); 173313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 173413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 173513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::stlrb(const Register& rt, const Register& rn) { 173613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rt.Is32Bits()); 173713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 173813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(STLR_b | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt)); 173913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 174013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 174113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::stlxrb(const Register& rs, const Register& rt, 174213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch const Register& rn) { 174313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rs.Is32Bits()); 174413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rt.Is32Bits()); 174513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 174613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(STLXR_b | Rs(rs) | Rt2(x31) | Rn(rn) | Rt(rt)); 174713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 174813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 174913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::ldarh(const Register& rt, const Register& rn) { 175013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rt.Is32Bits()); 175113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 175213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(LDAR_h | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt)); 175313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 175413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 175513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::ldaxrh(const Register& rt, const Register& rn) { 175613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rt.Is32Bits()); 175713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 175813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(LDAXR_h | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt)); 175913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 176013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 176113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::stlrh(const Register& rt, const Register& rn) { 176213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rt.Is32Bits()); 176313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 176413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(STLR_h | Rs(x31) | Rt2(x31) | Rn(rn) | Rt(rt)); 176513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 176613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch 176713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid Assembler::stlxrh(const Register& rs, const Register& rt, 176813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch const Register& rn) { 176913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rs.Is32Bits()); 177013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rt.Is32Bits()); 177113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch DCHECK(rn.Is64Bits()); 177213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch Emit(STLXR_h | Rs(rs) | Rt2(x31) | Rn(rn) | Rt(rt)); 177313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch} 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mov(const Register& rd, const Register& rm) { 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Moves involving the stack pointer are encoded as add immediate with 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // second operand of zero. Otherwise, orr with first operand zr is 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // used. 1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (rd.IsSP() || rm.IsSP()) { 1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(rd, rm, 0); 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch orr(rd, AppropriateZeroRegFor(rd), rm); 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mvn(const Register& rd, const Operand& operand) { 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch orn(rd, AppropriateZeroRegFor(rd), operand); 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::mrs(const Register& rt, SystemRegister sysreg) { 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rt.Is64Bits()); 1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(MRS | ImmSystemRegister(sysreg) | Rt(rt)); 1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::msr(SystemRegister sysreg, const Register& rt) { 1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rt.Is64Bits()); 1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(MSR | Rt(rt) | ImmSystemRegister(sysreg)); 1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::hint(SystemHint code) { 1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(HINT | ImmHint(code) | Rt(xzr)); 1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::dmb(BarrierDomain domain, BarrierType type) { 1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(DMB | ImmBarrierDomain(domain) | ImmBarrierType(type)); 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::dsb(BarrierDomain domain, BarrierType type) { 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(DSB | ImmBarrierDomain(domain) | ImmBarrierType(type)); 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::isb() { 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(ISB | ImmBarrierDomain(FullSystem) | ImmBarrierType(BarrierAll)); 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmov(FPRegister fd, double imm) { 1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.Is64Bits()); 1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsImmFP64(imm)); 1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FMOV_d_imm | Rd(fd) | ImmFP64(imm)); 1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmov(FPRegister fd, float imm) { 1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.Is32Bits()); 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsImmFP32(imm)); 1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FMOV_s_imm | Rd(fd) | ImmFP32(imm)); 1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmov(Register rd, FPRegister fn) { 1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == fn.SizeInBits()); 1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPIntegerConvertOp op = rd.Is32Bits() ? FMOV_ws : FMOV_xd; 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(op | Rd(rd) | Rn(fn)); 1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmov(FPRegister fd, Register rn) { 1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == rn.SizeInBits()); 1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPIntegerConvertOp op = fd.Is32Bits() ? FMOV_sw : FMOV_dx; 1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(op | Rd(fd) | Rn(rn)); 1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmov(FPRegister fd, FPRegister fn) { 1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FPType(fd) | FMOV | Rd(fd) | Rn(fn)); 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fadd(const FPRegister& fd, 1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm) { 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2Source(fd, fn, fm, FADD); 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fsub(const FPRegister& fd, 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm) { 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2Source(fd, fn, fm, FSUB); 1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmul(const FPRegister& fd, 1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm) { 1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2Source(fd, fn, fm, FMUL); 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmadd(const FPRegister& fd, 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa) { 1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMADD_s : FMADD_d); 1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmsub(const FPRegister& fd, 1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa) { 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FMSUB_s : FMSUB_d); 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fnmadd(const FPRegister& fd, 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa) { 1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMADD_s : FNMADD_d); 1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fnmsub(const FPRegister& fd, 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa) { 1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing3Source(fd, fn, fm, fa, fd.Is32Bits() ? FNMSUB_s : FNMSUB_d); 1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fdiv(const FPRegister& fd, 1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm) { 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2Source(fd, fn, fm, FDIV); 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmax(const FPRegister& fd, 1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm) { 1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2Source(fd, fn, fm, FMAX); 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmaxnm(const FPRegister& fd, 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm) { 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2Source(fd, fn, fm, FMAXNM); 1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fmin(const FPRegister& fd, 1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm) { 1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2Source(fd, fn, fm, FMIN); 1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fminnm(const FPRegister& fd, 1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm) { 1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2Source(fd, fn, fm, FMINNM); 1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fabs(const FPRegister& fd, 1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn) { 1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1Source(fd, fn, FABS); 1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fneg(const FPRegister& fd, 1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn) { 1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1Source(fd, fn, FNEG); 1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fsqrt(const FPRegister& fd, 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn) { 1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1Source(fd, fn, FSQRT); 1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::frinta(const FPRegister& fd, 1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn) { 1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1Source(fd, fn, FRINTA); 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::frintm(const FPRegister& fd, 1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn) { 1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1Source(fd, fn, FRINTM); 1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::frintn(const FPRegister& fd, 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn) { 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1Source(fd, fn, FRINTN); 1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid Assembler::frintp(const FPRegister& fd, const FPRegister& fn) { 1989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier DCHECK(fd.SizeInBits() == fn.SizeInBits()); 1990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier FPDataProcessing1Source(fd, fn, FRINTP); 1991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 1992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::frintz(const FPRegister& fd, 1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn) { 1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1Source(fd, fn, FRINTZ); 1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcmp(const FPRegister& fn, 2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm) { 2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fn.SizeInBits() == fm.SizeInBits()); 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FPType(fn) | FCMP | Rm(fm) | Rn(fn)); 2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcmp(const FPRegister& fn, 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double value) { 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(value); 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Although the fcmp instruction can strictly only take an immediate value of 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // +0.0, we don't need to check for -0.0 because the sign of 0.0 doesn't 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // affect the result of the comparison. 2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value == 0.0); 2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FPType(fn) | FCMP_zero | Rn(fn)); 2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fccmp(const FPRegister& fn, 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StatusFlags nzcv, 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond) { 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fn.SizeInBits() == fm.SizeInBits()); 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FPType(fn) | FCCMP | Rm(fm) | Cond(cond) | Rn(fn) | Nzcv(nzcv)); 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcsel(const FPRegister& fd, 2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond) { 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fm.SizeInBits()); 2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FPType(fd) | FCSEL | Rm(fm) | Cond(cond) | Rn(fn) | Rd(fd)); 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::FPConvertToInt(const Register& rd, 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPIntegerConvertOp op) { 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | FPType(fn) | op | Rn(fn) | Rd(rd)); 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcvt(const FPRegister& fd, 2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn) { 2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (fd.Is64Bits()) { 2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert float to double. 2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fn.Is32Bits()); 2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1Source(fd, fn, FCVT_ds); 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert double to float. 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fn.Is64Bits()); 2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1Source(fd, fn, FCVT_sd); 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcvtau(const Register& rd, const FPRegister& fn) { 2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPConvertToInt(rd, fn, FCVTAU); 2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcvtas(const Register& rd, const FPRegister& fn) { 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPConvertToInt(rd, fn, FCVTAS); 2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcvtmu(const Register& rd, const FPRegister& fn) { 2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPConvertToInt(rd, fn, FCVTMU); 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcvtms(const Register& rd, const FPRegister& fn) { 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPConvertToInt(rd, fn, FCVTMS); 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcvtnu(const Register& rd, const FPRegister& fn) { 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPConvertToInt(rd, fn, FCVTNU); 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcvtns(const Register& rd, const FPRegister& fn) { 2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPConvertToInt(rd, fn, FCVTNS); 2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcvtzu(const Register& rd, const FPRegister& fn) { 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPConvertToInt(rd, fn, FCVTZU); 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::fcvtzs(const Register& rd, const FPRegister& fn) { 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPConvertToInt(rd, fn, FCVTZS); 2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::scvtf(const FPRegister& fd, 2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned fbits) { 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (fbits == 0) { 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rn) | FPType(fd) | SCVTF | Rn(rn) | Rd(fd)); 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rn) | FPType(fd) | SCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | 2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Rd(fd)); 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ucvtf(const FPRegister& fd, 2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned fbits) { 2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (fbits == 0) { 2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rn) | FPType(fd) | UCVTF | Rn(rn) | Rd(fd)); 2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rn) | FPType(fd) | UCVTF_fixed | FPScale(64 - fbits) | Rn(rn) | 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Rd(fd)); 2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Assembler::dcptr(Label* label) { 2124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); 2125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (label->is_bound()) { 2126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The label is bound, so it does not need to be updated and the internal 2127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // reference should be emitted. 2128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // In this case, label->pos() returns the offset of the label from the 2130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // start of the buffer. 2131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch internal_reference_positions_.push_back(pc_offset()); 2132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch dc64(reinterpret_cast<uintptr_t>(buffer_ + label->pos())); 2133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t offset; 2135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (label->is_linked()) { 2136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The label is linked, so the internal reference should be added 2137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // onto the end of the label's link chain. 2138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // In this case, label->pos() returns the offset of the last linked 2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // instruction from the start of the buffer. 2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch offset = label->pos() - pc_offset(); 2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(offset != kStartOfLabelLinkChain); 2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The label is unused, so it now becomes linked and the internal 2145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // reference is at the start of the new link chain. 2146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch offset = kStartOfLabelLinkChain; 2147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The instruction at pc is now the last link in the label's chain. 2149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch label->link_to(pc_offset()); 2150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Traditionally the offset to the previous instruction in the chain is 2152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // encoded in the instruction payload (e.g. branch range) but internal 2153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // references are not instructions so while unbound they are encoded as 2154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // two consecutive brk instructions. The two 16-bit immediates are used 2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // to encode the offset. 2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch offset >>= kInstructionSizeLog2; 2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(is_int32(offset)); 2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint32_t high16 = unsigned_bitextract_32(31, 16, offset); 2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint32_t low16 = unsigned_bitextract_32(15, 0, offset); 2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch brk(high16); 2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch brk(low16); 2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Note: 2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Below, a difference in case for the same letter indicates a 2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// negated bit. 2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If b is 1, then B is 0. 2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::ImmFP32(float imm) { 2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsImmFP32(imm)); 2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bits = float_to_rawbits(imm); 2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit7: a000.0000 2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bit7 = ((bits >> 31) & 0x1) << 7; 2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit6: 0b00.0000 2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bit6 = ((bits >> 29) & 0x1) << 6; 2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit5_to_0: 00cd.efgh 2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bit5_to_0 = (bits >> 19) & 0x3f; 2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (bit7 | bit6 | bit5_to_0) << ImmFP_offset; 2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstr Assembler::ImmFP64(double imm) { 2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsImmFP64(imm)); 2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bits: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0000.0000.0000.0000.0000.0000.0000.0000 2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t bits = double_to_rawbits(imm); 2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit7: a000.0000 2192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint64_t bit7 = ((bits >> 63) & 0x1) << 7; 2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit6: 0b00.0000 2194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint64_t bit6 = ((bits >> 61) & 0x1) << 6; 2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit5_to_0: 00cd.efgh 2196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint64_t bit5_to_0 = (bits >> 48) & 0x3f; 2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<Instr>((bit7 | bit6 | bit5_to_0) << ImmFP_offset); 2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code generation helpers. 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::MoveWide(const Register& rd, 2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t imm, 2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int shift, 2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MoveWideImmediateOp mov_op) { 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Ignore the top 32 bits of an immediate if we're moving to a W register. 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (rd.Is32Bits()) { 2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the top 32 bits are zero (a positive 32-bit number) or top 2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 33 bits are one (a negative 32-bit number, sign extended to 64 bits). 2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(((imm >> kWRegSizeInBits) == 0) || 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ((imm >> (kWRegSizeInBits - 1)) == 0x1ffffffff)); 2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm &= kWRegMask; 2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift >= 0) { 2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Explicit shift specified. 2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((shift == 0) || (shift == 16) || (shift == 32) || (shift == 48)); 2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits() || (shift == 0) || (shift == 16)); 2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shift /= 16; 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate a new immediate and shift combination to encode the immediate 2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // argument. 2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shift = 0; 2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((imm & ~0xffffUL) == 0) { 2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Nothing to do. 2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if ((imm & ~(0xffffUL << 16)) == 0) { 2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm >>= 16; 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shift = 1; 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if ((imm & ~(0xffffUL << 32)) == 0) { 2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits()); 2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm >>= 32; 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shift = 2; 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if ((imm & ~(0xffffUL << 48)) == 0) { 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits()); 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm >>= 48; 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shift = 3; 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_uint16(imm)); 2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Emit(SF(rd) | MoveWideImmediateFixed | mov_op | Rd(rd) | 2244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ImmMoveWide(static_cast<int>(imm)) | ShiftMoveWide(shift)); 2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::AddSub(const Register& rd, 2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsUpdate S, 2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubOp op) { 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!operand.NeedsRelocation(this)); 2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (operand.IsImmediate()) { 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t immediate = operand.ImmediateValue(); 2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsImmAddSub(immediate)); 2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd); 2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | AddSubImmediateFixed | op | Flags(S) | 2260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ImmAddSub(static_cast<int>(immediate)) | dest_reg | RnSP(rn)); 2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (operand.IsShiftedRegister()) { 2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(operand.reg().SizeInBits() == rd.SizeInBits()); 2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(operand.shift() != ROR); 2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For instructions of the form: 2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // add/sub wsp, <Wn>, <Wm> [, LSL #0-3 ] 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // add/sub <Wd>, wsp, <Wm> [, LSL #0-3 ] 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // add/sub wsp, wsp, <Wm> [, LSL #0-3 ] 2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // adds/subs <Wd>, wsp, <Wm> [, LSL #0-3 ] 2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // or their 64-bit register equivalents, convert the operand from shifted to 2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // extended register mode, and emit an add/sub extended instruction. 2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (rn.IsSP() || rd.IsSP()) { 2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!(rd.IsSP() && (S == SetFlags))); 2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcExtendedRegister(rd, rn, operand.ToExtendedRegister(), S, 2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubExtendedFixed | op); 2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcShiftedRegister(rd, rn, operand, S, AddSubShiftedFixed | op); 2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(operand.IsExtendedRegister()); 2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcExtendedRegister(rd, rn, operand, S, AddSubExtendedFixed | op); 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::AddSubWithCarry(const Register& rd, 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsUpdate S, 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubWithCarryOp op) { 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == operand.reg().SizeInBits()); 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0)); 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!operand.NeedsRelocation(this)); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | Rn(rn) | Rd(rd)); 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::hlt(int code) { 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_uint16(code)); 2301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(HLT | ImmException(code)); 2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::brk(int code) { 2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_uint16(code)); 2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(BRK | ImmException(code)); 2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::EmitStringData(const char* string) { 2312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t len = strlen(string) + 1; 2313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(RoundUp(len, kInstructionSize) <= static_cast<size_t>(kGap)); 2314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch EmitData(string, static_cast<int>(len)); 2315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pad with NULL characters until pc_ is aligned. 2316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char pad[] = {'\0', '\0', '\0', '\0'}; 2317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(pad) == kInstructionSize); 2318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitData(pad, RoundUp(pc_offset(), kInstructionSize) - pc_offset()); 2319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::debug(const char* message, uint32_t code, Instr params) { 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef USE_SIMULATOR 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't generate simulator specific code if we are building a snapshot, which 2325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // might be run on real hardware. 2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!serializer_enabled()) { 2327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The arguments to the debug marker need to be contiguous in memory, so 2328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // make sure we don't try to emit pools. 2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BlockPoolsScope scope(this); 2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label start; 2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&start); 2333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Refer to instructions-arm64.h for a description of the marker and its 2335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // arguments. 2336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hlt(kImmExceptionIsDebug); 2337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugCodeOffset); 2338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dc32(code); 2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugParamsOffset); 2340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dc32(params); 2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(SizeOfCodeGeneratedSince(&start) == kDebugMessageOffset); 2342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStringData(message); 2343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hlt(kImmExceptionIsUnreachable); 2344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 2346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fall through if Serializer is enabled. 2348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 2349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (params & BREAK) { 2351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch hlt(kImmExceptionIsDebug); 2352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::Logical(const Register& rd, 2357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 2359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LogicalOp op) { 2360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 2361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!operand.NeedsRelocation(this)); 2362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (operand.IsImmediate()) { 2363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t immediate = operand.ImmediateValue(); 2364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned reg_size = rd.SizeInBits(); 2365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(immediate != 0); 2367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(immediate != -1); 2368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.Is64Bits() || is_uint32(immediate)); 2369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the operation is NOT, invert the operation and immediate. 2371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((op & NOT) == NOT) { 2372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch op = static_cast<LogicalOp>(op & ~NOT); 2373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch immediate = rd.Is64Bits() ? ~immediate : (~immediate & kWRegMask); 2374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned n, imm_s, imm_r; 2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsImmLogical(immediate, reg_size, &n, &imm_s, &imm_r)) { 2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Immediate can be encoded in the instruction. 2379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LogicalImmediate(rd, rn, n, imm_s, imm_r, op); 2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This case is handled in the macro assembler. 2382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(operand.IsShiftedRegister()); 2386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(operand.reg().SizeInBits() == rd.SizeInBits()); 2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr dp_op = static_cast<Instr>(op | LogicalShiftedFixed); 2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcShiftedRegister(rd, rn, operand, LeaveFlags, dp_op); 2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::LogicalImmediate(const Register& rd, 2394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned n, 2396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned imm_s, 2397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned imm_r, 2398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LogicalOp op) { 2399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned reg_size = rd.SizeInBits(); 2400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr dest_reg = (op == ANDS) ? Rd(rd) : RdSP(rd); 2401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | LogicalImmediateFixed | op | BitN(n, reg_size) | 2402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImmSetBits(imm_s, reg_size) | ImmRotate(imm_r, reg_size) | dest_reg | 2403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Rn(rn)); 2404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::ConditionalCompare(const Register& rn, 2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 2409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StatusFlags nzcv, 2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond, 2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalCompareOp op) { 2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr ccmpop; 2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!operand.NeedsRelocation(this)); 2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (operand.IsImmediate()) { 2415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t immediate = operand.ImmediateValue(); 2416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsImmConditionalCompare(immediate)); 2417014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ccmpop = ConditionalCompareImmediateFixed | op | 2418014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ImmCondCmp(static_cast<unsigned>(immediate)); 2419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(operand.IsShiftedRegister() && (operand.shift_amount() == 0)); 2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ccmpop = ConditionalCompareRegisterFixed | op | Rm(operand.reg()); 2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rn) | ccmpop | Cond(cond) | Rn(rn) | Nzcv(nzcv)); 2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::DataProcessing1Source(const Register& rd, 2428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing1SourceOp op) { 2430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() == rn.SizeInBits()); 2431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rn) | op | Rn(rn) | Rd(rd)); 2432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::FPDataProcessing1Source(const FPRegister& fd, 2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1SourceOp op) { 2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FPType(fn) | op | Rn(fn) | Rd(fd)); 2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::FPDataProcessing2Source(const FPRegister& fd, 2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 2445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2SourceOp op) { 2446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fn.SizeInBits()); 2447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(fd.SizeInBits() == fm.SizeInBits()); 2448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd)); 2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::FPDataProcessing3Source(const FPRegister& fd, 2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa, 2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing3SourceOp op) { 2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AreSameSizeAndType(fd, fn, fm, fa)); 2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(FPType(fd) | op | Rm(fm) | Rn(fn) | Rd(fd) | Ra(fa)); 2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::EmitShift(const Register& rd, 2463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Shift shift, 2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned shift_amount) { 2466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (shift) { 2467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LSL: 2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lsl(rd, rn, shift_amount); 2469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LSR: 2471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lsr(rd, rn, shift_amount); 2472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ASR: 2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch asr(rd, rn, shift_amount); 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ROR: 2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ror(rd, rn, shift_amount); 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::EmitExtendShift(const Register& rd, 2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Extend extend, 2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned left_shift) { 2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.SizeInBits() >= rn.SizeInBits()); 2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned reg_size = rd.SizeInBits(); 2491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use the correct size of register. 2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rn_ = Register::Create(rn.code(), rd.SizeInBits()); 2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bits extracted are high_bit:0. 2494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned high_bit = (8 << (extend & 0x3)) - 1; 2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Number of bits left in the result that are not introduced by the shift. 2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned non_shift_bits = (reg_size - left_shift) & (reg_size - 1); 2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((non_shift_bits > high_bit) || (non_shift_bits == 0)) { 2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (extend) { 2500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UXTB: 2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UXTH: 2502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UXTW: ubfm(rd, rn_, non_shift_bits, high_bit); break; 2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case SXTB: 2504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case SXTH: 2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case SXTW: sbfm(rd, rn_, non_shift_bits, high_bit); break; 2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UXTX: 2507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case SXTX: { 2508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rn.SizeInBits() == kXRegSizeInBits); 2509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Nothing to extend. Just shift. 2510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lsl(rd, rn_, left_shift); 2511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: UNREACHABLE(); 2514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // No need to extend as the extended bits would be shifted away. 2517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lsl(rd, rn_, left_shift); 2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::DataProcShiftedRegister(const Register& rd, 2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 2525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsUpdate S, 2526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr op) { 2527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(operand.IsShiftedRegister()); 2528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rn.Is64Bits() || (rn.Is32Bits() && is_uint5(operand.shift_amount()))); 2529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!operand.NeedsRelocation(this)); 2530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | op | Flags(S) | 2531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ShiftDP(operand.shift()) | ImmDPShift(operand.shift_amount()) | 2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Rm(operand.reg()) | Rn(rn) | Rd(rd)); 2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::DataProcExtendedRegister(const Register& rd, 2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsUpdate S, 2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr op) { 2541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!operand.NeedsRelocation(this)); 2542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr dest_reg = (S == SetFlags) ? Rd(rd) : RdSP(rd); 2543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(SF(rd) | op | Flags(S) | Rm(operand.reg()) | 2544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtendMode(operand.extend()) | ImmExtendShift(operand.shift_amount()) | 2545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dest_reg | RnSP(rn)); 2546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsImmAddSub(int64_t immediate) { 2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return is_uint12(immediate) || 2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (is_uint12(immediate >> 12) && ((immediate & 0xfff) == 0)); 2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::LoadStore(const CPURegister& rt, 2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& addr, 2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStoreOp op) { 2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr memop = op | Rt(rt) | RnSP(addr.base()); 2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (addr.IsImmediateOffset()) { 2560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LSDataSize size = CalcLSDataSize(op); 2561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IsImmLSScaled(addr.offset(), size)) { 2562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset = static_cast<int>(addr.offset()); 2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use the scaled addressing mode. 2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(LoadStoreUnsignedOffsetFixed | memop | 2565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ImmLSUnsigned(offset >> size)); 2566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (IsImmLSUnscaled(addr.offset())) { 2567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset = static_cast<int>(addr.offset()); 2568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use the unscaled addressing mode. 2569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(LoadStoreUnscaledOffsetFixed | memop | ImmLS(offset)); 2570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This case is handled in the macro assembler. 2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (addr.IsRegisterOffset()) { 2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Extend ext = addr.extend(); 2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Shift shift = addr.shift(); 2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned shift_amount = addr.shift_amount(); 2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // LSL is encoded in the option field as UXTX. 2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (shift == LSL) { 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ext = UXTX; 2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Shifts are encoded in one bit, indicating a left shift by the memory 2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // access size. 2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((shift_amount == 0) || 2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (shift_amount == static_cast<unsigned>(CalcLSDataSize(op)))); 2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(LoadStoreRegisterOffsetFixed | memop | Rm(addr.regoffset()) | 2589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExtendMode(ext) | ImmShiftLS((shift_amount > 0) ? 1 : 0)); 2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pre-index and post-index modes. 2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!rt.Is(addr.base())); 2593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (IsImmLSUnscaled(addr.offset())) { 2594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset = static_cast<int>(addr.offset()); 2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (addr.IsPreIndex()) { 2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(LoadStorePreIndexFixed | memop | ImmLS(offset)); 2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(addr.IsPostIndex()); 2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Emit(LoadStorePostIndexFixed | memop | ImmLS(offset)); 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This case is handled in the macro assembler. 2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsImmLSUnscaled(int64_t offset) { 2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return is_int9(offset); 2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsImmLSScaled(int64_t offset, LSDataSize size) { 2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool offset_is_size_multiple = (((offset >> size) << size) == offset); 2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return offset_is_size_multiple && is_uint12(offset >> size); 2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsImmLSPair(int64_t offset, LSDataSize size) { 2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool offset_is_size_multiple = (((offset >> size) << size) == offset); 2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return offset_is_size_multiple && is_int7(offset >> size); 2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2626014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool Assembler::IsImmLLiteral(int64_t offset) { 2627014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int inst_size = static_cast<int>(kInstructionSizeLog2); 2628014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool offset_is_inst_multiple = 2629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (((offset >> inst_size) << inst_size) == offset); 2630014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return offset_is_inst_multiple && is_intn(offset, ImmLLiteral_width); 2631014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 2632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Test if a given value can be encoded in the immediate field of a logical 2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// instruction. 2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If it can be encoded, the function returns true, and values pointed to by n, 2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// imm_s and imm_r are updated with immediates encoded in the format required 2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// by the corresponding fields in the logical instruction. 2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If it can not be encoded, the function returns false, and the values pointed 2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// to by n, imm_s and imm_r are undefined. 2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsImmLogical(uint64_t value, 2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned width, 2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned* n, 2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned* imm_s, 2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned* imm_r) { 2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((n != NULL) && (imm_s != NULL) && (imm_r != NULL)); 2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((width == kWRegSizeInBits) || (width == kXRegSizeInBits)); 2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool negate = false; 2650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Logical immediates are encoded using parameters n, imm_s and imm_r using 2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the following table: 2653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // N imms immr size S R 2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) 2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) 2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) 2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) 2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) 2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 11110s xxxxxr 2 UInt(s) UInt(r) 2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (s bits must not be all set) 2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A pattern is constructed of size bits, where the least significant S+1 bits 2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // are set. The pattern is rotated right by R, and repeated across a 32 or 2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 64-bit value, depending on destination register width. 2666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Put another way: the basic format of a logical immediate is a single 2668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // contiguous stretch of 1 bits, repeated across the whole word at intervals 2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // given by a power of 2. To identify them quickly, we first locate the 2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // lowest stretch of 1 bits, then the next 1 bit above that; that combination 2671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is different for every logical immediate, so it gives us all the 2672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // information we need to identify the only logical immediate that our input 2673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // could be, and then we simply check if that's the value we actually have. 2674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (The rotation parameter does give the possibility of the stretch of 1 bits 2676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // going 'round the end' of the word. To deal with that, we observe that in 2677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // any situation where that happens the bitwise NOT of the value is also a 2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // valid logical immediate. So we simply invert the input whenever its low bit 2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is set, and then we know that the rotated case can't arise.) 2680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (value & 1) { 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the low bit is 1, negate the value, and set a flag to remember that we 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // did (so that we can adjust the return values appropriately). 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch negate = true; 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value = ~value; 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (width == kWRegSizeInBits) { 2689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // To handle 32-bit logical immediates, the very easiest thing is to repeat 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the input value twice to make a 64-bit word. The correct encoding of that 2691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // as a logical immediate will also be the correct encoding of the 32-bit 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // value. 2693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The most-significant 32 bits may not be zero (ie. negate is true) so 2695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // shift the value left before duplicating it. 2696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value <<= kWRegSizeInBits; 2697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value |= value >> kWRegSizeInBits; 2698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The basic analysis idea: imagine our input word looks like this. 2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0011111000111110001111100011111000111110001111100011111000111110 2703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // c b a 2704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // |<--d-->| 2705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We find the lowest set bit (as an actual power-of-2 value, not its index) 2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and call it a. Then we add a to our original number, which wipes out the 2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bottommost stretch of set bits and replaces it with a 1 carried into the 2709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // next zero bit. Then we look for the new lowest set bit, which is in 2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // position b, and subtract it, so now our number is just like the original 2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // but with the lowest stretch of set bits completely gone. Now we find the 2712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // lowest set bit again, which is position c in the diagram above. Then we'll 2713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // measure the distance d between bit positions a and c (using CLZ), and that 2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tells us that the only valid logical immediate that could possibly be equal 2715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to this number is the one in which a stretch of bits running from a to just 2716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // below b is replicated every d bits. 2717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t a = LargestPowerOf2Divisor(value); 2718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t value_plus_a = value + a; 2719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t b = LargestPowerOf2Divisor(value_plus_a); 2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t value_plus_a_minus_b = value_plus_a - b; 2721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t c = LargestPowerOf2Divisor(value_plus_a_minus_b); 2722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int d, clz_a, out_n; 2724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t mask; 2725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (c != 0) { 2727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The general case, in which there is more than one stretch of set bits. 2728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the repeat distance d, and set up a bitmask covering the basic 2729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // unit of repetition (i.e. a word with the bottom d bits set). Also, in all 2730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of these cases the N bit of the output will be zero. 2731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch clz_a = CountLeadingZeros(a, kXRegSizeInBits); 2732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int clz_c = CountLeadingZeros(c, kXRegSizeInBits); 2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch d = clz_a - clz_c; 2734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mask = ((V8_UINT64_C(1) << d) - 1); 2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_n = 0; 2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle degenerate cases. 2738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If any of those 'find lowest set bit' operations didn't find a set bit at 2740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // all, then the word will have been zero thereafter, so in particular the 2741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // last lowest_set_bit operation will have returned zero. So we can test for 2742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // all the special case conditions in one go by seeing if c is zero. 2743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (a == 0) { 2744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The input was zero (or all 1 bits, which will come to here too after we 2745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // inverted it at the start of the function), for which we just return 2746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // false. 2747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Otherwise, if c was zero but a was not, then there's just one stretch 2750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of set bits in our word, meaning that we have the trivial case of 2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // d == 64 and only one 'repetition'. Set up all the same variables as in 2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the general case above, and set the N bit in the output. 2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch clz_a = CountLeadingZeros(a, kXRegSizeInBits); 2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch d = 64; 2755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mask = ~V8_UINT64_C(0); 2756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch out_n = 1; 2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the repeat period d is not a power of two, it can't be encoded. 2761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IS_POWER_OF_TWO(d)) { 2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (((b - a) & ~mask) != 0) { 2766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the bit stretch (b - a) does not fit within the mask derived from the 2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // repeat period, then fail. 2768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The only possible option is b - a repeated every d bits. Now we're going to 2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // actually construct the valid logical immediate derived from that 2773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // specification, and see if it equals our original input. 2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // To repeat a value every d bits, we multiply it by a number of the form 2776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (1 + 2^d + 2^(2d) + ...), i.e. 0x0001000100010001 or similar. These can 2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // be derived using a table lookup on CLZ(d). 2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint64_t multipliers[] = { 2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0x0000000000000001UL, 2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0x0000000100000001UL, 2781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0x0001000100010001UL, 2782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0x0101010101010101UL, 2783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0x1111111111111111UL, 2784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0x5555555555555555UL, 2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 2786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int multiplier_idx = CountLeadingZeros(d, kXRegSizeInBits) - 57; 2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Ensure that the index to the multipliers array is within bounds. 2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((multiplier_idx >= 0) && 2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (static_cast<size_t>(multiplier_idx) < arraysize(multipliers))); 2790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t multiplier = multipliers[multiplier_idx]; 2791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t candidate = (b - a) * multiplier; 2792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (value != candidate) { 2794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The candidate pattern doesn't match our input value, so fail. 2795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have a match! This is a valid logical immediate, so now we have to 2799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // construct the bits and pieces of the instruction encoding that generates 2800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // it. 2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Count the set bits in our basic stretch. The special case of clz(0) == -1 2803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // makes the answer come out right for stretches that reach the very top of 2804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the word (e.g. numbers like 0xffffc00000000000). 2805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int clz_b = (b == 0) ? -1 : CountLeadingZeros(b, kXRegSizeInBits); 2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int s = clz_a - clz_b; 2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Decide how many bits to rotate right by, to put the low bit of that basic 2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stretch in position a. 2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int r; 2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (negate) { 2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we inverted the input right at the start of this function, here's 2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // where we compensate: the number of set bits becomes the number of clear 2814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bits, and the rotation count is based on position b rather than position 2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a (since b is the location of the 'lowest' 1 bit after inversion). 2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch s = d - s; 2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r = (clz_b + 1) & (d - 1); 2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r = (clz_a + 1) & (d - 1); 2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now we're done, except for having to encode the S output in such a way that 2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // it gives both the number of set bits and the length of the repeated 2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // segment. The s field is encoded like this: 2825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // imms size S 2827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ssssss 64 UInt(ssssss) 2828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0sssss 32 UInt(sssss) 2829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 10ssss 16 UInt(ssss) 2830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 110sss 8 UInt(sss) 2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1110ss 4 UInt(ss) 2832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 11110s 2 UInt(s) 2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // So we 'or' (-d << 1) with our computed s to form imms. 2835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *n = out_n; 2836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *imm_s = ((-d << 1) | (s - 1)) & 0x3f; 2837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *imm_r = r; 2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 2840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsImmConditionalCompare(int64_t immediate) { 2844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return is_uint5(immediate); 2845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsImmFP32(float imm) { 2849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Valid values will have the form: 2850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // aBbb.bbbc.defg.h000.0000.0000.0000.0000 2851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bits = float_to_rawbits(imm); 2852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bits[19..0] are cleared. 2853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((bits & 0x7ffff) != 0) { 2854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bits[29..25] are all set or all cleared. 2858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t b_pattern = (bits >> 16) & 0x3e00; 2859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (b_pattern != 0 && b_pattern != 0x3e00) { 2860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit[30] and bit[29] are opposite. 2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (((bits ^ (bits << 1)) & 0x40000000) == 0) { 2865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 2869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::IsImmFP64(double imm) { 2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Valid values will have the form: 2874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 2875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0000.0000.0000.0000.0000.0000.0000.0000 2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t bits = double_to_rawbits(imm); 2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bits[47..0] are cleared. 2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((bits & 0xffffffffffffL) != 0) { 2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bits[61..54] are all set or all cleared. 2883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t b_pattern = (bits >> 48) & 0x3fc0; 2884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (b_pattern != 0 && b_pattern != 0x3fc0) { 2885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit[62] and bit[61] are opposite. 2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (((bits ^ (bits << 1)) & 0x4000000000000000L) == 0) { 2890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 2891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 2894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::GrowBuffer() { 2898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!own_buffer_) FATAL("external code buffer is too small"); 2899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute new buffer size. 2901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeDesc desc; // the new buffer 2902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (buffer_size_ < 1 * MB) { 2903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch desc.buffer_size = 2 * buffer_size_; 2904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch desc.buffer_size = buffer_size_ + 1 * MB; 2906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_GT(desc.buffer_size, 0); // No overflow. 2908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte* buffer = reinterpret_cast<byte*>(buffer_); 2910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set up new buffer. 2912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch desc.buffer = NewArray<byte>(desc.buffer_size); 2913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch desc.origin = this; 2914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch desc.instr_size = pc_offset(); 2916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch desc.reloc_size = 2917014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<int>((buffer + buffer_size_) - reloc_info_writer.pos()); 2918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy the data. 2920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t pc_delta = desc.buffer - buffer; 2921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t rc_delta = (desc.buffer + desc.buffer_size) - 2922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (buffer + buffer_size_); 2923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memmove(desc.buffer, buffer, desc.instr_size); 2924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memmove(reloc_info_writer.pos() + rc_delta, 2925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info_writer.pos(), desc.reloc_size); 2926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Switch buffers. 2928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeleteArray(buffer_); 2929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_ = desc.buffer; 2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_size_ = desc.buffer_size; 2931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pc_ = reinterpret_cast<byte*>(pc_) + pc_delta; 2932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 2933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info_writer.last_pc() + pc_delta); 2934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // None of our relocation types are pc relative pointing outside the code 2936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // buffer nor pc absolute pointing inside the code buffer, so there is no need 2937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to relocate any emitted relocation entries. 2938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Relocate internal references. 2940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (auto pos : internal_reference_positions_) { 2941014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos); 2942014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch *p += pc_delta; 2943014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2944014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 2945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pending relocation entries are also relative, no need to relocate. 2946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We do not try to reuse pool constants. 2951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo rinfo(isolate(), reinterpret_cast<byte*>(pc_), rmode, data, NULL); 2952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (((rmode >= RelocInfo::COMMENT) && 29533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch (rmode <= RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL)) || 2954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (rmode == RelocInfo::INTERNAL_REFERENCE) || 2955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (rmode == RelocInfo::CONST_POOL) || (rmode == RelocInfo::VENEER_POOL) || 2956c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) || 2957c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch (rmode == RelocInfo::DEOPT_INLINING_ID) || 295862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch (rmode == RelocInfo::DEOPT_REASON) || (rmode == RelocInfo::DEOPT_ID)) { 2959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Adjust code for new modes. 2960014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(RelocInfo::IsDebugBreakSlot(rmode) || RelocInfo::IsComment(rmode) || 2961bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch RelocInfo::IsDeoptReason(rmode) || RelocInfo::IsDeoptId(rmode) || 2962f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch RelocInfo::IsDeoptPosition(rmode) || 2963014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo::IsInternalReference(rmode) || 296462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode)); 2965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // These modes do not need an entry in the constant pool. 2966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch constpool_.RecordEntry(data, rmode); 2968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure the constant pool is not emitted in place of the next 2969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction for which we just recorded relocation info. 2970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BlockConstPoolFor(1); 2971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!RelocInfo::IsNone(rmode)) { 2974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't record external references unless the heap will be serialized. 2975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (rmode == RelocInfo::EXTERNAL_REFERENCE && 2976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !serializer_enabled() && !emit_debug_code()) { 2977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 2978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here 2980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { 2981014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo reloc_info_with_ast_id(isolate(), reinterpret_cast<byte*>(pc_), 2982014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch rmode, RecordedAstId().ToInt(), NULL); 2983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ClearRecordedAstId(); 2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info_writer.Write(&reloc_info_with_ast_id); 2985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info_writer.Write(&rinfo); 2987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::BlockConstPoolFor(int instructions) { 2993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int pc_limit = pc_offset() + instructions * kInstructionSize; 2994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (no_const_pool_before_ < pc_limit) { 2995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch no_const_pool_before_ = pc_limit; 2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure the pool won't be blocked for too long. 2997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(pc_limit < constpool_.MaxPcOffset()); 2998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (next_constant_pool_check_ < no_const_pool_before_) { 3001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_constant_pool_check_ = no_const_pool_before_; 3002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::CheckConstPool(bool force_emit, bool require_jump) { 3007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Some short sequence of instruction mustn't be broken up by constant pool 3008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // emission, such sequences are protected by calls to BlockConstPoolFor and 3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // BlockConstPoolScope. 3010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_const_pool_blocked()) { 3011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Something is wrong if emission is forced and blocked at the same time. 3012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!force_emit); 3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 3014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // There is nothing to do if there are no pending constant pool entries. 3017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (constpool_.IsEmpty()) { 3018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate the offset of the next check. 3019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetNextConstPoolCheckIn(kCheckConstPoolInterval); 3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 3021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We emit a constant pool when: 3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // * requested to do so by parameter force_emit (e.g. after each function). 3025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // * the distance to the first instruction accessing the constant pool is 3026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // kApproxMaxDistToConstPool or more. 3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // * the number of entries in the pool is kApproxMaxPoolEntryCount or more. 3028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int dist = constpool_.DistanceToFirstUse(); 3029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int count = constpool_.EntryCount(); 3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!force_emit && 3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (dist < kApproxMaxDistToConstPool) && 3032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (count < kApproxMaxPoolEntryCount)) { 3033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 3034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit veneers for branches that would go out of range during emission of the 3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // constant pool. 3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int worst_case_size = constpool_.WorstCaseSize(); 3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckVeneerPool(false, require_jump, 3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kVeneerDistanceMargin + worst_case_size); 3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the code buffer is large enough before emitting the constant 3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pool (this includes the gap to the relocation information). 3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int needed_space = worst_case_size + kGap + 1 * kInstructionSize; 3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (buffer_space() <= needed_space) { 3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GrowBuffer(); 3048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label size_check; 3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&size_check); 3052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch constpool_.Emit(require_jump); 3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(SizeOfCodeGeneratedSince(&size_check) <= 3054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<unsigned>(worst_case_size)); 3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Since a constant pool was just emitted, move the check offset forward by 3057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the standard interval. 3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetNextConstPoolCheckIn(kCheckConstPoolInterval); 3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Assembler::ShouldEmitVeneer(int max_reachable_pc, int margin) { 3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Account for the branch around the veneers and the guard. 3064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int protection_offset = 2 * kInstructionSize; 3065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return pc_offset() > max_reachable_pc - margin - protection_offset - 3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<int>(unresolved_branches_.size() * kMaxVeneerCodeSize); 3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::RecordVeneerPool(int location_offset, int size) { 3071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo rinfo(isolate(), buffer_ + location_offset, RelocInfo::VENEER_POOL, 3072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<intptr_t>(size), NULL); 3073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info_writer.Write(&rinfo); 3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::EmitVeneers(bool force_emit, bool need_protection, int margin) { 3078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BlockPoolsScope scope(this); 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordComment("[ Veneers"); 3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The exact size of the veneer pool must be recorded (see the comment at the 3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // declaration site of RecordConstPool()), but computing the number of 3083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // veneers that will be generated is not obvious. So instead we remember the 3084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // current position and will record the size after the pool has been 3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // generated. 3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label size_check; 3087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&size_check); 3088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int veneer_pool_relocinfo_loc = pc_offset(); 3089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label end; 3091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (need_protection) { 3092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch b(&end); 3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVeneersGuard(); 3096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label veneer_size_check; 3098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::multimap<int, FarBranchInfo>::iterator it, it_to_delete; 3100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch it = unresolved_branches_.begin(); 3102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (it != unresolved_branches_.end()) { 3103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (force_emit || ShouldEmitVeneer(it->first, margin)) { 3104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* branch = InstructionAt(it->second.pc_offset_); 3105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* label = it->second.label_; 3106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 3108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&veneer_size_check); 3109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 3110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Patch the branch to point to the current position, and emit a branch 3111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to the label. 3112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* veneer = reinterpret_cast<Instruction*>(pc_); 3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RemoveBranchFromLabelLinkChain(branch, label, veneer); 3114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch branch->SetImmPCOffsetTarget(isolate(), veneer); 3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch b(label); 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(SizeOfCodeGeneratedSince(&veneer_size_check) <= 3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<uint64_t>(kMaxVeneerCodeSize)); 3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch veneer_size_check.Unuse(); 3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch it_to_delete = it++; 3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unresolved_branches_.erase(it_to_delete); 3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ++it; 3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record the veneer pool size. 3130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int pool_size = static_cast<int>(SizeOfCodeGeneratedSince(&size_check)); 3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordVeneerPool(veneer_pool_relocinfo_loc, pool_size); 3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (unresolved_branches_.empty()) { 3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_veneer_pool_check_ = kMaxInt; 3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_veneer_pool_check_ = 3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unresolved_branches_first_limit() - kVeneerDistanceCheckMargin; 3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bind(&end); 3141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordComment("]"); 3143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::CheckVeneerPool(bool force_emit, bool require_jump, 3147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int margin) { 3148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // There is nothing to do if there are no pending veneer pool entries. 3149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (unresolved_branches_.empty()) { 3150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(next_veneer_pool_check_ == kMaxInt); 3151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 3152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(pc_offset() < unresolved_branches_first_limit()); 3155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Some short sequence of instruction mustn't be broken up by veneer pool 3157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // emission, such sequences are protected by calls to BlockVeneerPoolFor and 3158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // BlockVeneerPoolScope. 3159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_veneer_pool_blocked()) { 3160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!force_emit); 3161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 3162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!require_jump) { 3165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prefer emitting veneers protected by an existing instruction. 3166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch margin *= kVeneerNoProtectionFactor; 3167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (force_emit || ShouldEmitVeneers(margin)) { 3169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVeneers(force_emit, require_jump, margin); 3170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 3171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_veneer_pool_check_ = 3172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unresolved_branches_first_limit() - kVeneerDistanceCheckMargin; 3173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Assembler::buffer_space() const { 3178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return static_cast<int>(reloc_info_writer.pos() - 3179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<byte*>(pc_)); 3180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Assembler::RecordConstPool(int size) { 3184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We only need this for debugger support, to correctly compute offsets in the 3185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // code. 3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordRelocInfo(RelocInfo::CONST_POOL, static_cast<intptr_t>(size)); 3187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PatchingAssembler::PatchAdrFar(int64_t target_offset) { 3191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The code at the current instruction should be: 3192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // adr rd, 0 3193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nop (adr_far) 3194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nop (adr_far) 3195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // movz scratch, 0 3196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Verify the expected code. 3198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* expected_adr = InstructionAt(0); 3199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(expected_adr->IsAdr() && (expected_adr->ImmPCRel() == 0)); 3200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int rd_code = expected_adr->Rd(); 3201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < kAdrFarPatchableNNops; ++i) { 3202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(InstructionAt((i + 1) * kInstructionSize)->IsNop(ADR_FAR_NOP)); 3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* expected_movz = 3205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstructionAt((kAdrFarPatchableNInstrs - 1) * kInstructionSize); 3206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(expected_movz->IsMovz() && 3207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (expected_movz->ImmMoveWide() == 0) && 3208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (expected_movz->ShiftMoveWide() == 0)); 3209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int scratch_code = expected_movz->Rd(); 3210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Patch to load the correct address. 3212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register rd = Register::XRegFromCode(rd_code); 3213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = Register::XRegFromCode(scratch_code); 3214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Addresses are only 48 bits. 3215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch adr(rd, target_offset & 0xFFFF); 3216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movz(scratch, (target_offset >> 16) & 0xFFFF, 16); 3217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch movk(scratch, (target_offset >> 32) & 0xFFFF, 32); 3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((target_offset >> 48) == 0); 3219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch add(rd, rd, scratch); 3220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 3224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 3225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_ARM64 3227