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