1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_ARM64_ASSEMBLER_ARM64_H_ 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_ARM64_ASSEMBLER_ARM64_H_ 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <list> 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <map> 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <vector> 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/instructions-arm64.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/globals.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/serialize.h" 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Registers. 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define REGISTER_CODE_LIST(R) \ 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochR(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \ 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochR(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \ 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochR(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \ 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochR(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31) 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte; 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Some CPURegister methods can return Register and FPRegister types, so we 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// need to declare them in advance. 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct Register; 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct FPRegister; 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct CPURegister { 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum RegisterType { 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The kInvalid value is used to detect uninitialized static instances, 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // which are always zero-initialized before any constructors are called. 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kInvalid = 0, 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kRegister, 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kFPRegister, 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kNoRegister 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static CPURegister Create(unsigned code, unsigned size, RegisterType type) { 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister r = {code, size, type}; 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return r; 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned code() const; 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegisterType type() const; 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegList Bit() const; 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned SizeInBits() const; 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int SizeInBytes() const; 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool Is32Bits() const; 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool Is64Bits() const; 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValid() const; 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValidOrNone() const; 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValidRegister() const; 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValidFPRegister() const; 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsNone() const; 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool Is(const CPURegister& other) const; 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool Aliases(const CPURegister& other) const; 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsZero() const; 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsSP() const; 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsRegister() const; 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsFPRegister() const; 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register X() const; 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register W() const; 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPRegister D() const; 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPRegister S() const; 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsSameSizeAndType(const CPURegister& other) const; 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // V8 compatibility. 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is(const CPURegister& other) const { return Is(other); } 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_valid() const { return IsValid(); } 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned reg_code; 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned reg_size; 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegisterType reg_type; 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct Register : public CPURegister { 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register Create(unsigned code, unsigned size) { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register(CPURegister::Create(code, size, CPURegister::kRegister)); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register() { 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_code = 0; 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_size = 0; 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_type = CPURegister::kNoRegister; 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit Register(const CPURegister& r) { 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_code = r.reg_code; 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_size = r.reg_size; 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_type = r.reg_type; 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValidOrNone()); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register(const Register& r) { // NOLINT(runtime/explicit) 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_code = r.reg_code; 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_size = r.reg_size; 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_type = r.reg_type; 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValidOrNone()); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValid() const { 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsRegister() || IsNone()); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return IsValidRegister(); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register XRegFromCode(unsigned code); 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register WRegFromCode(unsigned code); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Start of V8 compatibility section --------------------- 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // These memebers are necessary for compilation. 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A few of them may be unused for now. 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kNumRegisters = kNumberOfRegisters; 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int NumRegisters() { return kNumRegisters; } 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We allow crankshaft to use the following registers: 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - x0 to x15 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - x18 to x24 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - x27 (also context) 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): Register x25 is currently free and could be available for 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // crankshaft, but we don't use it as we might use it as a per function 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // literal pool pointer in the future. 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): Consider storing cp in x25 to have only two ranges. 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We split allocatable registers in three ranges called 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - "low range" 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - "high range" 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - "context" 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned kAllocatableLowRangeBegin = 0; 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned kAllocatableLowRangeEnd = 15; 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned kAllocatableHighRangeBegin = 18; 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned kAllocatableHighRangeEnd = 24; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned kAllocatableContext = 27; 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Gap between low and high ranges. 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kAllocatableRangeGapSize = 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1; 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxNumAllocatableRegisters = 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) + 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1) + 1; // cp 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; } 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return true if the register is one that crankshaft can allocate. 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsAllocatable() const { 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ((reg_code == kAllocatableContext) || 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (reg_code <= kAllocatableLowRangeEnd) || 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ((reg_code >= kAllocatableHighRangeBegin) && 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (reg_code <= kAllocatableHighRangeEnd))); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register FromAllocationIndex(unsigned index) { 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters())); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // cp is the last allocatable register. 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (index == (static_cast<unsigned>(NumAllocatableRegisters() - 1))) { 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return from_code(kAllocatableContext); 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Handle low and high ranges. 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (index <= kAllocatableLowRangeEnd) 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? from_code(index) 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : from_code(index + kAllocatableRangeGapSize); 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const char* AllocationIndexToString(int index) { 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((index >= 0) && (index < NumAllocatableRegisters())); 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((kAllocatableLowRangeBegin == 0) && 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableLowRangeEnd == 15) && 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableHighRangeBegin == 18) && 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableHighRangeEnd == 24) && 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableContext == 27)); 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* const names[] = { 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "x0", "x1", "x2", "x3", "x4", 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "x5", "x6", "x7", "x8", "x9", 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "x10", "x11", "x12", "x13", "x14", 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "x15", "x18", "x19", "x20", "x21", 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "x22", "x23", "x24", "x27", 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return names[index]; 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int ToAllocationIndex(Register reg) { 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg.IsAllocatable()); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned code = reg.code(); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (code == kAllocatableContext) { 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return NumAllocatableRegisters() - 1; 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (code <= kAllocatableLowRangeEnd) 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? code 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : code - kAllocatableRangeGapSize; 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Register from_code(int code) { 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Always return an X register. 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Register::Create(code, kXRegSizeInBits); 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // End of V8 compatibility section ----------------------- 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstruct FPRegister : public CPURegister { 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static FPRegister Create(unsigned code, unsigned size) { 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return FPRegister( 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister::Create(code, size, CPURegister::kFPRegister)); 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPRegister() { 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_code = 0; 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_size = 0; 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_type = CPURegister::kNoRegister; 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit FPRegister(const CPURegister& r) { 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_code = r.reg_code; 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_size = r.reg_size; 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_type = r.reg_type; 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValidOrNone()); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit) 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_code = r.reg_code; 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_size = r.reg_size; 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reg_type = r.reg_type; 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValidOrNone()); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValid() const { 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsFPRegister() || IsNone()); 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return IsValidFPRegister(); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static FPRegister SRegFromCode(unsigned code); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static FPRegister DRegFromCode(unsigned code); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Start of V8 compatibility section --------------------- 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxNumRegisters = kNumberOfFPRegisters; 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Crankshaft can use all the FP registers except: 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - d15 which is used to keep the 0 double value 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - d30 which is used in crankshaft as a double scratch register 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - d31 which is used in the MacroAssembler as a double scratch register 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned kAllocatableLowRangeBegin = 0; 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned kAllocatableLowRangeEnd = 14; 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned kAllocatableHighRangeBegin = 16; 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const unsigned kAllocatableHighRangeEnd = 28; 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const RegList kAllocatableFPRegisters = 0x1fff7fff; 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Gap between low and high ranges. 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kAllocatableRangeGapSize = 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1; 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxNumAllocatableRegisters = 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) + 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; } 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return true if the register is one that crankshaft can allocate. 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsAllocatable() const { 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (Bit() & kAllocatableFPRegisters) != 0; 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static FPRegister FromAllocationIndex(unsigned int index) { 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters())); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (index <= kAllocatableLowRangeEnd) 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? from_code(index) 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : from_code(index + kAllocatableRangeGapSize); 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const char* AllocationIndexToString(int index) { 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((index >= 0) && (index < NumAllocatableRegisters())); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((kAllocatableLowRangeBegin == 0) && 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableLowRangeEnd == 14) && 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableHighRangeBegin == 16) && 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (kAllocatableHighRangeEnd == 28)); 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* const names[] = { 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "d8", "d9", "d10", "d11", "d12", "d13", "d14", 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "d24", "d25", "d26", "d27", "d28" 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return names[index]; 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int ToAllocationIndex(FPRegister reg) { 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg.IsAllocatable()); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned code = reg.code(); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (code <= kAllocatableLowRangeEnd) 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? code 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : code - kAllocatableRangeGapSize; 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static FPRegister from_code(int code) { 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Always return a D register. 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return FPRegister::Create(code, kDRegSizeInBits); 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // End of V8 compatibility section ----------------------- 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSTATIC_ASSERT(sizeof(CPURegister) == sizeof(Register)); 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSTATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister)); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if defined(ARM64_DEFINE_REG_STATICS) 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define INITIALIZE_REGISTER(register_class, name, code, size, type) \ 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister init_##register_class##_##name = {code, size, type}; \ 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const register_class& name = *reinterpret_cast<const register_class*>( \ 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &init_##register_class##_##name) 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ALIAS_REGISTER(register_class, alias, name) \ 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const register_class& alias = *reinterpret_cast<const register_class*>( \ 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &init_##register_class##_##name) 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define INITIALIZE_REGISTER(register_class, name, code, size, type) \ 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extern const register_class& name 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ALIAS_REGISTER(register_class, alias, name) \ 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extern const register_class& alias 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // defined(ARM64_DEFINE_REG_STATICS) 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// No*Reg is used to indicate an unused argument, or an error case. Note that 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// these all compare equal (using the Is() method). The Register and FPRegister 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// variants are provided for convenience. 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochINITIALIZE_REGISTER(Register, NoReg, 0, 0, CPURegister::kNoRegister); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochINITIALIZE_REGISTER(FPRegister, NoFPReg, 0, 0, CPURegister::kNoRegister); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochINITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// v8 compatibility. 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochINITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister); 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DEFINE_REGISTERS(N) \ 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INITIALIZE_REGISTER(Register, w##N, N, \ 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kWRegSizeInBits, CPURegister::kRegister); \ 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INITIALIZE_REGISTER(Register, x##N, N, \ 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kXRegSizeInBits, CPURegister::kRegister); 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER_CODE_LIST(DEFINE_REGISTERS) 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEFINE_REGISTERS 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochINITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits, 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister::kRegister); 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochINITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits, 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister::kRegister); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DEFINE_FPREGISTERS(N) \ 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INITIALIZE_REGISTER(FPRegister, s##N, N, \ 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kSRegSizeInBits, CPURegister::kFPRegister); \ 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INITIALIZE_REGISTER(FPRegister, d##N, N, \ 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDRegSizeInBits, CPURegister::kFPRegister); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochREGISTER_CODE_LIST(DEFINE_FPREGISTERS) 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEFINE_FPREGISTERS 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef INITIALIZE_REGISTER 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Registers aliases. 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, ip0, x16); 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, ip1, x17); 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, wip0, w16); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, wip1, w17); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Root register. 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, root, x26); 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, rr, x26); 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Context pointer register. 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, cp, x27); 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We use a register as a JS stack pointer to overcome the restriction on the 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// architectural SP alignment. 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We chose x28 because it is contiguous with the other specific purpose 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// registers. 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochSTATIC_ASSERT(kJSSPCode == 28); 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, jssp, x28); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, wjssp, w28); 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, fp, x29); 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, lr, x30); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, xzr, x31); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(Register, wzr, w31); 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Keeps the 0 double value. 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(FPRegister, fp_zero, d15); 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Crankshaft double scratch register. 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d29); 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// MacroAssembler double scratch registers. 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(FPRegister, fp_scratch, d30); 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(FPRegister, fp_scratch1, d30); 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochALIAS_REGISTER(FPRegister, fp_scratch2, d31); 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef ALIAS_REGISTER 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochRegister GetAllocatableRegisterThatIsNotOneOf(Register reg1, 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg2 = NoReg, 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg3 = NoReg, 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg4 = NoReg); 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// AreAliased returns true if any of the named registers overlap. Arguments set 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// to NoReg are ignored. The system stack pointer may be specified. 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreAliased(const CPURegister& reg1, 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg2, 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg3 = NoReg, 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg4 = NoReg, 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg5 = NoReg, 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg6 = NoReg, 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg7 = NoReg, 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg8 = NoReg); 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// AreSameSizeAndType returns true if all of the specified registers have the 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// same size, and are of the same type. The system stack pointer may be 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// specified. Arguments set to NoReg are ignored, as are any subsequent 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// arguments. At least one argument (reg1) must be valid (not NoCPUReg). 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool AreSameSizeAndType(const CPURegister& reg1, 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg2, 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg3 = NoCPUReg, 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg4 = NoCPUReg, 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg5 = NoCPUReg, 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg6 = NoCPUReg, 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg7 = NoCPUReg, 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& reg8 = NoCPUReg); 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef FPRegister DoubleRegister; 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Lists of registers. 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CPURegList { 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit CPURegList(CPURegister reg1, 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister reg2 = NoCPUReg, 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister reg3 = NoCPUReg, 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister reg4 = NoCPUReg) 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_(reg1.SizeInBits()), type_(reg1.type()) { 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AreSameSizeAndType(reg1, reg2, reg3, reg4)); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegList(CPURegister::RegisterType type, unsigned size, RegList list) 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : list_(list), size_(size), type_(type) { 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegList(CPURegister::RegisterType type, unsigned size, 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned first_reg, unsigned last_reg) 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : size_(size), type_(type) { 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(((type == CPURegister::kRegister) && 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (last_reg < kNumberOfRegisters)) || 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ((type == CPURegister::kFPRegister) && 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (last_reg < kNumberOfFPRegisters))); 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(last_reg >= first_reg); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list_ = (1UL << (last_reg + 1)) - 1; 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list_ &= ~((1UL << first_reg) - 1); 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister::RegisterType type() const { 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return type_; 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegList list() const { 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return list_; 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void set_list(RegList new_list) { 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch list_ = new_list; 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Combine another CPURegList into this one. Registers that already exist in 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this list are left unchanged. The type and size of the registers in the 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 'other' list must match those in this list. 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Combine(const CPURegList& other); 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove every register in the other CPURegList from this one. Registers that 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // do not exist in this list are ignored. The type of the registers in the 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 'other' list must match those in this list. 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Remove(const CPURegList& other); 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Variants of Combine and Remove which take CPURegisters. 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Combine(const CPURegister& other); 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Remove(const CPURegister& other1, 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& other2 = NoCPUReg, 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& other3 = NoCPUReg, 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& other4 = NoCPUReg); 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Variants of Combine and Remove which take a single register by its code; 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the type and size of the register is inferred from this list. 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Combine(int code); 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Remove(int code); 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove all callee-saved registers from the list. This can be useful when 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // preparing registers for an AAPCS64 function call, for example. 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RemoveCalleeSaved(); 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister PopLowestIndex(); 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister PopHighestIndex(); 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // AAPCS64 callee-saved registers. 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static CPURegList GetCalleeSaved(unsigned size = kXRegSizeInBits); 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static CPURegList GetCalleeSavedFP(unsigned size = kDRegSizeInBits); 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // AAPCS64 caller-saved registers. Note that this includes lr. 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static CPURegList GetCallerSaved(unsigned size = kXRegSizeInBits); 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static CPURegList GetCallerSavedFP(unsigned size = kDRegSizeInBits); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Registers saved as safepoints. 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static CPURegList GetSafepointSavedRegisters(); 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsEmpty() const { 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return list_ == 0; 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IncludesAliasOf(const CPURegister& other1, 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& other2 = NoCPUReg, 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& other3 = NoCPUReg, 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& other4 = NoCPUReg) const { 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegList list = 0; 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!other1.IsNone() && (other1.type() == type_)) list |= other1.Bit(); 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!other2.IsNone() && (other2.type() == type_)) list |= other2.Bit(); 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!other3.IsNone() && (other3.type() == type_)) list |= other3.Bit(); 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!other4.IsNone() && (other4.type() == type_)) list |= other4.Bit(); 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (list_ & list) != 0; 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int Count() const { 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CountSetBits(list_, kRegListSizeInBits); 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned RegisterSizeInBits() const { 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return size_; 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned RegisterSizeInBytes() const { 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int size_in_bits = RegisterSizeInBits(); 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((size_in_bits % kBitsPerByte) == 0); 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return size_in_bits / kBitsPerByte; 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned TotalSizeInBytes() const { 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsValid()); 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return RegisterSizeInBytes() * Count(); 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegList list_; 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned size_; 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CPURegister::RegisterType type_; 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsValid() const { 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const RegList kValidRegisters = 0x8000000ffffffff; 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const RegList kValidFPRegisters = 0x0000000ffffffff; 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (type_) { 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CPURegister::kRegister: 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (list_ & kValidRegisters) == list_; 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CPURegister::kFPRegister: 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (list_ & kValidFPRegisters) == list_; 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CPURegister::kNoRegister: 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return list_ == 0; 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// AAPCS64 callee-saved registers. 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kCalleeSaved CPURegList::GetCalleeSaved() 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kCalleeSavedFP CPURegList::GetCalleeSavedFP() 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// AAPCS64 caller-saved registers. Note that this includes lr. 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kCallerSaved CPURegList::GetCallerSaved() 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define kCallerSavedFP CPURegList::GetCallerSavedFP() 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Immediates. 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Immediate { 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename T> 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline explicit Immediate(Handle<T> handle); 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is allowed to be an implicit constructor because Immediate is 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a wrapper class that doesn't normally perform any type conversion. 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename T> 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Immediate(T value); // NOLINT(runtime/explicit) 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename T> 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Immediate(T value, RelocInfo::Mode rmode); 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t value() const { return value_; } 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode rmode() const { return rmode_; } 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void InitializeHandle(Handle<Object> value); 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t value_; 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::Mode rmode_; 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Operands. 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int kSmiShift = kSmiTagSize + kSmiShiftSize; 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1; 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Represents an operand in a machine instruction. 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Operand { 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): If necessary, study more in details which methods 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): should be inlined or not. 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rm, {<shift> {#<shift_amount>}} 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // where <shift> is one of {LSL, LSR, ASR, ROR}. 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <shift_amount> is uint6_t. 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is allowed to be an implicit constructor because Operand is 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a wrapper class that doesn't normally perform any type conversion. 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Operand(Register reg, 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Shift shift = LSL, 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned shift_amount = 0); // NOLINT(runtime/explicit) 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rm, <extend> {#<shift_amount>} 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}. 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // <shift_amount> is uint2_t. 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Operand(Register reg, 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Extend extend, 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned shift_amount = 0); 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename T> 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline explicit Operand(Handle<T> handle); 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Implicit constructor for all int types, ExternalReference, and Smi. 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename T> 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Operand(T t); // NOLINT(runtime/explicit) 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Implicit constructor for int types. 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch template<typename T> 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Operand(T t, RelocInfo::Mode rmode); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool IsImmediate() const; 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool IsShiftedRegister() const; 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool IsExtendedRegister() const; 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool IsZero() const; 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This returns an LSL shift (<= 4) operand as an equivalent extend operand, 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // which helps in the encoding of instructions that use the stack pointer. 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Operand ToExtendedRegister() const; 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Immediate immediate() const; 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int64_t ImmediateValue() const; 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Register reg() const; 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Shift shift() const; 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Extend extend() const; 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline unsigned shift_amount() const; 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Relocation information. 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool NeedsRelocation(const Assembler* assembler) const; 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Helpers 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Operand UntagSmi(Register smi); 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Operand UntagSmiAndScale(Register smi, int scale); 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate immediate_; 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg_; 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Shift shift_; 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Extend extend_; 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned shift_amount_; 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// MemOperand represents a memory operand in a load or store instruction. 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MemOperand { 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline MemOperand(); 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline explicit MemOperand(Register base, 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t offset = 0, 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddrMode addrmode = Offset); 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline explicit MemOperand(Register base, 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register regoffset, 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Shift shift = LSL, 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned shift_amount = 0); 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline explicit MemOperand(Register base, 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register regoffset, 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Extend extend, 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned shift_amount = 0); 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline explicit MemOperand(Register base, 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& offset, 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddrMode addrmode = Offset); 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& base() const { return base_; } 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& regoffset() const { return regoffset_; } 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t offset() const { return offset_; } 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddrMode addrmode() const { return addrmode_; } 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Shift shift() const { return shift_; } 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Extend extend() const { return extend_; } 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned shift_amount() const { return shift_amount_; } 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool IsImmediateOffset() const; 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool IsRegisterOffset() const; 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool IsPreIndex() const; 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline bool IsPostIndex() const; 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For offset modes, return the offset as an Operand. This helper cannot 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // handle indexed modes. 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline Operand OffsetAsOperand() const; 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum PairResult { 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kNotPair, // Can't use a pair instruction. 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPairAB, // Can use a pair instruction (operandA has lower address). 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPairBA // Can use a pair instruction (operandB has lower address). 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if two MemOperand are consistent for stp/ldp use. 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static PairResult AreConsistentForPair(const MemOperand& operandA, 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& operandB, 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int access_size_log2 = kXRegSizeLog2); 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register base_; 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register regoffset_; 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t offset_; 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddrMode addrmode_; 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Shift shift_; 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Extend extend_; 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned shift_amount_; 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ConstPool { 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit ConstPool(Assembler* assm) 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : assm_(assm), 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch first_use_(-1), 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch shared_entries_count(0) {} 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordEntry(intptr_t data, RelocInfo::Mode mode); 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int EntryCount() const { 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return shared_entries_count + unique_entries_.size(); 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsEmpty() const { 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return shared_entries_.empty() && unique_entries_.empty(); 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Distance in bytes between the current pc and the first instruction 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // using the pool. If there are no pending entries return kMaxInt. 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int DistanceToFirstUse(); 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Offset after which instructions using the pool will be out of range. 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int MaxPcOffset(); 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Maximum size the constant pool can be with current entries. It always 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // includes alignment padding and branch over. 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int WorstCaseSize(); 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Size in bytes of the literal pool *if* it is emitted at the current 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pc. The size will include the branch over the pool if it was requested. 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int SizeIfEmittedAtCurrentPc(bool require_jump); 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the literal pool at the current pc with a branch over the pool if 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // requested. 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Emit(bool require_jump); 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Discard any pending pool entries. 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Clear(); 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool CanBeShared(RelocInfo::Mode mode); 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitMarker(); 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitGuard(); 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitEntries(); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler* assm_; 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep track of the first instruction requiring a constant pool entry 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // since the previous constant pool was emitted. 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int first_use_; 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values, pc offset(s) of entries which can be shared. 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::multimap<uint64_t, int> shared_entries_; 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Number of distinct literal in shared entries. 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int shared_entries_count; 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // values, pc offset of entries which cannot be shared. 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::vector<std::pair<uint64_t, int> > unique_entries_; 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------- 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Assembler. 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Assembler : public AssemblerBase { 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create an assembler. Instructions and relocation information are emitted 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // into a buffer, with the instructions starting from the beginning and the 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // relocation information starting from the end of the buffer. See CodeDesc 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for a detailed comment on the layout (globals.h). 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the provided buffer is NULL, the assembler allocates and grows its own 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // buffer, and buffer_size determines the initial buffer size. The buffer is 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // owned by the assembler and deallocated upon destruction of the assembler. 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the provided buffer is not NULL, the assembler uses the provided buffer 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // for code generation and assumes its size to be buffer_size. If the buffer 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is too small, a fatal error occurs. No deallocation of the buffer is done 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // upon destruction of the assembler. 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler(Isolate* arg_isolate, void* buffer, int buffer_size); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual ~Assembler(); 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void AbortedCodeGeneration() { 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch constpool_.Clear(); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // System functions --------------------------------------------------------- 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Start generating code from the beginning of the buffer, discarding any code 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and data that has already been emitted into the buffer. 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In order to avoid any accidental transfer of state, Reset DCHECKs that the 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // constant pool is not blocked. 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Reset(); 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // GetCode emits any pending (non-emitted) code and fills the descriptor 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // desc. GetCode() is idempotent; it returns the same result if no other 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assembler functions are invoked in between GetCode() calls. 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The descriptor (desc) can be NULL. In that case, the code is finalized as 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // usual, but the descriptor is not populated. 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GetCode(CodeDesc* desc); 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Insert the smallest number of nop instructions 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // possible to align the pc offset to a multiple 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of m. m must be a power of 2 (>= 4). 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Align(int m); 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void Unreachable(); 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Label -------------------------------------------------------------------- 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bind a label to the current pc. Note that labels can only be bound once, 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and if labels are linked to other instructions, they _must_ be bound 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // before they go out of scope. 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bind(Label* label); 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // RelocInfo and pools ------------------------------------------------------ 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record relocation information for current pc_. 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the address in the constant pool of the code target address used by 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the branch/call instruction at pc. 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Address target_pointer_address_at(Address pc); 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Read/Modify the code target address in the branch/call instruction at pc. 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Address target_address_at(Address pc, 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConstantPoolArray* constant_pool); 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static void set_target_address_at(Address pc, 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConstantPoolArray* constant_pool, 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address target, 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ICacheFlushMode icache_flush_mode = 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLUSH_ICACHE_IF_NEEDED); 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline Address target_address_at(Address pc, Code* code); 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline void set_target_address_at(Address pc, 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* code, 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address target, 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ICacheFlushMode icache_flush_mode = 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FLUSH_ICACHE_IF_NEEDED); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the code target address at a call site from the return address of 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that call in the instruction stream. 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Address target_address_from_return_address(Address pc); 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Given the address of the beginning of a call, return the address in the 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction stream that call will return from. 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Address return_address_from_call_start(Address pc); 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the code target address of the patch debug break slot 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Address break_address_from_return_address(Address pc); 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This sets the branch destination (which is in the constant pool on ARM). 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is for calls and branches within generated code. 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static void deserialization_set_special_target_at( 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address constant_pool_entry, Code* code, Address target); 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All addresses in the constant pool are the same size as pointers. 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kSpecialTargetSize = kPointerSize; 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The sizes of the call sequences emitted by MacroAssembler::Call. 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Wherever possible, use MacroAssembler::CallSize instead of these constants, 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // as it will choose the correct value for a given relocation mode. 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Without relocation: 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // movz temp, #(target & 0x000000000000ffff) 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // movk temp, #(target & 0x00000000ffff0000) 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // movk temp, #(target & 0x0000ffff00000000) 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // blr temp 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // With relocation: 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ldr temp, =target 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // blr temp 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kCallSizeWithoutRelocation = 4 * kInstructionSize; 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kCallSizeWithRelocation = 2 * kInstructionSize; 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Size of the generated code in bytes 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t SizeOfGeneratedCode() const { 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_))); 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return pc_ - buffer_; 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the code size generated from label to the current position. 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t SizeOfCodeGeneratedSince(const Label* label) { 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(label->is_bound()); 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(pc_offset() >= label->pos()); 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(pc_offset() < buffer_size_); 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return pc_offset() - label->pos(); 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the size of the code generated since the given label. This function 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is used primarily to work around comparisons between signed and unsigned 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // quantities, since V8 uses both. 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(jbramley): Work out what sign to use for these things and if possible, 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // change things to be consistent. 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AssertSizeOfCodeGeneratedSince(const Label* label, ptrdiff_t size) { 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(size >= 0); 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(static_cast<uint64_t>(size) == SizeOfCodeGeneratedSince(label)); 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the number of instructions generated from label to the 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // current position. 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int InstructionsGeneratedSince(const Label* label) { 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return SizeOfCodeGeneratedSince(label) / kInstructionSize; 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Number of instructions generated for the return sequence in 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FullCodeGenerator::EmitReturnSequence. 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kJSRetSequenceInstructions = 7; 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Distance between start of patched return sequence and the emitted address 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to jump to. 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPatchReturnSequenceAddressOffset = 0; 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPatchDebugBreakSlotAddressOffset = 0; 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Number of instructions necessary to be able to later patch it to a call. 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // See DebugCodegen::GenerateSlot() and 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // BreakLocationIterator::SetDebugBreakAtSlot(). 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kDebugBreakSlotInstructions = 4; 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kDebugBreakSlotLength = 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDebugBreakSlotInstructions * kInstructionSize; 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstructionSize; 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prevent contant pool emission until EndBlockConstPool is called. 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call to this function can be nested but must be followed by an equal 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // number of call to EndBlockConstpool. 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void StartBlockConstPool(); 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Resume constant pool emission. Need to be called as many time as 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // StartBlockConstPool to have an effect. 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EndBlockConstPool(); 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_const_pool_blocked() const; 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsConstantPoolAt(Instruction* instr); 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static int ConstantPoolSizeAt(Instruction* instr); 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // See Assembler::CheckConstPool for more info. 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitPoolGuard(); 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prevent veneer pool emission until EndBlockVeneerPool is called. 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call to this function can be nested but must be followed by an equal 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // number of call to EndBlockConstpool. 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void StartBlockVeneerPool(); 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Resume constant pool emission. Need to be called as many time as 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // StartBlockVeneerPool to have an effect. 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EndBlockVeneerPool(); 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_veneer_pool_blocked() const { 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return veneer_pool_blocked_nesting_ > 0; 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Block/resume emission of constant pools and veneer pools. 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void StartBlockPools() { 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StartBlockConstPool(); 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StartBlockVeneerPool(); 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EndBlockPools() { 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EndBlockConstPool(); 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EndBlockVeneerPool(); 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Debugging ---------------------------------------------------------------- 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PositionsRecorder* positions_recorder() { return &positions_recorder_; } 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordComment(const char* msg); 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int buffer_space() const; 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mark address of the ExitJSFrame code. 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordJSReturn(); 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Mark address of a debug break slot. 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordDebugBreakSlot(); 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record the emission of a constant pool. 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The emission of constant and veneer pools depends on the size of the code 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // generated and the number of RelocInfo recorded. 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The Debug mechanism needs to map code offsets between two versions of a 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // function, compiled with and without debugger support (see for example 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Debug::PrepareForBreakPoints()). 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compiling functions with debugger support generates additional code 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (DebugCodegen::GenerateSlot()). This may affect the emission of the pools 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and cause the version of the code with debugger support to have pools 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // generated in different places. 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Recording the position and size of emitted pools allows to correctly 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // compute the offset mappings between the different versions of a function in 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // all situations. 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The parameter indicates the size of the pool (in bytes), including 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the marker and branch over the data. 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordConstPool(int size); 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Instruction set functions ------------------------------------------------ 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branch / Jump instructions. 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For branches offsets are scaled, i.e. they in instrcutions not in bytes. 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branch to register. 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void br(const Register& xn); 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branch-link to register. 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void blr(const Register& xn); 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branch to register with return hint. 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ret(const Register& xn = lr); 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unconditional branch to label. 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void b(Label* label); 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional branch to label. 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void b(Label* label, Condition cond); 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unconditional branch to PC offset. 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void b(int imm26); 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional branch to PC offset. 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void b(int imm19, Condition cond); 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branch-link to label / pc offset. 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bl(Label* label); 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bl(int imm26); 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compare and branch to label / pc offset if zero. 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cbz(const Register& rt, Label* label); 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cbz(const Register& rt, int imm19); 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compare and branch to label / pc offset if not zero. 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cbnz(const Register& rt, Label* label); 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cbnz(const Register& rt, int imm19); 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Test bit and branch to label / pc offset if zero. 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tbz(const Register& rt, unsigned bit_pos, Label* label); 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tbz(const Register& rt, unsigned bit_pos, int imm14); 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Test bit and branch to label / pc offset if not zero. 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tbnz(const Register& rt, unsigned bit_pos, Label* label); 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tbnz(const Register& rt, unsigned bit_pos, int imm14); 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Address calculation instructions. 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Calculate a PC-relative address. Unlike for branches the offset in adr is 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // unscaled (i.e. the result can be unaligned). 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void adr(const Register& rd, Label* label); 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void adr(const Register& rd, int imm21); 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Data Processing instructions. 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add. 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void add(const Register& rd, 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add and update status flags. 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void adds(const Register& rd, 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compare negative. 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cmn(const Register& rn, const Operand& operand); 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Subtract. 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sub(const Register& rd, 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Subtract and update status flags. 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void subs(const Register& rd, 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compare. 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cmp(const Register& rn, const Operand& operand); 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Negate. 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void neg(const Register& rd, 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Negate and update status flags. 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void negs(const Register& rd, 1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add with carry bit. 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void adc(const Register& rd, 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add with carry bit and update status flags. 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void adcs(const Register& rd, 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Subtract with carry bit. 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sbc(const Register& rd, 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Subtract with carry bit and update status flags. 1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sbcs(const Register& rd, 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Negate with carry bit. 1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ngc(const Register& rd, 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Negate with carry bit and update status flags. 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ngcs(const Register& rd, 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Logical instructions. 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitwise and (A & B). 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void and_(const Register& rd, 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitwise and (A & B) and update status flags. 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ands(const Register& rd, 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bit test, and set flags. 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void tst(const Register& rn, const Operand& operand); 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bit clear (A & ~B). 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bic(const Register& rd, 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bit clear (A & ~B) and update status flags. 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bics(const Register& rd, 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand); 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitwise or (A | B). 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void orr(const Register& rd, const Register& rn, const Operand& operand); 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitwise nor (A | ~B). 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void orn(const Register& rd, const Register& rn, const Operand& operand); 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitwise eor/xor (A ^ B). 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void eor(const Register& rd, const Register& rn, const Operand& operand); 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitwise enor/xnor (A ^ ~B). 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void eon(const Register& rd, const Register& rn, const Operand& operand); 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Logical shift left variable. 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lslv(const Register& rd, const Register& rn, const Register& rm); 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Logical shift right variable. 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lsrv(const Register& rd, const Register& rn, const Register& rm); 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Arithmetic shift right variable. 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void asrv(const Register& rd, const Register& rn, const Register& rm); 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Rotate right variable. 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void rorv(const Register& rd, const Register& rn, const Register& rm); 1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitfield instructions. 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitfield move. 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bfm(const Register& rd, 1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned immr, 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned imms); 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signed bitfield move. 1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sbfm(const Register& rd, 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned immr, 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned imms); 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsigned bitfield move. 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ubfm(const Register& rd, 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned immr, 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned imms); 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bfm aliases. 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitfield insert. 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bfi(const Register& rd, 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned lsb, 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned width) { 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(width >= 1); 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(lsb + width <= rn.SizeInBits()); 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bitfield extract and insert low. 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void bfxil(const Register& rd, 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned lsb, 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned width) { 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(width >= 1); 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(lsb + width <= rn.SizeInBits()); 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bfm(rd, rn, lsb, lsb + width - 1); 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sbfm aliases. 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Arithmetic shift right. 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void asr(const Register& rd, const Register& rn, unsigned shift) { 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(shift < rd.SizeInBits()); 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sbfm(rd, rn, shift, rd.SizeInBits() - 1); 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signed bitfield insert in zero. 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sbfiz(const Register& rd, 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned lsb, 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned width) { 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(width >= 1); 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(lsb + width <= rn.SizeInBits()); 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sbfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signed bitfield extract. 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sbfx(const Register& rd, 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned lsb, 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned width) { 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(width >= 1); 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(lsb + width <= rn.SizeInBits()); 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sbfm(rd, rn, lsb, lsb + width - 1); 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signed extend byte. 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sxtb(const Register& rd, const Register& rn) { 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sbfm(rd, rn, 0, 7); 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signed extend halfword. 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sxth(const Register& rd, const Register& rn) { 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sbfm(rd, rn, 0, 15); 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signed extend word. 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sxtw(const Register& rd, const Register& rn) { 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch sbfm(rd, rn, 0, 31); 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Ubfm aliases. 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Logical shift left. 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lsl(const Register& rd, const Register& rn, unsigned shift) { 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned reg_size = rd.SizeInBits(); 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(shift < reg_size); 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1); 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Logical shift right. 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void lsr(const Register& rd, const Register& rn, unsigned shift) { 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(shift < rd.SizeInBits()); 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ubfm(rd, rn, shift, rd.SizeInBits() - 1); 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsigned bitfield insert in zero. 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ubfiz(const Register& rd, 1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned lsb, 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned width) { 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(width >= 1); 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(lsb + width <= rn.SizeInBits()); 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ubfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1); 1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsigned bitfield extract. 1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ubfx(const Register& rd, 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned lsb, 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned width) { 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(width >= 1); 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(lsb + width <= rn.SizeInBits()); 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ubfm(rd, rn, lsb, lsb + width - 1); 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsigned extend byte. 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void uxtb(const Register& rd, const Register& rn) { 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ubfm(rd, rn, 0, 7); 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsigned extend halfword. 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void uxth(const Register& rd, const Register& rn) { 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ubfm(rd, rn, 0, 15); 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsigned extend word. 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void uxtw(const Register& rd, const Register& rn) { 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ubfm(rd, rn, 0, 31); 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Extract. 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void extr(const Register& rd, 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned lsb); 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional select: rd = cond ? rn : rm. 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void csel(const Register& rd, 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond); 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional select increment: rd = cond ? rn : rm + 1. 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void csinc(const Register& rd, 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond); 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional select inversion: rd = cond ? rn : ~rm. 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void csinv(const Register& rd, 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond); 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional select negation: rd = cond ? rn : -rm. 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void csneg(const Register& rd, 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond); 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional set: rd = cond ? 1 : 0. 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cset(const Register& rd, Condition cond); 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional set minus: rd = cond ? -1 : 0. 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void csetm(const Register& rd, Condition cond); 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional increment: rd = cond ? rn + 1 : rn. 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cinc(const Register& rd, const Register& rn, Condition cond); 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional invert: rd = cond ? ~rn : rn. 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cinv(const Register& rd, const Register& rn, Condition cond); 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional negate: rd = cond ? -rn : rn. 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cneg(const Register& rd, const Register& rn, Condition cond); 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Extr aliases. 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ror(const Register& rd, const Register& rs, unsigned shift) { 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch extr(rd, rs, rs, shift); 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional comparison. 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional compare negative. 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ccmn(const Register& rn, 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StatusFlags nzcv, 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond); 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Conditional compare. 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ccmp(const Register& rn, 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StatusFlags nzcv, 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond); 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Multiplication. 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 32 x 32 -> 32-bit and 64 x 64 -> 64-bit multiply. 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mul(const Register& rd, const Register& rn, const Register& rm); 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 32 + 32 x 32 -> 32-bit and 64 + 64 x 64 -> 64-bit multiply accumulate. 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void madd(const Register& rd, 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra); 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -(32 x 32) -> 32-bit and -(64 x 64) -> 64-bit multiply. 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mneg(const Register& rd, const Register& rn, const Register& rm); 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 32 - 32 x 32 -> 32-bit and 64 - 64 x 64 -> 64-bit multiply subtract. 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void msub(const Register& rd, 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra); 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 32 x 32 -> 64-bit multiply. 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void smull(const Register& rd, const Register& rn, const Register& rm); 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Xd = bits<127:64> of Xn * Xm. 1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void smulh(const Register& rd, const Register& rn, const Register& rm); 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signed 32 x 32 -> 64-bit multiply and accumulate. 1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void smaddl(const Register& rd, 1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra); 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsigned 32 x 32 -> 64-bit multiply and accumulate. 1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void umaddl(const Register& rd, 1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra); 1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signed 32 x 32 -> 64-bit multiply and subtract. 1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void smsubl(const Register& rd, 1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra); 1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsigned 32 x 32 -> 64-bit multiply and subtract. 1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void umsubl(const Register& rd, 1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra); 1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Signed integer divide. 1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void sdiv(const Register& rd, const Register& rn, const Register& rm); 1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unsigned integer divide. 1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void udiv(const Register& rd, const Register& rn, const Register& rm); 1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Bit count, bit reverse and endian reverse. 1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void rbit(const Register& rd, const Register& rn); 1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void rev16(const Register& rd, const Register& rn); 1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void rev32(const Register& rd, const Register& rn); 1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void rev(const Register& rd, const Register& rn); 1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void clz(const Register& rd, const Register& rn); 1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void cls(const Register& rd, const Register& rn); 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Memory instructions. 1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load integer or FP register. 1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldr(const CPURegister& rt, const MemOperand& src); 1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store integer or FP register. 1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void str(const CPURegister& rt, const MemOperand& dst); 1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load word with sign extension. 1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldrsw(const Register& rt, const MemOperand& src); 1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load byte. 1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldrb(const Register& rt, const MemOperand& src); 1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store byte. 1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void strb(const Register& rt, const MemOperand& dst); 1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load byte with sign extension. 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldrsb(const Register& rt, const MemOperand& src); 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load half-word. 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldrh(const Register& rt, const MemOperand& src); 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store half-word. 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void strh(const Register& rt, const MemOperand& dst); 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load half-word with sign extension. 1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldrsh(const Register& rt, const MemOperand& src); 1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load integer or FP register pair. 1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldp(const CPURegister& rt, const CPURegister& rt2, 1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& src); 1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store integer or FP register pair. 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void stp(const CPURegister& rt, const CPURegister& rt2, 1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& dst); 1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load word pair with sign extension. 1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src); 1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load integer or FP register pair, non-temporal. 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldnp(const CPURegister& rt, const CPURegister& rt2, 1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& src); 1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store integer or FP register pair, non-temporal. 1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void stnp(const CPURegister& rt, const CPURegister& rt2, 1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& dst); 1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load literal to register from a pc relative address. 1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldr_pcrel(const CPURegister& rt, int imm19); 1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load literal to register. 1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ldr(const CPURegister& rt, const Immediate& imm); 1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move instructions. The default shift of -1 indicates that the move 1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction will calculate an appropriate 16-bit immediate and left shift 1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that is equal to the 64-bit immediate argument. If an explicit left shift 1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value. 1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For movk, an explicit shift can be used to indicate which half word should 1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant 1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // half word with zero, whereas movk(x0, 0, 48) will overwrite the 1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // most-significant. 1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move and keep. 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void movk(const Register& rd, uint64_t imm, int shift = -1) { 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MoveWide(rd, imm, shift, MOVK); 1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move with non-zero. 1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void movn(const Register& rd, uint64_t imm, int shift = -1) { 1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MoveWide(rd, imm, shift, MOVN); 1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move with zero. 1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void movz(const Register& rd, uint64_t imm, int shift = -1) { 1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MoveWide(rd, imm, shift, MOVZ); 1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Misc instructions. 1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Monitor debug-mode breakpoint. 1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void brk(int code); 1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Halting debug-mode breakpoint. 1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void hlt(int code); 1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move register to register. 1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mov(const Register& rd, const Register& rn); 1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move NOT(operand) to register. 1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mvn(const Register& rd, const Operand& operand); 1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // System instructions. 1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move to register from system register. 1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void mrs(const Register& rt, SystemRegister sysreg); 1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move from register to system register. 1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void msr(SystemRegister sysreg, const Register& rt); 1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // System hint. 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void hint(SystemHint code); 1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Data memory barrier 1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dmb(BarrierDomain domain, BarrierType type); 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Data synchronization barrier 1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dsb(BarrierDomain domain, BarrierType type); 1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Instruction synchronization barrier 1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void isb(); 1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Alias for system instructions. 1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void nop() { hint(NOP); } 1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Different nop operations are used by the code generator to detect certain 1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // states of the generated code. 1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch enum NopMarkerTypes { 1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DEBUG_BREAK_NOP, 1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch INTERRUPT_CODE_NOP, 1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ADR_FAR_NOP, 1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FIRST_NOP_MARKER = DEBUG_BREAK_NOP, 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LAST_NOP_MARKER = ADR_FAR_NOP 1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void nop(NopMarkerTypes n) { 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((FIRST_NOP_MARKER <= n) && (n <= LAST_NOP_MARKER)); 1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mov(Register::XRegFromCode(n), Register::XRegFromCode(n)); 1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP instructions. 1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move immediate to FP register. 1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmov(FPRegister fd, double imm); 1584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmov(FPRegister fd, float imm); 1585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move FP register to register. 1587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmov(Register rd, FPRegister fn); 1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move register to FP register. 1590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmov(FPRegister fd, Register rn); 1591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move FP register to FP register. 1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmov(FPRegister fd, FPRegister fn); 1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP add. 1596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP subtract. 1599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP multiply. 1602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP fused multiply and add. 1605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmadd(const FPRegister& fd, 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa); 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP fused multiply and subtract. 1611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmsub(const FPRegister& fd, 1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa); 1615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP fused multiply, add and negate. 1617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fnmadd(const FPRegister& fd, 1618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa); 1621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP fused multiply, subtract and negate. 1623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fnmsub(const FPRegister& fd, 1624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa); 1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP divide. 1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP maximum. 1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP minimum. 1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP maximum. 1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fmaxnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP minimum. 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fminnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); 1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP absolute. 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fabs(const FPRegister& fd, const FPRegister& fn); 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP negate. 1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fneg(const FPRegister& fd, const FPRegister& fn); 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP square root. 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fsqrt(const FPRegister& fd, const FPRegister& fn); 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP round to integer (nearest with ties to away). 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void frinta(const FPRegister& fd, const FPRegister& fn); 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP round to integer (toward minus infinity). 1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void frintm(const FPRegister& fd, const FPRegister& fn); 1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP round to integer (nearest with ties to even). 1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void frintn(const FPRegister& fd, const FPRegister& fn); 1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP round to integer (towards zero.) 1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void frintz(const FPRegister& fd, const FPRegister& fn); 1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP compare registers. 1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcmp(const FPRegister& fn, const FPRegister& fm); 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP compare immediate. 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcmp(const FPRegister& fn, double value); 1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP conditional compare. 1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fccmp(const FPRegister& fn, 1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StatusFlags nzcv, 1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond); 1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP conditional select. 1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcsel(const FPRegister& fd, 1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond); 1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Common FP Convert function 1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void FPConvertToInt(const Register& rd, 1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPIntegerConvertOp op); 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP convert between single and double precision. 1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcvt(const FPRegister& fd, const FPRegister& fn); 1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert FP to unsigned integer (nearest with ties to away). 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcvtau(const Register& rd, const FPRegister& fn); 1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert FP to signed integer (nearest with ties to away). 1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcvtas(const Register& rd, const FPRegister& fn); 1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert FP to unsigned integer (round towards -infinity). 1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcvtmu(const Register& rd, const FPRegister& fn); 1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert FP to signed integer (round towards -infinity). 1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcvtms(const Register& rd, const FPRegister& fn); 1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert FP to unsigned integer (nearest with ties to even). 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcvtnu(const Register& rd, const FPRegister& fn); 1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert FP to signed integer (nearest with ties to even). 1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcvtns(const Register& rd, const FPRegister& fn); 1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert FP to unsigned integer (round towards zero). 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcvtzu(const Register& rd, const FPRegister& fn); 1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert FP to signed integer (rounf towards zero). 1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void fcvtzs(const Register& rd, const FPRegister& fn); 1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert signed integer or fixed point to FP. 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0); 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert unsigned integer or fixed point to FP. 1718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0); 1719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Instruction functions used only for test, debug, and patching. 1721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit raw instructions in the instruction stream. 1722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dci(Instr raw_inst) { Emit(raw_inst); } 1723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit 8 bits of data in the instruction stream. 1725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dc8(uint8_t data) { EmitData(&data, sizeof(data)); } 1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit 32 bits of data in the instruction stream. 1728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dc32(uint32_t data) { EmitData(&data, sizeof(data)); } 1729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit 64 bits of data in the instruction stream. 1731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dc64(uint64_t data) { EmitData(&data, sizeof(data)); } 1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy a string into the instruction stream, including the terminating NULL 1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // character. The instruction pointer (pc_) is then aligned correctly for 1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // subsequent instructions. 1736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitStringData(const char* string); 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pseudo-instructions ------------------------------------------------------ 1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Parameters are described in arm64/instructions-arm64.h. 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void debug(const char* message, uint32_t code, Instr params = BREAK); 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Required by V8. 1744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void dd(uint32_t data) { dc32(data); } 1745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void db(uint8_t data) { dc8(data); } 1746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Code generation helpers -------------------------------------------------- 1748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool IsConstPoolEmpty() const { return constpool_.IsEmpty(); } 1750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* pc() const { return Instruction::Cast(pc_); } 1752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* InstructionAt(int offset) const { 1754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<Instruction*>(buffer_ + offset); 1755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ptrdiff_t InstructionOffset(Instruction* instr) const { 1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<byte*>(instr) - buffer_; 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register encoding. 1762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr Rd(CPURegister rd) { 1763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rd.code() != kSPRegInternalCode); 1764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return rd.code() << Rd_offset; 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr Rn(CPURegister rn) { 1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rn.code() != kSPRegInternalCode); 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return rn.code() << Rn_offset; 1770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr Rm(CPURegister rm) { 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rm.code() != kSPRegInternalCode); 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return rm.code() << Rm_offset; 1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr Ra(CPURegister ra) { 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(ra.code() != kSPRegInternalCode); 1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ra.code() << Ra_offset; 1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr Rt(CPURegister rt) { 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rt.code() != kSPRegInternalCode); 1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return rt.code() << Rt_offset; 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr Rt2(CPURegister rt2) { 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(rt2.code() != kSPRegInternalCode); 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return rt2.code() << Rt2_offset; 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // These encoding functions allow the stack pointer to be encoded, and 1793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // disallow the zero register. 1794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr RdSP(Register rd) { 1795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!rd.IsZero()); 1796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (rd.code() & kRegCodeMask) << Rd_offset; 1797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr RnSP(Register rn) { 1800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!rn.IsZero()); 1801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (rn.code() & kRegCodeMask) << Rn_offset; 1802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Flags encoding. 1805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr Flags(FlagsUpdate S); 1806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr Cond(Condition cond); 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // PC-relative address encoding. 1809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmPCRelAddress(int imm21); 1810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branch encoding. 1812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmUncondBranch(int imm26); 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmCondBranch(int imm19); 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmCmpBranch(int imm19); 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmTestBranch(int imm14); 1816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmTestBranchBit(unsigned bit_pos); 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Data Processing encoding. 1819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr SF(Register rd); 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmAddSub(int64_t imm); 1821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmS(unsigned imms, unsigned reg_size); 1822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmR(unsigned immr, unsigned reg_size); 1823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmSetBits(unsigned imms, unsigned reg_size); 1824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmRotate(unsigned immr, unsigned reg_size); 1825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmLLiteral(int imm19); 1826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr BitN(unsigned bitn, unsigned reg_size); 1827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ShiftDP(Shift shift); 1828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmDPShift(unsigned amount); 1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ExtendMode(Extend extend); 1830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmExtendShift(unsigned left_shift); 1831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmCondCmp(unsigned imm); 1832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr Nzcv(StatusFlags nzcv); 1833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsImmAddSub(int64_t immediate); 1835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsImmLogical(uint64_t value, 1836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned width, 1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned* n, 1838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned* imm_s, 1839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned* imm_r); 1840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // MemOperand offset encoding. 1842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmLSUnsigned(int imm12); 1843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmLS(int imm9); 1844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmLSPair(int imm7, LSDataSize size); 1845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmShiftLS(unsigned shift_amount); 1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmException(int imm16); 1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmSystemRegister(int imm15); 1848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmHint(int imm7); 1849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmBarrierDomain(int imm2); 1850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmBarrierType(int imm2); 1851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static LSDataSize CalcLSDataSize(LoadStoreOp op); 1852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsImmLSUnscaled(int64_t offset); 1854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsImmLSScaled(int64_t offset, LSDataSize size); 1855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Move immediates encoding. 1857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ImmMoveWide(uint64_t imm); 1858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr ShiftMoveWide(int64_t shift); 1859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP Immediates. 1861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr ImmFP32(float imm); 1862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static Instr ImmFP64(double imm); 1863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr FPScale(unsigned scale); 1864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FP register type. 1866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline static Instr FPType(FPRegister fd); 1867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Class for scoping postponing the constant pool generation. 1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class BlockConstPoolScope { 1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) { 1872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assem_->StartBlockConstPool(); 1873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~BlockConstPoolScope() { 1875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assem_->EndBlockConstPool(); 1876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler* assem_; 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope); 1882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if is time to emit a constant pool. 1885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckConstPool(bool force_emit, bool require_jump); 1886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate a constant pool of the correct size for the generated code. 1888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate); 1889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate the constant pool for the generated code. 1891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void PopulateConstantPool(ConstantPoolArray* constant_pool); 1892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns true if we should emit a veneer as soon as possible for a branch 1894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // which can at most reach to specified pc. 1895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool ShouldEmitVeneer(int max_reachable_pc, 1896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int margin = kVeneerDistanceMargin); 1897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool ShouldEmitVeneers(int margin = kVeneerDistanceMargin) { 1898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ShouldEmitVeneer(unresolved_branches_first_limit(), margin); 1899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The maximum code size generated for a veneer. Currently one branch 1902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instruction. This is for code size checking purposes, and can be extended 1903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in the future for example if we decide to add nops between the veneers. 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxVeneerCodeSize = 1 * kInstructionSize; 1905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordVeneerPool(int location_offset, int size); 1907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emits veneers for branches that are approaching their maximum range. 1908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If need_protection is true, the veneers are protected by a branch jumping 1909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // over the code. 1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitVeneers(bool force_emit, bool need_protection, 1911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int margin = kVeneerDistanceMargin); 1912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitVeneersGuard() { EmitPoolGuard(); } 1913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Checks whether veneers need to be emitted at this point. 1914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If force_emit is set, a veneer is generated for *all* unresolved branches. 1915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckVeneerPool(bool force_emit, bool require_jump, 1916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int margin = kVeneerDistanceMargin); 1917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class BlockPoolsScope { 1919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit BlockPoolsScope(Assembler* assem) : assem_(assem) { 1921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assem_->StartBlockPools(); 1922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~BlockPoolsScope() { 1924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assem_->EndBlockPools(); 1925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 1928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler* assem_; 1929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope); 1931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 1932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected: 1934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const; 1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadStore(const CPURegister& rt, 1937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& addr, 1938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStoreOp op); 1939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadStorePair(const CPURegister& rt, const CPURegister& rt2, 1941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& addr, LoadStorePairOp op); 1942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsImmLSPair(int64_t offset, LSDataSize size); 1943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Logical(const Register& rd, 1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LogicalOp op); 1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LogicalImmediate(const Register& rd, 1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned n, 1951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned imm_s, 1952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned imm_r, 1953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LogicalOp op); 1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ConditionalCompare(const Register& rn, 1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StatusFlags nzcv, 1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond, 1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalCompareOp op); 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsImmConditionalCompare(int64_t immediate); 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddSubWithCarry(const Register& rd, 1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsUpdate S, 1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubWithCarryOp op); 1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Functions for emulating operands not directly supported by the instruction 1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // set. 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitShift(const Register& rd, 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Shift shift, 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned amount); 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitExtendShift(const Register& rd, 1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Extend extend, 1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned left_shift); 1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void AddSub(const Register& rd, 1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsUpdate S, 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AddSubOp op); 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsImmFP32(float imm); 1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool IsImmFP64(double imm); 1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified 1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // registers. Only simple loads are supported; sign- and zero-extension (such 1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // as in LDPSW_x or LDRB_w) are not supported. 1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline LoadStoreOp LoadOpFor(const CPURegister& rt); 1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline LoadStorePairOp LoadPairOpFor(const CPURegister& rt, 1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& rt2); 1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline LoadStoreOp StoreOpFor(const CPURegister& rt); 1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline LoadStorePairOp StorePairOpFor(const CPURegister& rt, 1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& rt2); 1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline LoadStorePairNonTemporalOp LoadPairNonTemporalOpFor( 1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& rt, const CPURegister& rt2); 1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline LoadStorePairNonTemporalOp StorePairNonTemporalOpFor( 2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& rt, const CPURegister& rt2); 2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt); 2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove the specified branch from the unbound label link chain. 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If available, a veneer for this label can be used for other branches in the 2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // chain if the link chain cannot be fixed up without this branch. 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RemoveBranchFromLabelLinkChain(Instruction* branch, 2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* label, 2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instruction* label_veneer = NULL); 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Instruction helpers. 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void MoveWide(const Register& rd, 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t imm, 2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int shift, 2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MoveWideImmediateOp mov_op); 2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DataProcShiftedRegister(const Register& rd, 2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsUpdate S, 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr op); 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DataProcExtendedRegister(const Register& rd, 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Operand& operand, 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FlagsUpdate S, 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr op); 2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void LoadStorePairNonTemporal(const CPURegister& rt, 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const CPURegister& rt2, 2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const MemOperand& addr, 2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStorePairNonTemporalOp op); 2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void ConditionalSelect(const Register& rd, 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cond, 2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConditionalSelectOp op); 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DataProcessing1Source(const Register& rd, 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing1SourceOp op); 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DataProcessing3Source(const Register& rd, 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rn, 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& rm, 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const Register& ra, 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DataProcessing3SourceOp op); 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void FPDataProcessing1Source(const FPRegister& fd, 2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing1SourceOp op); 2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void FPDataProcessing2Source(const FPRegister& fd, 2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing2SourceOp op); 2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void FPDataProcessing3Source(const FPRegister& fd, 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fn, 2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fm, 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const FPRegister& fa, 2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FPDataProcessing3SourceOp op); 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Label helpers. 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return an offset for a label-referencing instruction, typically a branch. 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int LinkAndGetByteOffsetTo(Label* label); 2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is the same as LinkAndGetByteOffsetTo, but return an offset 2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // suitable for fields that take instruction offsets. 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline int LinkAndGetInstructionOffsetTo(Label* label); 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kStartOfLabelLinkChain = 0; 2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Verify that a label's link chain is intact. 2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckLabelLinkChain(Label const * label); 2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void RecordLiteral(int64_t imm, unsigned size); 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Postpone the generation of the constant pool for the specified number of 2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instructions. 2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void BlockConstPoolFor(int instructions); 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set how far from current pc the next constant pool check will be. 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetNextConstPoolCheckIn(int instructions) { 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch next_constant_pool_check_ = pc_offset() + instructions * kInstructionSize; 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the instruction at pc_. 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Emit(Instr instruction) { 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(*pc_) == 1); 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(sizeof(instruction) == kInstructionSize); 2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_)); 2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memcpy(pc_, &instruction, sizeof(instruction)); 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pc_ += sizeof(instruction); 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckBuffer(); 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit data inline in the instruction stream. 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void EmitData(void const * data, unsigned size) { 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(sizeof(*pc_) == 1); 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((pc_ + size) <= (buffer_ + buffer_size_)); 2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): Somehow register we have some data here. Then we can 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // disassemble it correctly. 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memcpy(pc_, data, size); 2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pc_ += size; 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CheckBuffer(); 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void GrowBuffer(); 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckBufferSpace(); 2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void CheckBuffer(); 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pc offset of the next constant pool check. 2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int next_constant_pool_check_; 2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constant pool generation 2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pools are emitted in the instruction stream. They are emitted when: 2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // * the distance to the first use is above a pre-defined distance or 2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // * the numbers of entries in the pool is above a pre-defined size or 2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // * code generation is finished 2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If a pool needs to be emitted before code generation is finished a branch 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // over the emitted pool will be inserted. 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constants in the pool may be addresses of functions that gets relocated; 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if so, a relocation info entry is associated to the constant pool entry. 2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Repeated checking whether the constant pool should be emitted is rather 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // expensive. By default we only check again once a number of instructions 2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // has been generated. That also means that the sizing of the buffers is not 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // an exact science, and that we rely on some slop to not overrun buffers. 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kCheckConstPoolInterval = 128; 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Distance to first use after a which a pool will be emitted. Pool entries 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // are accessed with pc relative load therefore this cannot be more than 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1 * MB. Since constant pool emission checks are interval based this value 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is an approximation. 2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kApproxMaxDistToConstPool = 64 * KB; 2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Number of pool entries after which a pool will be emitted. Since constant 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pool emission checks are interval based this value is an approximation. 2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kApproxMaxPoolEntryCount = 512; 2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emission of the constant pool may be blocked in some code sequences. 2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int const_pool_blocked_nesting_; // Block emission if this is not zero. 2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int no_const_pool_before_; // Block emission before this pc offset. 2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emission of the veneer pools may be blocked in some code sequences. 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int veneer_pool_blocked_nesting_; // Block emission if this is not zero. 2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Relocation info generation 2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Each relocation is encoded as a variable size value 2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfoWriter reloc_info_writer; 2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Relocation info records are also used during code generation as temporary 2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // containers for constants and code target addresses until they are emitted 2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to the constant pool. These pending relocation info records are temporarily 2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stored in a separate buffer until a constant pool is emitted. 2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If every instruction in a long sequence is accessing the pool, we need one 2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pending relocation entry per instruction. 2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The pending constant pool. 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConstPool constpool_; 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Relocation for a type-recording IC has the AST id added to it. This 2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // member variable is a way to pass the information from the call site to 2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the relocation info. 2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId recorded_ast_id_; 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline TypeFeedbackId RecordedAstId(); 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch inline void ClearRecordedAstId(); 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected: 2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record the AST id of the CallIC being compiled, so that it can be placed 2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in the relocation information. 2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetRecordedAstId(TypeFeedbackId ast_id) { 2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(recorded_ast_id_.IsNone()); 2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch recorded_ast_id_ = ast_id; 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Code generation 2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The relocation writer's position is at least kGap bytes below the end of 2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the generated instructions. This is so that multi-instruction sequences do 2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // not have to check for overflow. The same is true for writes of large 2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // relocation info entries, and debug strings encoded in the instruction 2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // stream. 2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kGap = 128; 2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch class FarBranchInfo { 2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FarBranchInfo(int offset, Label* label) 2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : pc_offset_(offset), label_(label) {} 2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Offset of the branch in the code generation buffer. 2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int pc_offset_; 2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The label branched to. 2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* label_; 2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch protected: 2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Information about unresolved (forward) branches. 2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The Assembler is only allowed to delete out-of-date information from here 2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // after a label is bound. The MacroAssembler uses this information to 2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // generate veneers. 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The second member gives information about the unresolved branch. The first 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // member of the pair is the maximum offset that the branch can reach in the 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // buffer. The map is sorted according to this reachable offset, allowing to 2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // easily check when veneers need to be emitted. 2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note that the maximum reachable offset (first member of the pairs) should 2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // always be positive but has the same type as the return value for 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // pc_offset() for convenience. 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::multimap<int, FarBranchInfo> unresolved_branches_; 2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We generate a veneer for a branch if we reach within this distance of the 2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // limit of the range. 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kVeneerDistanceMargin = 1 * KB; 2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The factor of 2 is a finger in the air guess. With a default margin of 2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1KB, that leaves us an addional 256 instructions to avoid generating a 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // protective branch. 2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kVeneerNoProtectionFactor = 2; 2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kVeneerDistanceCheckMargin = 2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kVeneerNoProtectionFactor * kVeneerDistanceMargin; 2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int unresolved_branches_first_limit() const { 2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!unresolved_branches_.empty()); 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return unresolved_branches_.begin()->first; 2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is similar to next_constant_pool_check_ and helps reduce the overhead 2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of checking for veneer pools. 2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It is maintained to the closest unresolved branch limit minus the maximum 2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // veneer margin (or kMaxInt if there are no unresolved branches). 2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int next_veneer_pool_check_; 2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If a veneer is emitted for a branch instruction, that instruction must be 2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // removed from the associated label's link chain so that the assembler does 2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // not later attempt (likely unsuccessfully) to patch it to branch directly to 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the label. 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeleteUnresolvedBranchInfoForLabel(Label* label); 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This function deletes the information related to the label by traversing 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the label chain, and for each PC-relative instruction in the chain checking 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if pending unresolved information exists. Its complexity is proportional to 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the length of the label chain. 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label); 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PositionsRecorder positions_recorder_; 2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class PositionsRecorder; 2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class EnsureSpace; 2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class ConstPool; 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass PatchingAssembler : public Assembler { 2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create an Assembler with a buffer starting at 'start'. 2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The buffer size is 2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // size of instructions to patch + kGap 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Where kGap is the distance from which the Assembler tries to grow the 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // buffer. 2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If more or fewer instructions than expected are generated or if some 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // relocation information takes space in the buffer, the PatchingAssembler 2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // will crash trying to grow the buffer. 2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PatchingAssembler(Instruction* start, unsigned count) 2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Assembler(NULL, 2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<byte*>(start), 2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch count * kInstructionSize + kGap) { 2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StartBlockPools(); 2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PatchingAssembler(byte* start, unsigned count) 2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Assembler(NULL, start, count * kInstructionSize + kGap) { 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Block constant pool emission. 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StartBlockPools(); 2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ~PatchingAssembler() { 2272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Const pool should still be blocked. 2273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_const_pool_blocked()); 2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EndBlockPools(); 2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Verify we have generated the number of instruction we expected. 2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((pc_offset() + kGap) == buffer_size_); 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Verify no relocation information has been emitted. 2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsConstPoolEmpty()); 2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Flush the Instruction cache. 2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t length = buffer_size_ - kGap; 2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CpuFeatures::FlushICache(buffer_, length); 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // See definition of PatchAdrFar() for details. 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kAdrFarPatchableNNops = 2; 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 2; 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void PatchAdrFar(int64_t target_offset); 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass EnsureSpace BASE_EMBEDDED { 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit EnsureSpace(Assembler* assembler) { 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch assembler->CheckBufferSpace(); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 2297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} } // namespace v8::internal 2299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_ARM64_ASSEMBLER_ARM64_H_ 2301