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