1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2013 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_ARM64 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define ARM64_DEFINE_FP_STATICS 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/assembler-arm64-inl.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm64/instructions-arm64.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Instruction::IsLoad() const { 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) { 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) { 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Mask(LoadStorePairLBit) != 0; 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreOpMask)); 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDRB_w: 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDRH_w: 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDR_w: 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDR_x: 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDRSB_w: 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDRSB_x: 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDRSH_w: 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDRSH_x: 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDRSW_x: 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDR_s: 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDR_d: return true; 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return false; 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Instruction::IsStore() const { 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) { 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) { 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Mask(LoadStorePairLBit) == 0; 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreOpMask)); 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STRB_w: 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STRH_w: 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STR_w: 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STR_x: 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STR_s: 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STR_d: return true; 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return false; 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic uint64_t RotateRight(uint64_t value, 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned int rotate, 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned int width) { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(width <= 64); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rotate &= 63; 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) | 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (value >> rotate); 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic uint64_t RepeatBitsAcrossReg(unsigned reg_size, 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t value, 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned width) { 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((width == 2) || (width == 4) || (width == 8) || (width == 16) || 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (width == 32)); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((reg_size == kWRegSizeInBits) || (reg_size == kXRegSizeInBits)); 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t result = value & ((1UL << width) - 1UL); 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (unsigned i = width; i < reg_size; i *= 2) { 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result |= (result << i); 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Logical immediates can't encode zero, so a return value of zero is used to 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// indicate a failure case. Specifically, where the constraints on imm_s are not 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// met. 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochuint64_t Instruction::ImmLogical() { 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned reg_size = SixtyFourBits() ? kXRegSizeInBits : kWRegSizeInBits; 94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t n = BitN(); 95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t imm_s = ImmSetBits(); 96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t imm_r = ImmRotate(); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // An integer is constructed from the n, imm_s and imm_r bits according to 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the following table: 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // N imms immr size S R 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0 11110s xxxxxr 2 UInt(s) UInt(r) 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (s bits must not be all set) 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // A pattern is constructed of size bits, where the least significant S+1 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bits are set. The pattern is rotated right by R, and repeated across a 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 32 or 64-bit value, depending on destination register width. 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (n == 1) { 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (imm_s == 0x3F) { 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t bits = (1UL << (imm_s + 1)) - 1; 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return RotateRight(bits, imm_r, 64); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((imm_s >> 1) == 0x1F) { 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int width = 0x20; width >= 0x2; width >>= 1) { 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((imm_s & width) == 0) { 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mask = width - 1; 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((imm_s & mask) == mask) { 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t bits = (1UL << ((imm_s & mask) + 1)) - 1; 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return RepeatBitsAcrossReg(reg_size, 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RotateRight(bits, imm_r & mask, width), 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch width); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochfloat Instruction::ImmFP32() { 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ImmFP: abcdefgh (8 bits) 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits) 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // where B is b ^ 1 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bits = ImmFP(); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bit7 = (bits >> 7) & 0x1; 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bit6 = (bits >> 6) & 0x1; 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bit5_to_0 = bits & 0x3f; 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return rawbits_to_float(result); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble Instruction::ImmFP64() { 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ImmFP: abcdefgh (8 bits) 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 0000.0000.0000.0000.0000.0000.0000.0000 (64 bits) 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // where B is b ^ 1 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t bits = ImmFP(); 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t bit7 = (bits >> 7) & 0x1; 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t bit6 = (bits >> 6) & 0x1; 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t bit5_to_0 = bits & 0x3f; 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48); 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return rawbits_to_double(result); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochLSDataSize CalcLSPairDataSize(LoadStorePairOp op) { 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STP_x: 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDP_x: 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case STP_d: 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case LDP_d: return LSDoubleWord; 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return LSWord; 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint64_t Instruction::ImmPCOffset() { 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t offset; 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsPCRelAddressing()) { 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // PC-relative addressing. Only ADR is supported. 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset = ImmPCRel(); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (BranchType() != UnknownBranchType) { 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // All PC-relative branches. 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Relative branch offsets are instruction-size-aligned. 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset = ImmBranch() << kInstructionSizeLog2; 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (IsUnresolvedInternalReference()) { 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Internal references are always word-aligned. 194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch offset = ImmUnresolvedInternalReference() << kInstructionSizeLog2; 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load literal (offset from PC). 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsLdrLiteral()); 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The offset is always shifted by 2 bits, even for loads to 64-bits 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // registers. 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset = ImmLLiteral() << kInstructionSizeLog2; 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return offset; 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochInstruction* Instruction::ImmPCOffsetTarget() { 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return InstructionAtOffset(ImmPCOffset()); 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Instruction::IsValidImmPCOffset(ImmBranchType branch_type, 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ptrdiff_t offset) { 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return is_intn(offset, ImmBranchRangeBitwidth(branch_type)); 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Instruction::IsTargetInImmPCOffsetRange(Instruction* target) { 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return IsValidImmPCOffset(BranchType(), DistanceTo(target)); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Instruction::SetImmPCOffsetTarget(Isolate* isolate, Instruction* target) { 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsPCRelAddressing()) { 224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetPCRelImmTarget(isolate, target); 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (BranchType() != UnknownBranchType) { 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetBranchImmTarget(target); 227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else if (IsUnresolvedInternalReference()) { 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetUnresolvedInternalReferenceImmTarget(isolate, target); 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Load literal (offset from PC). 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetImmLLiteral(target); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Instruction::SetPCRelImmTarget(Isolate* isolate, Instruction* target) { 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ADRP is not supported, so 'this' must point to an ADR instruction. 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsAdr()); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ptrdiff_t target_offset = DistanceTo(target); 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr imm; 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Instruction::IsValidPCRelOffset(target_offset)) { 243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch imm = Assembler::ImmPCRelAddress(static_cast<int>(target_offset)); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInstructionBits(Mask(~ImmPCRel_mask) | imm); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PatchingAssembler patcher(isolate, this, 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PatchingAssembler::kAdrFarPatchableNInstrs); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.PatchAdrFar(target_offset); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Instruction::SetBranchImmTarget(Instruction* target) { 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsAligned(DistanceTo(target), kInstructionSize)); 255014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(IsValidImmPCOffset(BranchType(), 256014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DistanceTo(target) >> kInstructionSizeLog2)); 257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int offset = static_cast<int>(DistanceTo(target) >> kInstructionSizeLog2); 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr branch_imm = 0; 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint32_t imm_mask = 0; 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (BranchType()) { 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CondBranchType: { 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch branch_imm = Assembler::ImmCondBranch(offset); 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm_mask = ImmCondBranch_mask; 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case UncondBranchType: { 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch branch_imm = Assembler::ImmUncondBranch(offset); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm_mask = ImmUncondBranch_mask; 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case CompareBranchType: { 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch branch_imm = Assembler::ImmCmpBranch(offset); 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm_mask = ImmCmpBranch_mask; 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case TestBranchType: { 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch branch_imm = Assembler::ImmTestBranch(offset); 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch imm_mask = ImmTestBranch_mask; 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: UNREACHABLE(); 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInstructionBits(Mask(~imm_mask) | branch_imm); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Instruction::SetUnresolvedInternalReferenceImmTarget(Isolate* isolate, 288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Instruction* target) { 289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(IsUnresolvedInternalReference()); 290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(IsAligned(DistanceTo(target), kInstructionSize)); 291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(is_int32(DistanceTo(target) >> kInstructionSizeLog2)); 292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int32_t target_offset = 293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<int32_t>(DistanceTo(target) >> kInstructionSizeLog2); 294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint32_t high16 = unsigned_bitextract_32(31, 16, target_offset); 295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uint32_t low16 = unsigned_bitextract_32(15, 0, target_offset); 296014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PatchingAssembler patcher(isolate, this, 2); 298014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch patcher.brk(high16); 299014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch patcher.brk(low16); 300014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 301014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Instruction::SetImmLLiteral(Instruction* source) { 304014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(IsLdrLiteral()); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsAligned(DistanceTo(source), kInstructionSize)); 306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(Assembler::IsImmLLiteral(DistanceTo(source))); 307014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Instr imm = Assembler::ImmLLiteral( 308014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<int>(DistanceTo(source) >> kLoadLiteralScaleLog2)); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr mask = ImmLLiteral_mask; 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetInstructionBits(Mask(~mask) | imm); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(jbramley): We can't put this inline in the class because things like 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// xzr and Register are not defined in that header. Consider adding 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// instructions-arm64-inl.h to work around this. 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool InstructionSequence::IsInlineData() const { 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inline data is encoded as a single movz instruction which writes to xzr 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (x31). 321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return IsMovz() && SixtyFourBits() && (Rd() == kZeroRegCode); 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): If we extend ::InlineData() to support bigger data, we need 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to update this method too. 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(jbramley): We can't put this inline in the class because things like 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// xzr and Register are not defined in that header. Consider adding 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// instructions-arm64-inl.h to work around this. 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochuint64_t InstructionSequence::InlineData() const { 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsInlineData()); 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t payload = ImmMoveWide(); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(all): If we extend ::InlineData() to support bigger data, we need 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to update this method too. 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return payload; 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 339014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_ARM64 343