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