143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin/*
243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * Copyright (C) 2011 The Android Open Source Project
343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin *
443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * Licensed under the Apache License, Version 2.0 (the "License");
543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * you may not use this file except in compliance with the License.
643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * You may obtain a copy of the License at
743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin *
843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin *      http://www.apache.org/licenses/LICENSE-2.0
943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin *
1043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * Unless required by applicable law or agreed to in writing, software
1143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * distributed under the License is distributed on an "AS IS" BASIS,
1243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * See the License for the specific language governing permissions and
1443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * limitations under the License.
1543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin */
1643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
1743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin#include "codegen_arm64.h"
180b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe
190b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "arm64_lir.h"
200b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/logging.h"
2143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin#include "dex/quick/mir_to_lir-inl.h"
22b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h"
2343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
2443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchinnamespace art {
2543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
26e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin/* This file contains codegen for the A64 ISA. */
27e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
282eba1fa7e9e5f91e18ae3778d529520bd2c78d55Serban Constantinescuint32_t Arm64Mir2Lir::EncodeImmSingle(uint32_t bits) {
29e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  /*
30e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   * Valid values will have the form:
31e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   *
32e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   *   aBbb.bbbc.defg.h000.0000.0000.0000.0000
33e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   *
34e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   * where B = not(b). In other words, if b == 1, then B == 0 and viceversa.
35e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   */
36e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
37e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bits[19..0] are cleared.
38e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if ((bits & 0x0007ffff) != 0)
3943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    return -1;
40e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
41e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bits[29..25] are all set or all cleared.
42e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint32_t b_pattern = (bits >> 16) & 0x3e00;
43e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (b_pattern != 0 && b_pattern != 0x3e00)
44e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    return -1;
45e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
46e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bit[30] and bit[29] are opposite.
47e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (((bits ^ (bits << 1)) & 0x40000000) == 0)
48e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    return -1;
49e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
50e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000
51e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bit7: a000.0000
52e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint32_t bit7 = ((bits >> 31) & 0x1) << 7;
53e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bit6: 0b00.0000
54e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint32_t bit6 = ((bits >> 29) & 0x1) << 6;
55e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bit5_to_0: 00cd.efgh
56e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint32_t bit5_to_0 = (bits >> 19) & 0x3f;
57e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  return (bit7 | bit6 | bit5_to_0);
5843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
5943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
602eba1fa7e9e5f91e18ae3778d529520bd2c78d55Serban Constantinescuint32_t Arm64Mir2Lir::EncodeImmDouble(uint64_t bits) {
61e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  /*
62e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   * Valid values will have the form:
63e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   *
64e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   *   aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
65e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   *   0000.0000.0000.0000.0000.0000.0000.0000
66e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   *
67e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   * where B = not(b).
68e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin   */
69e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
70e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bits[47..0] are cleared.
71e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if ((bits & UINT64_C(0xffffffffffff)) != 0)
7243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    return -1;
73e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
74e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bits[61..54] are all set or all cleared.
75e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint32_t b_pattern = (bits >> 48) & 0x3fc0;
76e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (b_pattern != 0 && b_pattern != 0x3fc0)
77e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    return -1;
78e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
79e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bit[62] and bit[61] are opposite.
80e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (((bits ^ (bits << 1)) & UINT64_C(0x4000000000000000)) == 0)
81e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    return -1;
82e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
83e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bit7: a000.0000
84e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint32_t bit7 = ((bits >> 63) & 0x1) << 7;
85e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bit6: 0b00.0000
86e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint32_t bit6 = ((bits >> 61) & 0x1) << 6;
87e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bit5_to_0: 00cd.efgh
88e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint32_t bit5_to_0 = (bits >> 48) & 0x3f;
89e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  return (bit7 | bit6 | bit5_to_0);
9043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
9143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
9263999683329612292d534e6be09dbde9480f1250Serban Constantinescusize_t Arm64Mir2Lir::GetLoadStoreSize(LIR* lir) {
9363999683329612292d534e6be09dbde9480f1250Serban Constantinescu  bool opcode_is_wide = IS_WIDE(lir->opcode);
944163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = UNWIDE(lir->opcode);
9563999683329612292d534e6be09dbde9480f1250Serban Constantinescu  DCHECK(!IsPseudoLirOp(opcode));
964163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  const A64EncodingMap *encoder = &EncodingMap[opcode];
9763999683329612292d534e6be09dbde9480f1250Serban Constantinescu  uint32_t bits = opcode_is_wide ? encoder->xskeleton : encoder->wskeleton;
9863999683329612292d534e6be09dbde9480f1250Serban Constantinescu  return (bits >> 30);
9963999683329612292d534e6be09dbde9480f1250Serban Constantinescu}
10063999683329612292d534e6be09dbde9480f1250Serban Constantinescu
10163999683329612292d534e6be09dbde9480f1250Serban Constantinescusize_t Arm64Mir2Lir::GetInstructionOffset(LIR* lir) {
10263999683329612292d534e6be09dbde9480f1250Serban Constantinescu  size_t offset = lir->operands[2];
10363999683329612292d534e6be09dbde9480f1250Serban Constantinescu  uint64_t check_flags = GetTargetInstFlags(lir->opcode);
10463999683329612292d534e6be09dbde9480f1250Serban Constantinescu  DCHECK((check_flags & IS_LOAD) || (check_flags & IS_STORE));
10563999683329612292d534e6be09dbde9480f1250Serban Constantinescu  if (check_flags & SCALED_OFFSET_X0) {
10663999683329612292d534e6be09dbde9480f1250Serban Constantinescu    DCHECK(check_flags & IS_TERTIARY_OP);
10763999683329612292d534e6be09dbde9480f1250Serban Constantinescu    offset = offset * (1 << GetLoadStoreSize(lir));
10863999683329612292d534e6be09dbde9480f1250Serban Constantinescu  }
10963999683329612292d534e6be09dbde9480f1250Serban Constantinescu  return offset;
11063999683329612292d534e6be09dbde9480f1250Serban Constantinescu}
11163999683329612292d534e6be09dbde9480f1250Serban Constantinescu
112c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo FranchinLIR* Arm64Mir2Lir::LoadFPConstantValue(RegStorage r_dest, int32_t value) {
113c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  DCHECK(r_dest.IsSingle());
11443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  if (value == 0) {
115c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    return NewLIR2(kA64Fmov2sw, r_dest.GetReg(), rwzr);
11643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  } else {
117e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    int32_t encoded_imm = EncodeImmSingle((uint32_t)value);
11843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    if (encoded_imm >= 0) {
119c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      return NewLIR2(kA64Fmov2fI, r_dest.GetReg(), encoded_imm);
12043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    }
12143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
122e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
12343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  LIR* data_target = ScanLiteralPool(literal_list_, value, 0);
1242cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (data_target == nullptr) {
125f987927a68d0489970c1eca6a32fd02ca9913357Andreas Gampe    // Wide, as we need 8B alignment.
126f987927a68d0489970c1eca6a32fd02ca9913357Andreas Gampe    data_target = AddWideData(&literal_list_, value, 0);
12743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
128e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
1298dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
130e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  LIR* load_pc_rel = RawLIR(current_dalvik_offset_, kA64Ldr2fp,
131c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin                            r_dest.GetReg(), 0, 0, 0, 0, data_target);
13243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  AppendLIR(load_pc_rel);
13343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return load_pc_rel;
13443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
13543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
136c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo FranchinLIR* Arm64Mir2Lir::LoadFPConstantValueWide(RegStorage r_dest, int64_t value) {
137c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  DCHECK(r_dest.IsDouble());
138e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (value == 0) {
139c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    return NewLIR2(kA64Fmov2Sx, r_dest.GetReg(), rxzr);
140e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  } else {
141e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    int32_t encoded_imm = EncodeImmDouble(value);
142e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    if (encoded_imm >= 0) {
1434163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin      return NewLIR2(WIDE(kA64Fmov2fI), r_dest.GetReg(), encoded_imm);
14443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    }
145e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  }
146e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
147e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // No short form - load from the literal pool.
148e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  int32_t val_lo = Low32Bits(value);
149e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  int32_t val_hi = High32Bits(value);
150e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi);
1512cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (data_target == nullptr) {
152e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    data_target = AddWideData(&literal_list_, val_lo, val_hi);
153e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  }
154e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
1558dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
1564163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  LIR* load_pc_rel = RawLIR(current_dalvik_offset_, WIDE(kA64Ldr2fp),
157c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin                            r_dest.GetReg(), 0, 0, 0, 0, data_target);
158e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  AppendLIR(load_pc_rel);
159e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  return load_pc_rel;
16043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
16143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
162e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinstatic int CountLeadingZeros(bool is_wide, uint64_t value) {
163c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  return (is_wide) ? __builtin_clzll(value) : __builtin_clz((uint32_t)value);
164e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin}
165e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
166e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinstatic int CountTrailingZeros(bool is_wide, uint64_t value) {
167c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  return (is_wide) ? __builtin_ctzll(value) : __builtin_ctz((uint32_t)value);
168e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin}
169e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
170e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinstatic int CountSetBits(bool is_wide, uint64_t value) {
171e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  return ((is_wide) ?
172e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu          __builtin_popcountll(value) : __builtin_popcount((uint32_t)value));
173e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin}
174e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
175e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin/**
176e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @brief Try encoding an immediate in the form required by logical instructions.
177e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin *
178e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @param is_wide Whether @p value is a 64-bit (as opposed to 32-bit) value.
179e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @param value An integer to be encoded. This is interpreted as 64-bit if @p is_wide is true and as
180e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin *   32-bit if @p is_wide is false.
181e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @return A non-negative integer containing the encoded immediate or -1 if the encoding failed.
182e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @note This is the inverse of Arm64Mir2Lir::DecodeLogicalImmediate().
18343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin */
184e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinint Arm64Mir2Lir::EncodeLogicalImmediate(bool is_wide, uint64_t value) {
185e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  unsigned n, imm_s, imm_r;
186e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
187e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // Logical immediates are encoded using parameters n, imm_s and imm_r using
188e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // the following table:
189e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //
190e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //  N   imms    immr    size        S             R
191e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //  1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
192e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //  0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
193e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //  0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
194e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //  0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
195e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //  0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
196e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //  0  11110s  xxxxxr     2    UInt(s)       UInt(r)
197e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // (s bits must not be all set)
198e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //
199e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // A pattern is constructed of size bits, where the least significant S+1
200e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // bits are set. The pattern is rotated right by R, and repeated across a
201e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // 32 or 64-bit value, depending on destination register width.
202e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //
203e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // To test if an arbitary immediate can be encoded using this scheme, an
204e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // iterative algorithm is used.
205e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  //
206e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
207e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // 1. If the value has all set or all clear bits, it can't be encoded.
208e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (value == 0 || value == ~UINT64_C(0) ||
209e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      (!is_wide && (uint32_t)value == ~UINT32_C(0))) {
210e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    return -1;
211e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  }
212e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
213e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  unsigned lead_zero  = CountLeadingZeros(is_wide, value);
214e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  unsigned lead_one   = CountLeadingZeros(is_wide, ~value);
215e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  unsigned trail_zero = CountTrailingZeros(is_wide, value);
216e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  unsigned trail_one  = CountTrailingZeros(is_wide, ~value);
217e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  unsigned set_bits   = CountSetBits(is_wide, value);
218e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
219e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // The fixed bits in the immediate s field.
220e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // If width == 64 (X reg), start at 0xFFFFFF80.
221e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // If width == 32 (W reg), start at 0xFFFFFFC0, as the iteration for 64-bit
222e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // widths won't be executed.
223e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  unsigned width = (is_wide) ? 64 : 32;
224e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  int imm_s_fixed = (is_wide) ? -128 : -64;
225e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  int imm_s_mask = 0x3f;
226e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
227e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  for (;;) {
228e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // 2. If the value is two bits wide, it can be encoded.
229e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    if (width == 2) {
230e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      n = 0;
231e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      imm_s = 0x3C;
232e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      imm_r = (value & 3) - 1;
233e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      break;
234e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    }
235e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
236e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    n = (width == 64) ? 1 : 0;
237e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    imm_s = ((imm_s_fixed | (set_bits - 1)) & imm_s_mask);
238e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    if ((lead_zero + set_bits) == width) {
239e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      imm_r = 0;
240e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    } else {
241e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      imm_r = (lead_zero > 0) ? (width - trail_zero) : lead_one;
242e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    }
243e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
244e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // 3. If the sum of leading zeros, trailing zeros and set bits is
245e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    //    equal to the bit width of the value, it can be encoded.
246e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    if (lead_zero + trail_zero + set_bits == width) {
247e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      break;
248e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    }
249e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
250e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // 4. If the sum of leading ones, trailing ones and unset bits in the
251e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    //    value is equal to the bit width of the value, it can be encoded.
252e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    if (lead_one + trail_one + (width - set_bits) == width) {
253e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      break;
254e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    }
255e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
256e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // 5. If the most-significant half of the bitwise value is equal to
257e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    //    the least-significant half, return to step 2 using the
258e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    //    least-significant half of the value.
259e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    uint64_t mask = (UINT64_C(1) << (width >> 1)) - 1;
260e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    if ((value & mask) == ((value >> (width >> 1)) & mask)) {
261e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      width >>= 1;
262e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      set_bits >>= 1;
263e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      imm_s_fixed >>= 1;
264e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      continue;
265e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    }
266e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
267e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // 6. Otherwise, the value can't be encoded.
268e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    return -1;
269e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  }
270e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
271e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  return (n << 12 | imm_r << 6 | imm_s);
27243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
27343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
274c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// Maximum number of instructions to use for encoding the immediate.
275c763e350da562b0c6bebf10599588d4901140e45Matteo Franchinstatic const int max_num_ops_per_const_load = 2;
276c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin
277c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin/**
278c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * @brief Return the number of fast halfwords in the given uint64_t integer.
279c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * @details The input integer is split into 4 halfwords (bits 0-15, 16-31, 32-47, 48-63). The
280c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin *   number of fast halfwords (halfwords that are either 0 or 0xffff) is returned. See below for
281c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin *   a more accurate description.
282c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * @param value The input 64-bit integer.
283c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * @return Return @c retval such that (retval & 0x7) is the maximum between n and m, where n is
284c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin *   the number of halfwords with all bits unset (0) and m is the number of halfwords with all bits
285c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin *   set (0xffff). Additionally (retval & 0x8) is set when m > n.
286c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin */
287c763e350da562b0c6bebf10599588d4901140e45Matteo Franchinstatic int GetNumFastHalfWords(uint64_t value) {
288c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  unsigned int num_0000_halfwords = 0;
289c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  unsigned int num_ffff_halfwords = 0;
290c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  for (int shift = 0; shift < 64; shift += 16) {
291c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    uint16_t halfword = static_cast<uint16_t>(value >> shift);
292c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    if (halfword == 0)
293c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      num_0000_halfwords++;
294c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    else if (halfword == UINT16_C(0xffff))
295c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      num_ffff_halfwords++;
296c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  }
297c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  if (num_0000_halfwords >= num_ffff_halfwords) {
298c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    DCHECK_LE(num_0000_halfwords, 4U);
299c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    return num_0000_halfwords;
300c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  } else {
301c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    DCHECK_LE(num_ffff_halfwords, 4U);
302c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    return num_ffff_halfwords | 0x8;
303c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  }
304c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin}
305c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin
306c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// The InexpensiveConstantXXX variants below are used in the promotion algorithm to determine how a
307c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// constant is considered for promotion. If the constant is "inexpensive" then the promotion
308c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// algorithm will give it a low priority for promotion, even when it is referenced many times in
309c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// the code.
310c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin
3116a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersbool Arm64Mir2Lir::InexpensiveConstantInt(int32_t value ATTRIBUTE_UNUSED) {
312c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  // A 32-bit int can always be loaded with 2 instructions (and without using the literal pool).
313c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  // We therefore return true and give it a low priority for promotion.
314c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  return true;
31543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
31643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
31743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchinbool Arm64Mir2Lir::InexpensiveConstantFloat(int32_t value) {
31843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return EncodeImmSingle(value) >= 0;
31943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
32043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
32143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchinbool Arm64Mir2Lir::InexpensiveConstantLong(int64_t value) {
322c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  int num_slow_halfwords = 4 - (GetNumFastHalfWords(value) & 0x7);
323c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  if (num_slow_halfwords <= max_num_ops_per_const_load) {
324c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    return true;
325c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  }
326c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  return (EncodeLogicalImmediate(/*is_wide=*/true, value) >= 0);
32743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
32843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
32943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchinbool Arm64Mir2Lir::InexpensiveConstantDouble(int64_t value) {
33043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return EncodeImmDouble(value) >= 0;
33143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
33243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
333c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// The InexpensiveConstantXXX variants below are used to determine which A64 instructions to use
334c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// when one of the operands is an immediate (e.g. register version or immediate version of add).
335c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin
336c763e350da562b0c6bebf10599588d4901140e45Matteo Franchinbool Arm64Mir2Lir::InexpensiveConstantInt(int32_t value, Instruction::Code opcode) {
337c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  switch (opcode) {
338c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::IF_EQ:
339c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::IF_NE:
340c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::IF_LT:
341c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::IF_GE:
342c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::IF_GT:
343c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::IF_LE:
344c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::ADD_INT:
345c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::ADD_INT_2ADDR:
346c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::SUB_INT:
347c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::SUB_INT_2ADDR:
348c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    // The code below is consistent with the implementation of OpRegRegImm().
349c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    {
350b504d2f89fdd5c01816bcbad752797cb78de0e99buzbee      uint32_t abs_value = (value == INT_MIN) ? value : std::abs(value);
351c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      if (abs_value < 0x1000) {
352c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin        return true;
353c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      } else if ((abs_value & UINT64_C(0xfff)) == 0 && ((abs_value >> 12) < 0x1000)) {
354c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin        return true;
355c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      }
356c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      return false;
357c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    }
358c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::SHL_INT:
359c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::SHL_INT_2ADDR:
360c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::SHR_INT:
361c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::SHR_INT_2ADDR:
362c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::USHR_INT:
363c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::USHR_INT_2ADDR:
364c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    return true;
365c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::AND_INT:
366c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::AND_INT_2ADDR:
367c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::AND_INT_LIT16:
368c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::AND_INT_LIT8:
369c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::OR_INT:
370c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::OR_INT_2ADDR:
371c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::OR_INT_LIT16:
372c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::OR_INT_LIT8:
373c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::XOR_INT:
374c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::XOR_INT_2ADDR:
375c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::XOR_INT_LIT16:
376c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  case Instruction::XOR_INT_LIT8:
377c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    if (value == 0 || value == INT32_C(-1)) {
378c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      return true;
379c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    }
380c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    return (EncodeLogicalImmediate(/*is_wide=*/false, value) >= 0);
381c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  default:
382c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    return false;
383c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  }
384c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin}
385c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin
38643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin/*
387e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * Load a immediate using one single instruction when possible; otherwise
388e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * use a pair of movz and movk instructions.
38943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin *
39043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * No additional register clobbering operation performed. Use this version when
39143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * 1) r_dest is freshly returned from AllocTemp or
39243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * 2) The codegen is under fixed register usage
39343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin */
39443ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) {
39543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  LIR* res;
39643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
39743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  if (r_dest.IsFloat()) {
398c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    return LoadFPConstantValue(r_dest, value);
399c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  }
400c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
401c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  if (r_dest.Is64Bit()) {
402c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    return LoadConstantWide(r_dest, value);
40343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
40443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
405e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // Loading SP/ZR with an immediate is not supported.
406c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  DCHECK(!A64_REG_IS_SP(r_dest.GetReg()));
407c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  DCHECK(!A64_REG_IS_ZR(r_dest.GetReg()));
408e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
409e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // Compute how many movk, movz instructions are needed to load the value.
410e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint16_t high_bits = High16Bits(value);
411e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  uint16_t low_bits = Low16Bits(value);
412e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
413e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  bool low_fast = ((uint16_t)(low_bits + 1) <= 1);
414e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  bool high_fast = ((uint16_t)(high_bits + 1) <= 1);
415e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
416e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (LIKELY(low_fast || high_fast)) {
417e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // 1 instruction is enough to load the immediate.
418e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    if (LIKELY(low_bits == high_bits)) {
419e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // Value is either 0 or -1: we can just use wzr.
4204163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin      A64Opcode opcode = LIKELY(low_bits == 0) ? kA64Mov2rr : kA64Mvn2rr;
421e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      res = NewLIR2(opcode, r_dest.GetReg(), rwzr);
422e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    } else {
423e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      uint16_t uniform_bits, useful_bits;
424e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      int shift;
425e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
426e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      if (LIKELY(high_fast)) {
427e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        shift = 0;
428e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        uniform_bits = high_bits;
429e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        useful_bits = low_bits;
430e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      } else {
431e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        shift = 1;
432e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        uniform_bits = low_bits;
433e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        useful_bits = high_bits;
434e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      }
435e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
436e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      if (UNLIKELY(uniform_bits != 0)) {
437e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        res = NewLIR3(kA64Movn3rdM, r_dest.GetReg(), ~useful_bits, shift);
438e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      } else {
439e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        res = NewLIR3(kA64Movz3rdM, r_dest.GetReg(), useful_bits, shift);
440e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      }
441e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    }
442e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  } else {
443e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // movk, movz require 2 instructions. Try detecting logical immediates.
444e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    int log_imm = EncodeLogicalImmediate(/*is_wide=*/false, value);
445e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    if (log_imm >= 0) {
446e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      res = NewLIR3(kA64Orr3Rrl, r_dest.GetReg(), rwzr, log_imm);
447e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    } else {
448e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // Use 2 instructions.
449e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      res = NewLIR3(kA64Movz3rdM, r_dest.GetReg(), low_bits, 0);
450e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      NewLIR3(kA64Movk3rdM, r_dest.GetReg(), high_bits, 1);
451e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    }
45243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
453e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
45443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return res;
45543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
45643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
457c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin// TODO: clean up the names. LoadConstantWide() should really be LoadConstantNoClobberWide().
458c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo FranchinLIR* Arm64Mir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) {
459c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  if (r_dest.IsFloat()) {
460c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    return LoadFPConstantValueWide(r_dest, value);
461c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  }
462c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
463c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  DCHECK(r_dest.Is64Bit());
464c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
465c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  // Loading SP/ZR with an immediate is not supported.
466c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  DCHECK(!A64_REG_IS_SP(r_dest.GetReg()));
467c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  DCHECK(!A64_REG_IS_ZR(r_dest.GetReg()));
468c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
469c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  if (LIKELY(value == INT64_C(0) || value == INT64_C(-1))) {
470c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    // value is either 0 or -1: we can just use xzr.
4714163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin    A64Opcode opcode = LIKELY(value == 0) ? WIDE(kA64Mov2rr) : WIDE(kA64Mvn2rr);
472c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    return NewLIR2(opcode, r_dest.GetReg(), rxzr);
473c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  }
474c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
475c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  // At least one in value's halfwords is not 0x0, nor 0xffff: find out how many.
476c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  uint64_t uvalue = static_cast<uint64_t>(value);
477c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  int num_fast_halfwords = GetNumFastHalfWords(uvalue);
478c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  int num_slow_halfwords = 4 - (num_fast_halfwords & 0x7);
479c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  bool more_ffff_halfwords = (num_fast_halfwords & 0x8) != 0;
480c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
481c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  if (num_slow_halfwords > 1) {
482c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    // A single movz/movn is not enough. Try the logical immediate route.
483c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    int log_imm = EncodeLogicalImmediate(/*is_wide=*/true, value);
484c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    if (log_imm >= 0) {
485c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      return NewLIR3(WIDE(kA64Orr3Rrl), r_dest.GetReg(), rxzr, log_imm);
486c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    }
487c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  }
488c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
489c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  if (num_slow_halfwords <= max_num_ops_per_const_load) {
490c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    // We can encode the number using a movz/movn followed by one or more movk.
4914163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin    A64Opcode op;
492c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    uint16_t background;
493c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    LIR* res = nullptr;
494c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
495c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    // Decide whether to use a movz or a movn.
496c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    if (more_ffff_halfwords) {
497c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      op = WIDE(kA64Movn3rdM);
498c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      background = 0xffff;
499c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    } else {
500c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      op = WIDE(kA64Movz3rdM);
501c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      background = 0;
502c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    }
503c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
504c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    // Emit the first instruction (movz, movn).
505c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    int shift;
506c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    for (shift = 0; shift < 4; shift++) {
507c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      uint16_t halfword = static_cast<uint16_t>(uvalue >> (shift << 4));
508c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      if (halfword != background) {
509c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin        res = NewLIR3(op, r_dest.GetReg(), halfword ^ background, shift);
510c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin        break;
511c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      }
512c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    }
513c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
514c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    // Emit the movk instructions.
515c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    for (shift++; shift < 4; shift++) {
516c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      uint16_t halfword = static_cast<uint16_t>(uvalue >> (shift << 4));
517c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      if (halfword != background) {
518c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin        NewLIR3(WIDE(kA64Movk3rdM), r_dest.GetReg(), halfword, shift);
519c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin      }
520c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    }
521c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    return res;
522c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  }
523c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
524c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  // Use the literal pool.
525c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  int32_t val_lo = Low32Bits(value);
526c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  int32_t val_hi = High32Bits(value);
527c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi);
5282cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (data_target == nullptr) {
529c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin    data_target = AddWideData(&literal_list_, val_lo, val_hi);
530c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  }
531c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
532c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral);
533c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  LIR *res = RawLIR(current_dalvik_offset_, WIDE(kA64Ldr2rp),
534c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin                    r_dest.GetReg(), 0, 0, 0, 0, data_target);
535c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  AppendLIR(res);
536c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin  return res;
537c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin}
538c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin
53943ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpUnconditionalBranch(LIR* target) {
540e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  LIR* res = NewLIR1(kA64B1t, 0 /* offset to be patched  during assembly */);
54143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  res->target = target;
54243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return res;
54343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
54443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
54543ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target) {
546e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  LIR* branch = NewLIR2(kA64B2ct, ArmConditionEncoding(cc),
547e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin                        0 /* offset to be patched */);
54843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  branch->target = target;
54943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return branch;
55043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
55143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
55243ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpReg(OpKind op, RegStorage r_dest_src) {
5534163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
55443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  switch (op) {
55543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpBlx:
556e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Blr1x;
55743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
55843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    default:
55943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      LOG(FATAL) << "Bad opcode " << op;
56043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
56143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return NewLIR1(opcode, r_dest_src.GetReg());
56243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
56343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
564bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo FranchinLIR* Arm64Mir2Lir::OpRegRegShift(OpKind op, RegStorage r_dest_src1, RegStorage r_src2, int shift) {
5654163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode wide = (r_dest_src1.Is64Bit()) ? WIDE(0) : UNWIDE(0);
566bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  CHECK_EQ(r_dest_src1.Is64Bit(), r_src2.Is64Bit());
5674163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
568e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
569bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  switch (op) {
57043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpCmn:
571bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      opcode = kA64Cmn3rro;
57243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
57343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpCmp:
574bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      opcode = kA64Cmp3rro;
57543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
57643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpMov:
577e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Mov2rr;
57843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
57943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpMvn:
580e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Mvn2rr;
58143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
58243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpNeg:
583e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Neg3rro;
58443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
58543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpTst:
586e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Tst3rro;
58743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
58843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpRev:
58943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      DCHECK_EQ(shift, 0);
590e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // Binary, but rm is encoded twice.
591169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu      return NewLIR2(kA64Rev2rr | wide, r_dest_src1.GetReg(), r_src2.GetReg());
59243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpRevsh:
593e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // Binary, but rm is encoded twice.
594a3fe7422d7ce8bfb01f95decef45f91a44d39264Zheng Xu      NewLIR2(kA64Rev162rr | wide, r_dest_src1.GetReg(), r_src2.GetReg());
595a3fe7422d7ce8bfb01f95decef45f91a44d39264Zheng Xu      // "sxth r1, r2" is "sbfm r1, r2, #0, #15"
596a3fe7422d7ce8bfb01f95decef45f91a44d39264Zheng Xu      return NewLIR4(kA64Sbfm4rrdd | wide, r_dest_src1.GetReg(), r_dest_src1.GetReg(), 0, 15);
59743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOp2Byte:
598e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      DCHECK_EQ(shift, ENCODE_NO_SHIFT);
599e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // "sbfx r1, r2, #imm1, #imm2" is "sbfm r1, r2, #imm1, #(imm1 + imm2 - 1)".
600e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // For now we use sbfm directly.
601bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      return NewLIR4(kA64Sbfm4rrdd | wide, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 7);
60243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOp2Short:
603e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      DCHECK_EQ(shift, ENCODE_NO_SHIFT);
604e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // For now we use sbfm rather than its alias, sbfx.
605bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      return NewLIR4(kA64Sbfm4rrdd | wide, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 15);
60643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOp2Char:
607e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // "ubfx r1, r2, #imm1, #imm2" is "ubfm r1, r2, #imm1, #(imm1 + imm2 - 1)".
608e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // For now we use ubfm directly.
609e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      DCHECK_EQ(shift, ENCODE_NO_SHIFT);
610bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      return NewLIR4(kA64Ubfm4rrdd | wide, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 15);
61143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    default:
612ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu      return OpRegRegRegShift(op, r_dest_src1, r_dest_src1, r_src2, shift);
61343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
614e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
61543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  DCHECK(!IsPseudoLirOp(opcode));
61643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  if (EncodingMap[opcode].flags & IS_BINARY_OP) {
617e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    DCHECK_EQ(shift, ENCODE_NO_SHIFT);
618bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    return NewLIR2(opcode | wide, r_dest_src1.GetReg(), r_src2.GetReg());
61943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  } else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
6204163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin    A64EncodingKind kind = EncodingMap[opcode].field_loc[2].kind;
621bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    if (kind == kFmtShift) {
622bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      return NewLIR3(opcode | wide, r_dest_src1.GetReg(), r_src2.GetReg(), shift);
62343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    }
62443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
625e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
626e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  LOG(FATAL) << "Unexpected encoding operand count";
6272cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  return nullptr;
62843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
62943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
630cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng XuLIR* Arm64Mir2Lir::OpRegRegExtend(OpKind op, RegStorage r_dest_src1, RegStorage r_src2,
631cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu                                  A64RegExtEncodings ext, uint8_t amount) {
6324163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode wide = (r_dest_src1.Is64Bit()) ? WIDE(0) : UNWIDE(0);
6334163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
634f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith
635f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith  switch (op) {
636f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith    case kOpCmn:
637f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith      opcode = kA64Cmn3Rre;
638f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith      break;
639f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith    case kOpCmp:
640f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith      opcode = kA64Cmp3Rre;
641f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith      break;
642cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu    case kOpAdd:
643cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu      // Note: intentional fallthrough
644cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu    case kOpSub:
645cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu      return OpRegRegRegExtend(op, r_dest_src1, r_dest_src1, r_src2, ext, amount);
646f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith    default:
647f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith      LOG(FATAL) << "Bad Opcode: " << opcode;
64865b798ea10dd716c1bb3dda029f9bf255435af72Andreas Gampe      UNREACHABLE();
649f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith  }
650f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith
651f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith  DCHECK(!IsPseudoLirOp(opcode));
652f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith  if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
6534163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin    A64EncodingKind kind = EncodingMap[opcode].field_loc[2].kind;
654f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith    if (kind == kFmtExtend) {
655cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu      return NewLIR3(opcode | wide, r_dest_src1.GetReg(), r_src2.GetReg(),
656cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu                     EncodeExtend(ext, amount));
657f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith    }
658f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith  }
659f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith
660f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith  LOG(FATAL) << "Unexpected encoding operand count";
6612cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  return nullptr;
662f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith}
663f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith
66443ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) {
665f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith  /* RegReg operations with SP in first parameter need extended register instruction form.
666cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu   * Only CMN, CMP, ADD & SUB instructions are implemented.
667f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith   */
668baa7c88a34fdfd230a2a383c2e388945f4d907b6Zheng Xu  if (r_dest_src1 == rs_sp) {
669cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu    return OpRegRegExtend(op, r_dest_src1, r_src2, kA64Uxtx, 0);
670f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith  } else {
671f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith    return OpRegRegShift(op, r_dest_src1, r_src2, ENCODE_NO_SHIFT);
672f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith  }
67343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
67443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
6756a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan RogersLIR* Arm64Mir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset,
6766a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               MoveType move_type) {
6776a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(r_dest, r_base, offset, move_type);
67843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  UNIMPLEMENTED(FATAL);
6796a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNREACHABLE();
68043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
68143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
6826a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan RogersLIR* Arm64Mir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src,
6836a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                               MoveType move_type) {
6846a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(r_base, offset, r_src, move_type);
68543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  UNIMPLEMENTED(FATAL);
68643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return nullptr;
68743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
68843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
68943ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) {
6906a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(op, cc, r_dest, r_src);
691e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  LOG(FATAL) << "Unexpected use of OpCondRegReg for Arm64";
6926a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNREACHABLE();
69343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
69443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
695ed65c5e982705defdb597d94d1aa3f2997239c9bSerban ConstantinescuLIR* Arm64Mir2Lir::OpRegRegRegShift(OpKind op, RegStorage r_dest, RegStorage r_src1,
696ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu                                    RegStorage r_src2, int shift) {
6974163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
698e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
699bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  switch (op) {
70043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpAdd:
701e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Add4rrro;
70243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
70343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpSub:
704e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Sub4rrro;
70543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
706e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // case kOpRsub:
707e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    //   opcode = kA64RsubWWW;
708e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    //   break;
70943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpAdc:
710e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Adc3rrr;
71143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
71243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpAnd:
713e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64And4rrro;
71443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
71543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpXor:
716e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Eor4rrro;
71743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
71843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpMul:
719e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Mul3rrr;
72043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
72143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpDiv:
722e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Sdiv3rrr;
72343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
72443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpOr:
725e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Orr4rrro;
72643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
72743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpSbc:
728e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Sbc3rrr;
72943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
73043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpLsl:
731e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Lsl3rrr;
73243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
73343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpLsr:
734e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Lsr3rrr;
73543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
73643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpAsr:
737e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Asr3rrr;
73843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
73943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpRor:
740e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Ror3rrr;
74143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
74243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    default:
74343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      LOG(FATAL) << "Bad opcode: " << op;
74443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
74543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
746e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
747e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // The instructions above belong to two kinds:
748e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // - 4-operands instructions, where the last operand is a shift/extend immediate,
749e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  // - 3-operands instructions with no shift/extend.
7504163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode widened_opcode = r_dest.Is64Bit() ? WIDE(opcode) : opcode;
751ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu  CHECK_EQ(r_dest.Is64Bit(), r_src1.Is64Bit());
752ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu  CHECK_EQ(r_dest.Is64Bit(), r_src2.Is64Bit());
75343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  if (EncodingMap[opcode].flags & IS_QUAD_OP) {
7540955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    DCHECK(!IsExtendEncoding(shift));
755ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu    return NewLIR4(widened_opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg(), shift);
75643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  } else {
75743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
758e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    DCHECK_EQ(shift, ENCODE_NO_SHIFT);
759ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu    return NewLIR3(widened_opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg());
76043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
76143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
76243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
76347b31aa855379471c06735b738396fa76e7c1988Andreas GampeLIR* Arm64Mir2Lir::OpRegRegRegExtend(OpKind op, RegStorage r_dest, RegStorage r_src1,
76447b31aa855379471c06735b738396fa76e7c1988Andreas Gampe                                     RegStorage r_src2, A64RegExtEncodings ext, uint8_t amount) {
7654163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
76647b31aa855379471c06735b738396fa76e7c1988Andreas Gampe
76747b31aa855379471c06735b738396fa76e7c1988Andreas Gampe  switch (op) {
76847b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    case kOpAdd:
76947b31aa855379471c06735b738396fa76e7c1988Andreas Gampe      opcode = kA64Add4RRre;
77047b31aa855379471c06735b738396fa76e7c1988Andreas Gampe      break;
77147b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    case kOpSub:
77247b31aa855379471c06735b738396fa76e7c1988Andreas Gampe      opcode = kA64Sub4RRre;
77347b31aa855379471c06735b738396fa76e7c1988Andreas Gampe      break;
77447b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    default:
7752c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers      UNIMPLEMENTED(FATAL) << "Unimplemented opcode: " << op;
7762c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers      UNREACHABLE();
77747b31aa855379471c06735b738396fa76e7c1988Andreas Gampe  }
7784163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode widened_opcode = r_dest.Is64Bit() ? WIDE(opcode) : opcode;
77947b31aa855379471c06735b738396fa76e7c1988Andreas Gampe
78047b31aa855379471c06735b738396fa76e7c1988Andreas Gampe  if (r_dest.Is64Bit()) {
78147b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    CHECK(r_src1.Is64Bit());
78247b31aa855379471c06735b738396fa76e7c1988Andreas Gampe
78347b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    // dest determines whether the op is wide or not. Up-convert src2 when necessary.
78447b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    // Note: this is not according to aarch64 specifications, but our encoding.
78547b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    if (!r_src2.Is64Bit()) {
78647b31aa855379471c06735b738396fa76e7c1988Andreas Gampe      r_src2 = As64BitReg(r_src2);
78747b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    }
78847b31aa855379471c06735b738396fa76e7c1988Andreas Gampe  } else {
78947b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    CHECK(!r_src1.Is64Bit());
79047b31aa855379471c06735b738396fa76e7c1988Andreas Gampe    CHECK(!r_src2.Is64Bit());
79147b31aa855379471c06735b738396fa76e7c1988Andreas Gampe  }
79247b31aa855379471c06735b738396fa76e7c1988Andreas Gampe
79347b31aa855379471c06735b738396fa76e7c1988Andreas Gampe  // Sanity checks.
79447b31aa855379471c06735b738396fa76e7c1988Andreas Gampe  //    1) Amount is in the range 0..4
79547b31aa855379471c06735b738396fa76e7c1988Andreas Gampe  CHECK_LE(amount, 4);
79647b31aa855379471c06735b738396fa76e7c1988Andreas Gampe
79747b31aa855379471c06735b738396fa76e7c1988Andreas Gampe  return NewLIR4(widened_opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg(),
79847b31aa855379471c06735b738396fa76e7c1988Andreas Gampe                 EncodeExtend(ext, amount));
79947b31aa855379471c06735b738396fa76e7c1988Andreas Gampe}
80047b31aa855379471c06735b738396fa76e7c1988Andreas Gampe
80143ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) {
802ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu  return OpRegRegRegShift(op, r_dest, r_src1, r_src2, ENCODE_NO_SHIFT);
80343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
80443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
80543ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) {
806e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu  return OpRegRegImm64(op, r_dest, r_src1, static_cast<int64_t>(value));
807e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu}
808e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu
809e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng XuLIR* Arm64Mir2Lir::OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1, int64_t value) {
81043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  LIR* res;
81143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  bool neg = (value < 0);
812b504d2f89fdd5c01816bcbad752797cb78de0e99buzbee  uint64_t abs_value = (neg & !(value == LLONG_MIN)) ? -value : value;
8134163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
8144163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode alt_opcode = kA64Brk1d;
815c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  bool is_logical = false;
816bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  bool is_wide = r_dest.Is64Bit();
8174163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode wide = (is_wide) ? WIDE(0) : UNWIDE(0);
8189f975bfe091e9592a1b6b5b46d224ec04b1183b6Andreas Gampe  int info = 0;
81943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
820bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  switch (op) {
821e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case kOpLsl: {
822e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // "lsl w1, w2, #imm" is an alias of "ubfm w1, w2, #(-imm MOD 32), #(31-imm)"
8232d41a655f4f0e4b2178bbd7e93901a5ed6eae4a6Zheng Xu      // and "lsl x1, x2, #imm" of "ubfm x1, x2, #(-imm MOD 64), #(63-imm)".
824e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // For now, we just use ubfm directly.
8252d41a655f4f0e4b2178bbd7e93901a5ed6eae4a6Zheng Xu      int max_value = (is_wide) ? 63 : 31;
826e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      return NewLIR4(kA64Ubfm4rrdd | wide, r_dest.GetReg(), r_src1.GetReg(),
8272d41a655f4f0e4b2178bbd7e93901a5ed6eae4a6Zheng Xu                     (-value) & max_value, max_value - value);
828e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    }
82943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpLsr:
830e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      return NewLIR3(kA64Lsr3rrd | wide, r_dest.GetReg(), r_src1.GetReg(), value);
83143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpAsr:
832e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      return NewLIR3(kA64Asr3rrd | wide, r_dest.GetReg(), r_src1.GetReg(), value);
83343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpRor:
834e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // "ror r1, r2, #imm" is an alias of "extr r1, r2, r2, #imm".
835e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // For now, we just use extr directly.
836e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      return NewLIR4(kA64Extr4rrrd | wide, r_dest.GetReg(), r_src1.GetReg(), r_src1.GetReg(),
837e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin                     value);
83843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpAdd:
839e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      neg = !neg;
840fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers      FALLTHROUGH_INTENDED;
84143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpSub:
842e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      // Add and sub below read/write sp rather than xzr.
843e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      if (abs_value < 0x1000) {
844e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        opcode = (neg) ? kA64Add4RRdT : kA64Sub4RRdT;
845e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        return NewLIR4(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), abs_value, 0);
846e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      } else if ((abs_value & UINT64_C(0xfff)) == 0 && ((abs_value >> 12) < 0x1000)) {
847e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        opcode = (neg) ? kA64Add4RRdT : kA64Sub4RRdT;
848e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        return NewLIR4(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), abs_value >> 12, 1);
84943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      } else {
850903989dae724ec0b186ec98c2afd1e074ed41d4dVladimir Marko        alt_opcode = (op == kOpAdd) ? kA64Add4RRre : kA64Sub4RRre;
85147b31aa855379471c06735b738396fa76e7c1988Andreas Gampe        info = EncodeExtend(is_wide ? kA64Uxtx : kA64Uxtw, 0);
85243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      }
85343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
85443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpAdc:
855e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      alt_opcode = kA64Adc3rrr;
85643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
85743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpSbc:
858e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      alt_opcode = kA64Sbc3rrr;
85943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
86043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpOr:
861c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      is_logical = true;
862e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Orr3Rrl;
863e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      alt_opcode = kA64Orr4rrro;
86443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
86543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpAnd:
866c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      is_logical = true;
867e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64And3Rrl;
868e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      alt_opcode = kA64And4rrro;
86943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
87043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpXor:
871c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      is_logical = true;
872e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Eor3Rrl;
873e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      alt_opcode = kA64Eor4rrro;
87443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
87543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpMul:
87643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      // TUNING: power of 2, shift & add
877e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      alt_opcode = kA64Mul3rrr;
87843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
87943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    default:
88043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      LOG(FATAL) << "Bad opcode: " << op;
88143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
88243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
883c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  if (is_logical) {
884c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    int log_imm = EncodeLogicalImmediate(is_wide, value);
885c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    if (log_imm >= 0) {
886c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      return NewLIR3(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), log_imm);
887e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    } else {
888c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      // When the immediate is either 0 or ~0, the logical operation can be trivially reduced
889c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      // to a - possibly negated - assignment.
890c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      if (value == 0) {
891c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin        switch (op) {
892c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin          case kOpOr:
893c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin          case kOpXor:
894c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            // Or/Xor by zero reduces to an assignment.
895c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            return NewLIR2(kA64Mov2rr | wide, r_dest.GetReg(), r_src1.GetReg());
896c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin          default:
897c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            // And by zero reduces to a `mov rdest, xzr'.
898c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            DCHECK(op == kOpAnd);
899c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            return NewLIR2(kA64Mov2rr | wide, r_dest.GetReg(), (is_wide) ? rxzr : rwzr);
900c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin        }
901c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      } else if (value == INT64_C(-1)
902c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin                 || (!is_wide && static_cast<uint32_t>(value) == ~UINT32_C(0))) {
903c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin        switch (op) {
904c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin          case kOpAnd:
905c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            // And by -1 reduces to an assignment.
906c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            return NewLIR2(kA64Mov2rr | wide, r_dest.GetReg(), r_src1.GetReg());
907c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin          case kOpXor:
908c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            // Xor by -1 reduces to an `mvn rdest, rsrc'.
909c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            return NewLIR2(kA64Mvn2rr | wide, r_dest.GetReg(), r_src1.GetReg());
910c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin          default:
911c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            // Or by -1 reduces to a `mvn rdest, xzr'.
912c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            DCHECK(op == kOpOr);
913c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin            return NewLIR2(kA64Mvn2rr | wide, r_dest.GetReg(), (is_wide) ? rxzr : rwzr);
914c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin        }
915c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin      }
916e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    }
91743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
918c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin
919c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  RegStorage r_scratch;
920c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  if (is_wide) {
921c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    r_scratch = AllocTempWide();
922c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    LoadConstantWide(r_scratch, value);
923c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  } else {
924c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    r_scratch = AllocTemp();
925c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    LoadConstant(r_scratch, value);
926c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  }
927c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
928c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    res = NewLIR4(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg(), info);
929c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  else
930c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin    res = NewLIR3(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg());
931c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  FreeTemp(r_scratch);
932c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin  return res;
93343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
93443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
93543ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) {
936ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu  return OpRegImm64(op, r_dest_src1, static_cast<int64_t>(value));
937e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin}
938e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
939ed65c5e982705defdb597d94d1aa3f2997239c9bSerban ConstantinescuLIR* Arm64Mir2Lir::OpRegImm64(OpKind op, RegStorage r_dest_src1, int64_t value) {
9404163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode wide = (r_dest_src1.Is64Bit()) ? WIDE(0) : UNWIDE(0);
9414163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
9424163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode neg_opcode = kA64Brk1d;
943e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  bool shift;
94443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  bool neg = (value < 0);
945b504d2f89fdd5c01816bcbad752797cb78de0e99buzbee  uint64_t abs_value = (neg & !(value == LLONG_MIN)) ? -value : value;
946e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
947e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (LIKELY(abs_value < 0x1000)) {
948e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // abs_value is a 12-bit immediate.
949e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    shift = false;
950e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  } else if ((abs_value & UINT64_C(0xfff)) == 0 && ((abs_value >> 12) < 0x1000)) {
951e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    // abs_value is a shifted 12-bit immediate.
952e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    shift = true;
953e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    abs_value >>= 12;
954e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu  } else if (LIKELY(abs_value < 0x1000000 && (op == kOpAdd || op == kOpSub))) {
955e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    // Note: It is better to use two ADD/SUB instead of loading a number to a temp register.
956e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    // This works for both normal registers and SP.
957e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    // For a frame size == 0x2468, it will be encoded as:
958e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    //   sub sp, #0x2000
959e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    //   sub sp, #0x468
960e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    if (neg) {
961e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu      op = (op == kOpAdd) ? kOpSub : kOpAdd;
962e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    }
963e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    OpRegImm64(op, r_dest_src1, abs_value & (~INT64_C(0xfff)));
964e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    return OpRegImm64(op, r_dest_src1, abs_value & 0xfff);
965e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  } else {
966e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    RegStorage r_tmp;
967e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    LIR* res;
968e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    if (IS_WIDE(wide)) {
969e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu      r_tmp = AllocTempWide();
970e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu      res = LoadConstantWide(r_tmp, value);
971e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    } else {
972e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu      r_tmp = AllocTemp();
973e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu      res = LoadConstant(r_tmp, value);
974e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu    }
975e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    OpRegReg(op, r_dest_src1, r_tmp);
976e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    FreeTemp(r_tmp);
977e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    return res;
978e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  }
979e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
980bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  switch (op) {
98143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpAdd:
982e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      neg_opcode = kA64Sub4RRdT;
983e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Add4RRdT;
98443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
98543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpSub:
986e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      neg_opcode = kA64Add4RRdT;
987e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Sub4RRdT;
98843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
98943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kOpCmp:
990e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      neg_opcode = kA64Cmn3RdT;
991e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Cmp3RdT;
99243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
99343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    default:
994e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      LOG(FATAL) << "Bad op-kind in OpRegImm: " << op;
99543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
99643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
997e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
998e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (UNLIKELY(neg))
999e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    opcode = neg_opcode;
1000e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
1001e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  if (EncodingMap[opcode].flags & IS_QUAD_OP)
1002e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    return NewLIR4(opcode | wide, r_dest_src1.GetReg(), r_dest_src1.GetReg(), abs_value,
1003e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin                   (shift) ? 1 : 0);
1004e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  else
1005e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    return NewLIR3(opcode | wide, r_dest_src1.GetReg(), abs_value, (shift) ? 1 : 0);
100643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
100743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
1008e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinint Arm64Mir2Lir::EncodeShift(int shift_type, int amount) {
1009cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu  DCHECK_EQ(shift_type & 0x3, shift_type);
1010cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu  DCHECK_EQ(amount & 0x3f, amount);
1011c61b3c984c509d5f7c8eb71b853c81a34b5c28efMatteo Franchin  return ((shift_type & 0x3) << 7) | (amount & 0x3f);
1012e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin}
1013e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
1014e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinint Arm64Mir2Lir::EncodeExtend(int extend_type, int amount) {
1015cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu  DCHECK_EQ(extend_type & 0x7, extend_type);
1016cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu  DCHECK_EQ(amount & 0x7, amount);
1017e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  return  (1 << 6) | ((extend_type & 0x7) << 3) | (amount & 0x7);
1018e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin}
1019e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
1020e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinbool Arm64Mir2Lir::IsExtendEncoding(int encoded_value) {
1021e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  return ((1 << 6) & encoded_value) != 0;
102243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
102343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
102443ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest,
1025e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin                                   int scale, OpSize size) {
102643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  LIR* load;
10270955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin  int expected_scale = 0;
10284163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
10294b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe  r_base = Check64BitReg(r_base);
103063fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu
103163fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu  // TODO(Arm64): The sign extension of r_index should be carried out by using an extended
103263fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu  //   register offset load (rather than doing the sign extension in a separate instruction).
103363fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu  if (r_index.Is32Bit()) {
103463fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu    // Assemble: ``sxtw xN, wN''.
103563fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu    r_index = As64BitReg(r_index);
103663fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu    NewLIR4(WIDE(kA64Sbfm4rrdd), r_index.GetReg(), r_index.GetReg(), 0, 31);
103763fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu  }
103843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
103943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  if (r_dest.IsFloat()) {
10400955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    if (r_dest.IsDouble()) {
10410955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      DCHECK(size == k64 || size == kDouble);
10420955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 3;
10434163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin      opcode = WIDE(kA64Ldr4fXxG);
10440955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    } else {
10450955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      DCHECK(r_dest.IsSingle());
10460955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      DCHECK(size == k32 || size == kSingle);
10470955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 2;
10480955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      opcode = kA64Ldr4fXxG;
10490955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    }
10500955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin
10510955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    DCHECK(scale == 0 || scale == expected_scale);
10520955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    return NewLIR4(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(),
10530955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin                   (scale != 0) ? 1 : 0);
105443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
105543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
105643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  switch (size) {
1057e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case kDouble:
1058e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case kWord:
1059e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case k64:
10603c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      r_dest = Check64BitReg(r_dest);
10610955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      opcode = WIDE(kA64Ldr4rXxG);
10620955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 3;
10630955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      break;
106463fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu    case kReference:
1065f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe      r_dest = As32BitReg(r_dest);
1066f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe      FALLTHROUGH_INTENDED;
1067f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe    case kSingle:     // Intentional fall-through.
1068f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe    case k32:
10693c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      r_dest = Check32BitReg(r_dest);
1070e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Ldr4rXxG;
10710955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 2;
107243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
107343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kUnsignedHalf:
10744b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe      r_dest = Check32BitReg(r_dest);
1075e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Ldrh4wXxd;
10760955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 1;
107743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
107843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kSignedHalf:
10794b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe      r_dest = Check32BitReg(r_dest);
1080e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Ldrsh4rXxd;
10810955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 1;
108243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
108343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kUnsignedByte:
10844b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe      r_dest = Check32BitReg(r_dest);
1085e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Ldrb3wXx;
108643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
108743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kSignedByte:
10884b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe      r_dest = Check32BitReg(r_dest);
1089e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Ldrsb3rXx;
109043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
109143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    default:
109243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      LOG(FATAL) << "Bad size: " << size;
109343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
1094e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
10950955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin  if (UNLIKELY(expected_scale == 0)) {
10960955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    // This is a tertiary op (e.g. ldrb, ldrsb), it does not not support scale.
10970955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    DCHECK_NE(EncodingMap[UNWIDE(opcode)].flags & IS_TERTIARY_OP, 0U);
1098e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    DCHECK_EQ(scale, 0);
10990955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg());
1100e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  } else {
11010955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    DCHECK(scale == 0 || scale == expected_scale);
11020955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    load = NewLIR4(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(),
1103e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin                   (scale != 0) ? 1 : 0);
1104e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  }
110543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
110643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return load;
110743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
110843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
110943ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src,
1110e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin                                    int scale, OpSize size) {
1111e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  LIR* store;
11120955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin  int expected_scale = 0;
11134163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
11144b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe  r_base = Check64BitReg(r_base);
111563fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu
111663fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu  // TODO(Arm64): The sign extension of r_index should be carried out by using an extended
111763fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu  //   register offset store (rather than doing the sign extension in a separate instruction).
111863fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu  if (r_index.Is32Bit()) {
111963fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu    // Assemble: ``sxtw xN, wN''.
112063fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu    r_index = As64BitReg(r_index);
112163fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu    NewLIR4(WIDE(kA64Sbfm4rrdd), r_index.GetReg(), r_index.GetReg(), 0, 31);
112263fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu  }
112343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
112443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  if (r_src.IsFloat()) {
11250955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    if (r_src.IsDouble()) {
11260955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      DCHECK(size == k64 || size == kDouble);
11270955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 3;
11284163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin      opcode = WIDE(kA64Str4fXxG);
11290955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    } else {
11300955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      DCHECK(r_src.IsSingle());
11310955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      DCHECK(size == k32 || size == kSingle);
11320955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 2;
11330955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      opcode = kA64Str4fXxG;
11340955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    }
11350955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin
11360955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    DCHECK(scale == 0 || scale == expected_scale);
11370955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    return NewLIR4(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg(),
11380955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin                   (scale != 0) ? 1 : 0);
113943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
114043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
114143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  switch (size) {
1142e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case kDouble:     // Intentional fall-trough.
1143e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case kWord:       // Intentional fall-trough.
1144e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case k64:
11453c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      r_src = Check64BitReg(r_src);
11460955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      opcode = WIDE(kA64Str4rXxG);
11470955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 3;
1148e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      break;
1149255e014542b2180620230e4d9d6000ae06846bbdMatteo Franchin    case kReference:
1150f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe      r_src = As32BitReg(r_src);
1151f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe      FALLTHROUGH_INTENDED;
1152f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe    case kSingle:     // Intentional fall-trough.
1153f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe    case k32:
11543c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      r_src = Check32BitReg(r_src);
1155e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Str4rXxG;
11560955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 2;
115743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
115843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kUnsignedHalf:
115943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kSignedHalf:
11604b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe      r_src = Check32BitReg(r_src);
1161e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Strh4wXxd;
11620955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin      expected_scale = 1;
116343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
116443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kUnsignedByte:
116543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kSignedByte:
11664b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe      r_src = Check32BitReg(r_src);
1167e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Strb3wXx;
116843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
116943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    default:
117043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      LOG(FATAL) << "Bad size: " << size;
117143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
1172e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
11730955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin  if (UNLIKELY(expected_scale == 0)) {
11740955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    // This is a tertiary op (e.g. strb), it does not not support scale.
11750955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    DCHECK_NE(EncodingMap[UNWIDE(opcode)].flags & IS_TERTIARY_OP, 0U);
1176e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    DCHECK_EQ(scale, 0);
11770955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    store = NewLIR3(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg());
1178e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  } else {
11790955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin    store = NewLIR4(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg(),
11800955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin                    (scale != 0) ? 1 : 0);
1181e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  }
118243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
118343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return store;
118443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
118543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
118643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin/*
118743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * Load value from base + displacement.  Optionally perform null check
118843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * on base (which must have an associated s_reg and MIR).  If not
118943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * performing null check, incoming MIR can be null.
119043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin */
119143ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest,
11923bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko                                    OpSize size) {
11932cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  LIR* load = nullptr;
11944163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
11954163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode alt_opcode = kA64Brk1d;
1196bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  int scale = 0;
1197bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin
119843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  switch (size) {
1199e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case kDouble:     // Intentional fall-through.
1200e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case kWord:       // Intentional fall-through.
120143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case k64:
12023c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      r_dest = Check64BitReg(r_dest);
1203bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      scale = 3;
120443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      if (r_dest.IsFloat()) {
1205bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin        DCHECK(r_dest.IsDouble());
12064163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin        opcode = WIDE(kA64Ldr3fXD);
12074163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin        alt_opcode = WIDE(kA64Ldur3fXd);
1208e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      } else {
12090955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin        opcode = WIDE(kA64Ldr3rXD);
12100955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin        alt_opcode = WIDE(kA64Ldur3rXd);
121143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      }
121243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
1213255e014542b2180620230e4d9d6000ae06846bbdMatteo Franchin    case kReference:
1214f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe      r_dest = As32BitReg(r_dest);
1215f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe      FALLTHROUGH_INTENDED;
1216f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe    case kSingle:     // Intentional fall-through.
1217f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe    case k32:
12183c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      r_dest = Check32BitReg(r_dest);
1219bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      scale = 2;
122043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      if (r_dest.IsFloat()) {
1221bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin        DCHECK(r_dest.IsSingle());
1222e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        opcode = kA64Ldr3fXD;
1223bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      } else {
1224e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        opcode = kA64Ldr3rXD;
122543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      }
122643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
122743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kUnsignedHalf:
1228bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      scale = 1;
1229bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      opcode = kA64Ldrh3wXF;
123043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
123143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kSignedHalf:
1232bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      scale = 1;
1233e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Ldrsh3rXF;
123443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
123543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kUnsignedByte:
1236e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Ldrb3wXd;
123743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
123843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kSignedByte:
1239e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Ldrsb3rXd;
124043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
124143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    default:
124243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      LOG(FATAL) << "Bad size: " << size;
124343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
124443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
1245bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  bool displacement_is_aligned = (displacement & ((1 << scale) - 1)) == 0;
1246bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  int scaled_disp = displacement >> scale;
1247bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  if (displacement_is_aligned && scaled_disp >= 0 && scaled_disp < 4096) {
1248bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    // Can use scaled load.
1249bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), scaled_disp);
1250bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  } else if (alt_opcode != kA64Brk1d && IS_SIGNED_IMM9(displacement)) {
1251bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    // Can use unscaled load.
1252bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    load = NewLIR3(alt_opcode, r_dest.GetReg(), r_base.GetReg(), displacement);
1253e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  } else {
1254bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    // Use long sequence.
125533ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee    // TODO: cleaner support for index/displacement registers?  Not a reference, but must match width.
125633ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee    RegStorage r_scratch = AllocTempWide();
125733ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee    LoadConstantWide(r_scratch, displacement);
1258582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe    load = LoadBaseIndexed(r_base, r_scratch,
1259582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe                           (size == kReference) ? As64BitReg(r_dest) : r_dest,
1260582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe                           0, size);
1261bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    FreeTemp(r_scratch);
126243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
126343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
126443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  // TODO: in future may need to differentiate Dalvik accesses w/ spills
12658dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  if (mem_ref_type_ == ResourceMask::kDalvikReg) {
1266b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers    DCHECK_EQ(r_base, rs_sp);
126743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, r_dest.Is64Bit());
126843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
126943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return load;
127043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
127143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
12723c12c512faf6837844d5465b23b9410889e5eb11Andreas GampeLIR* Arm64Mir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest,
12733c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe                                OpSize size, VolatileKind is_volatile) {
1274674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  // LoadBaseDisp() will emit correct insn for atomic load on arm64
1275674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  // assuming r_dest is correctly prepared using RegClassForFieldLoadStore().
127643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
12773c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  LIR* load = LoadBaseDispBody(r_base, displacement, r_dest, size);
12783c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
12793c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  if (UNLIKELY(is_volatile == kVolatile)) {
128048f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    // TODO: This should generate an acquire load instead of the barrier.
128148f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    GenMemBarrier(kLoadAny);
12823c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  }
12833c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
12843c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  return load;
12852689fbad6b5ec1ae8f8c8791a80c6fd3cf24144dAndreas Gampe}
128643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
128743ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src,
1288e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin                                     OpSize size) {
12892cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  LIR* store = nullptr;
12904163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode opcode = kA64Brk1d;
12914163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin  A64Opcode alt_opcode = kA64Brk1d;
1292bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  int scale = 0;
1293bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin
129443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  switch (size) {
1295e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case kDouble:     // Intentional fall-through.
1296e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    case kWord:       // Intentional fall-through.
129743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case k64:
12983c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      r_src = Check64BitReg(r_src);
1299bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      scale = 3;
1300e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      if (r_src.IsFloat()) {
1301bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin        DCHECK(r_src.IsDouble());
13024163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin        opcode = WIDE(kA64Str3fXD);
13034163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin        alt_opcode = WIDE(kA64Stur3fXd);
130443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      } else {
13054163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin        opcode = WIDE(kA64Str3rXD);
13064163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin        alt_opcode = WIDE(kA64Stur3rXd);
130743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      }
130843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
1309255e014542b2180620230e4d9d6000ae06846bbdMatteo Franchin    case kReference:
1310f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe      r_src = As32BitReg(r_src);
1311f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe      FALLTHROUGH_INTENDED;
1312f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe    case kSingle:     // Intentional fall-through.
1313f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe    case k32:
13143c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe      r_src = Check32BitReg(r_src);
1315bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      scale = 2;
131643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      if (r_src.IsFloat()) {
131743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin        DCHECK(r_src.IsSingle());
1318e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        opcode = kA64Str3fXD;
1319bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      } else {
1320e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin        opcode = kA64Str3rXD;
132143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      }
132243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
132343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kUnsignedHalf:
132443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kSignedHalf:
1325bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin      scale = 1;
1326e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Strh3wXF;
132743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
132843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kUnsignedByte:
132943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    case kSignedByte:
1330e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin      opcode = kA64Strb3wXd;
133143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      break;
133243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    default:
133343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin      LOG(FATAL) << "Bad size: " << size;
133443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
1335e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin
1336bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  bool displacement_is_aligned = (displacement & ((1 << scale) - 1)) == 0;
1337bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  int scaled_disp = displacement >> scale;
1338bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  if (displacement_is_aligned && scaled_disp >= 0 && scaled_disp < 4096) {
1339bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    // Can use scaled store.
1340bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    store = NewLIR3(opcode, r_src.GetReg(), r_base.GetReg(), scaled_disp);
1341bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  } else if (alt_opcode != kA64Brk1d && IS_SIGNED_IMM9(displacement)) {
1342bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    // Can use unscaled store.
1343bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    store = NewLIR3(alt_opcode, r_src.GetReg(), r_base.GetReg(), displacement);
1344e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  } else {
1345bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin    // Use long sequence.
134633ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee    RegStorage r_scratch = AllocTempWide();
134733ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee    LoadConstantWide(r_scratch, displacement);
1348582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe    store = StoreBaseIndexed(r_base, r_scratch,
1349582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe                             (size == kReference) ? As64BitReg(r_src) : r_src,
1350582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe                             0, size);
1351e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin    FreeTemp(r_scratch);
135243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
135343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
1354bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin  // TODO: In future, may need to differentiate Dalvik & spill accesses.
13558dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko  if (mem_ref_type_ == ResourceMask::kDalvikReg) {
1356b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers    DCHECK_EQ(r_base, rs_sp);
135743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin    AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, r_src.Is64Bit());
135843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  }
135943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin  return store;
136043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
136143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
13623c12c512faf6837844d5465b23b9410889e5eb11Andreas GampeLIR* Arm64Mir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src,
13633c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe                                 OpSize size, VolatileKind is_volatile) {
136448f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm  // TODO: This should generate a release store and no barriers.
13653c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  if (UNLIKELY(is_volatile == kVolatile)) {
136648f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    // Ensure that prior accesses become visible to other threads first.
136748f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    GenMemBarrier(kAnyStore);
13683c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  }
13693c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
1370674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  // StoreBaseDisp() will emit correct insn for atomic store on arm64
1371674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko  // assuming r_dest is correctly prepared using RegClassForFieldLoadStore().
13723c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
13733c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  LIR* store = StoreBaseDispBody(r_base, displacement, r_src, size);
13743c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
13753c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  if (UNLIKELY(is_volatile == kVolatile)) {
137648f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    // Preserve order with respect to any subsequent volatile loads.
137748f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    // We need StoreLoad, but that generally requires the most expensive barrier.
137848f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm    GenMemBarrier(kAnyAny);
13793c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  }
13803c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe
13813c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe  return store;
1382674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko}
1383674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko
138443ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) {
13856a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(r_dest, r_src);
1386e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  LOG(FATAL) << "Unexpected use of OpFpRegCopy for Arm64";
13876a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNREACHABLE();
138843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
138943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
139043ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) {
13916a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNUSED(op, r_base, disp);
1392e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin  LOG(FATAL) << "Unexpected use of OpMem for Arm64";
13936a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  UNREACHABLE();
139443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
139543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
13966a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan RogersLIR* Arm64Mir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt,
13976a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                                    QuickEntrypointEnum trampoline ATTRIBUTE_UNUSED) {
13986a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  // The address of the trampoline is already loaded into r_tgt.
1399984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe  return OpReg(op, r_tgt);
140043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}
140143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin
140243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin}  // namespace art
1403